I have been working on project for some time now and I was able to add migrations without problem but week or two ago i transitioned from using onconfiguring optionsbuilder.useSqlServer to connect to sql server from my context class to using services from Startup class to connect to database
When I try to run add-migration i get this error
Unable to create an object of type 'mojDbContext'. For the different patterns supported at design time
Program class
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
startup class
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<mojDbContext>(options=> options.UseSqlServer(Configuration.GetConnectionString("ererer")));
services.AddControllersWithViews();
services.AddMvc();
services.AddDistributedMemoryCache();
services.AddSession();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseSession();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
my context class with removed dbset properties to keep code smaller
public class mojDbContext : DbContext
{
public mojDbContext(DbContextOptions<mojDbContext> options)
: base(options)
{
}
}
when i run add-migration -verbose i get this
https://i.stack.imgur.com/Rn7Op.png
Related
I have an ASP.NET project and everything is returning a 404, here's my startup code
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
else
app.UseExceptionHandler("/Home/Error");
app.UseStaticFiles();
app.UseAuthentication();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapGet("/debug/routes", async ctx =>
{
await ctx.Response.WriteAsync(string.Join(", ", endpoints.DataSources.SelectMany(x => x.Endpoints)));
});
});
}
}
here's a sample controller:
public class Home : Controller
{
private readonly DatabaseContext _databaseContext;
public Home(DatabaseContext databaseContext)
{
Console.WriteLine($"Initialized home controller"); // This doesn't get called at all.
_databaseContext = databaseContext;
_databaseContext.Database.EnsureCreated();
}
[HttpGet("/home")]
public IActionResult Index()
{
ViewData["Products"] = _databaseContext.Products.ToList();
return View();
}
.....
and whenever I launch the server it I would go to /home and it would return 404, I also go to /debug/routes and it would show only the 2 endpoints inside the UseEndpoints function but never the controller classes I made
Try registering you db context in service as below. You could be getting error due to dependency of DatabaseContext on your HomeController would not be able to resolve.
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add below line
services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(connectionString));
services.AddControllersWithViews();
}
In the Configure(IApplicationBuilder app, IWebHostEnvironment env) method of the Startup class you need something like: app.MapControllers();
I think you controllers are registered to DI throught the call services.AddControllersWithViews(); but there is no middleware registration to invoke your controllers, wich should be done in the Configure method.
I'm getting this error when I try the migration commands :
Add-Migration AddAuthentication
Update-Database
I've added all the proper nugget packages so I don't know where the error stems from.
Here is my startup.cs :
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddDbContext<AuthDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("AuthConnectionString")));
services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<AuthDbContext>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
And this is my Model :
public class AuthDbContext : IdentityDbContext
{
public AuthDbContext(DbContextOptions<AuthDbContext> options) : base(options)
{
}
And here is the connection string :
"ConnectionStrings": {
"AuthConnectionString": "Server=.;Database=AspNetAuth;Trusted_Connection=True"
}
}
Thank you for your time !
I use this connection string for local sql server
"Data Source=localhost;Initial Catalog=xxxx;Integrated Security=SSPI;Persist Security Info=True;"
I am trying to use Autofac with ASP.Net Core 3.1 but I am getting an exception which does not make sense.
I am getting the following exception:
Autofac.Core.Activators.Reflection.NoConstructorsFoundException: 'No accessible constructors were found for the type 'Microsoft.AspNetCore.Mvc.ModelBinding.CompositeBindingSource'.'
I think the issue might be because of the order of services registered but I can't figure out what I am doing wrong. My configuration is as follows:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Startup.cs class
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public ILifetimeScope AutofacContainer { get; private set; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddDbContext<EShopDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DBConnection")));
services.AddSwaggerGen();
services.AddOptions();
}
public void ConfigureContainer(ContainerBuilder containerBuilder)
{
containerBuilder.RegisterModule(new AutofacModule());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
this.AutofacContainer = app.ApplicationServices.GetAutofacRoot();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "eShop");
c.RoutePrefix = string.Empty;
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
AutofacModule.cs class
public class AutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
// scan all assemblies in current application domain and resolve them on convention
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.AsImplementedInterfaces();
}
}
What am I missing?
I was able to find the problem with the help of examples code...
The problem for me was in the AutofacModule.cs class. I was scanning the assembly incorrectly. Here is the working code.
public class AutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
// scan all assemblies in current application domain and resolve them on convention
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.AsImplementedInterfaces();
}
}
Autofac has examples of projects in Github and I found out that their documentation was different from their example code. This is the link of the ASP.Net Core 3.1 Example. for anyone who wants to see the configuration.
I want two versions of api gateway (1.0 and 2.0) in Net Core 3.1 . Additionally, I have a cache and permissions service. Is it possible for version 1.0 to have a different permissions service implementation than for version 2.0? Is it possible to have two different Startup files?
As far as I know, we could have Startup class conventions and Startup method conventions.
Startup class conventions:
The app can define multiple Startup classes for different environments. The appropriate Startup class is selected at runtime. The class whose name suffix matches the current environment is prioritized. If a matching Startup{EnvironmentName} class isn't found, the Startup class is used.
That means you could have multiple startup.cs like StartupDevelopment,StartupProduction, Startup. If your host application's server environment variable "ASPNETCORE_ENVIRONMENT" has been set to the "Development", it will use StartupDevelopment. If there is no startup.cs match the ASPNETCORE_ENVIRONMENT, it will use default Startup.cs.
More details about how to set the environment variable , you could refer to this article.
Codes like below:
public class StartupDevelopment
{
public StartupDevelopment(IConfiguration configuration)
{
Configuration = configuration;
Console.WriteLine(MethodBase.GetCurrentMethod().DeclaringType.Name);
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app)
{
app.UseDeveloperExceptionPage();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
public class StartupProduction
{
public StartupProduction(IConfiguration configuration)
{
Configuration = configuration;
Console.WriteLine(MethodBase.GetCurrentMethod().DeclaringType.Name);
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app)
{
app.UseExceptionHandler("/Error");
app.UseHsts();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
Console.WriteLine(MethodBase.GetCurrentMethod().DeclaringType.Name);
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
Your best bet is to register two different service implementations, with two different interface types.
interface IPermissions {}
interface IPermissionsV2 : IPermissions {}
class PermissionsV1 : IPermissions {}
class PermissionsV2 : IPermissionsV2 {}
public class APIV1{
public APIV1(IPermissions ...){}
}
public class APIV2{
public APIV2(IPermissionsV2 ...){}
}
// etc
Though you could use a proxy service to locate the real service. This feels like an anti-pattern that I shouldn't recommend;
interface IPermissions {}
interface IPermissions<T>:IPermissions {}
public class PermissionsV1 : IPermissions {}
public class PermissionsV2 : IPermissions {}
public class PermissionsProxy : IPermissions<T>{
private IPermissions implementation;
public PermissionsProxy (IServiceProvider provider){
if (typeof(T) ... )
implementation = provider.GetService<PermissionsV1>();
// etc
}
public void Method() => implementation.Method();
}
public class APIV1{
public APIV1(IPermissions<APIV1> ...){}
}
public class APIV2{
public APIV2(IPermissions<APIV2> ...){}
}
Or configure multiple middleware pipelines with different services. But that feels over-complicated.
I was developing a Web-App with Asp.Net Core 2.1 . After I added the new identity with scaffolder it generated me these codes:
Code generated in IdentityStartup.cs
[assembly:HostingStartup(typeof(ShareAndCare.Areas.Identity.IdentityHostingStartup))]
namespace ShareAndCare.Areas.Identity
{
public class IdentityHostingStartup : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
builder.ConfigureServices((context, services) => {
services.AddDbContext<ShareAndCareContext>(options =>
options.UseLazyLoadingProxies().UseSqlServer(
context.Configuration.GetConnectionString("ShareAndCareContextConnection")));
services.AddIdentity<ShareAndCareUser, IdentityRole>()
.AddEntityFrameworkStores<ShareAndCareContext>()
.AddDefaultTokenProviders();
services.AddSingleton<IEmailSender, EmailSender>();
});
}
}
}
Code generated in Startup.cs
namespace ShareAndCare
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseCookiePolicy();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
This was working fine until I wanted to scaffold a model with controller and views using EF. When set up everything and click ok I was getting an error saying : More than one DbContext named 'ShareAndCare.Models.ShareAndCareContext' was found. Specify which one to use by providing its fully qualified name using its exact case. I checked all the folders and namespaces but there was no problem there, there was only one context with that name. So what was the problem ?
I'm leaving that question and answer here so people don't go crazy looking for all possible solutions manually like I did. I found out that adding the context in the Configure method of IdentityHostingStartup.cs was causing the problem. I changed the place where I added the context to the Configure method of Startup.cs and it was working just fine.
namespace ShareAndCare
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddDbContext<ShareAndCareContext>(options =>
options.UseLazyLoadingProxies().UseSqlServer(
Configuration.GetConnectionString("ShareAndCareContextConnection")));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseCookiePolicy();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
I just deleted the 2 files:
Areas/Identity/Data/APNameIdentityDbContext.cs and
Areas/Identity/IdentityHostingStartup.cs
This fixed the error!
In my Case I was adding
services.AddDbContext<DBContext>
but instead my DBContext name was
ApplicationDBContext.
Changed my Name in Startup.cs and it worked
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddDbContext<ApplicationDBContext>(options => options.UseSqlServer(Configuration["Data:ConnectionStrings:DefaultConnection"]));
}
Hope this helps someone :)