76

.Net Core 1.0.0 - SDK Preview 2 (x64)

.Net Core 1.0.0 - VS "15" Preview 2 (x64)

.Net Core 1.0.0 - Runtime (x64)

So, we updated an RC1 app to the latest versions above. After many hours of switching references, it's running. However, when logging in (AccountController/Login), I am getting an error at:

public class AccountController : BaseController
{
    public UserManager<ApplicationUser> UserManager { get; private set; }
    public SignInManager<ApplicationUser> SignInManager { get; private set; }
    private readonly IEmailSender EmailSender;

    public AccountController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager, IEmailSender emailSender)
    {
        UserManager = userManager;
        SignInManager = signInManager;
        EmailSender = emailSender;
    }

    // GET: /Account/Login
    [HttpGet]
    [AllowAnonymous]
    public IActionResult Login(string returnUrl = null)
    {
        ViewBag.ReturnUrl = returnUrl;
        return View();
    }

    //
    // POST: /Account/Login
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Login(ViewModels.Account.LoginViewModel model, string returnUrl = null)
    {
        if (ModelState.IsValid)
        {
            // Errs this next line
            var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, false); // <-- ERRS HERE '.PasswordSignInAsync'
            if (result.Succeeded)
                return RedirectToLocal(returnUrl);

            ModelState.AddModelError("", "Invalid email or password.");
            return View(model);
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }
            

It blows up with the following error message:

InvalidOperationException: No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext.

Here is the Startup.cs:

public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

        // Add EF services to the services container.
        services.AddEntityFrameworkSqlServer()
           .AddDbContext<LogManagerContext>(options =>
              options.UseSqlServer(Configuration["Data:DefaultConnection:Connectionstring"]));

        services.AddSingleton(c => Configuration);

        // Add Identity services to the services container.
        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<LogManagerContext>()
            .AddDefaultTokenProviders();
            
        
        // Add MVC services to the services container.
        services.AddMvc();

        services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();

        //Add all SignalR related services to IoC. - Signal R not ready yet - Chad
        //services.AddSignalR();

        //Add InMemoryCache
        services.AddMemoryCache();

        services.AddSession(options =>
        {
            options.IdleTimeout = System.TimeSpan.FromHours(1);
            options.CookieName = ".LogManager";
        });

        // Uncomment the following line to add Web API servcies which makes it easier to port Web API 2 controllers.
        // You need to add Microsoft.AspNet.Mvc.WebApiCompatShim package to project.json
        // services.AddWebApiConventions();
        // Register application services.
        services.AddTransient<IEmailSender, AuthMessageSender>();
        
    }

    // Configure is called after ConfigureServices is called.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseSession();

        // Configure the HTTP request pipeline.
        // Add the console logger.
        //loggerFactory.MinimumLevel = LogLevel.Information; - moved to appsettings.json -chad
        loggerFactory.AddConsole();
        loggerFactory.AddDebug();

        loggerFactory.AddNLog();

        // Add the following to the request pipeline only in development environment.
        if (env.IsDevelopment())
        {
            app.UseBrowserLink();
            app.UseDeveloperExceptionPage();
            //app.UseDatabaseErrorPage(DatabaseErrorPageOptions.ShowAll);
        }
        else
        {
            // Add Error handling middleware which catches all application specific errors and
            // sends the request to the following path or controller action.
            app.UseExceptionHandler("/Home/Error");
        }

        env.ConfigureNLog("NLog.config");

        // Add static files to the request pipeline.
        app.UseStaticFiles();

        // Add cookie-based authentication to the request pipeline.
        app.UseIdentity();

        //SignalR
        //app.UseSignalR();

        // Add MVC to the request pipeline.
        app.UseMvc(routes =>
        {
            routes.MapRoute(
             name: "default",
             template: "{controller}/{action}/{id?}",
             defaults: new { controller = "Home", action = "Index" }
             );

            // Uncomment the following line to add a route for porting Web API 2 controllers.
            // routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}");
        });
    }

And here's the Context:

public class ApplicationUser : IdentityUser
{
    // Add Custom Profile Fields
    public string Name { get; set; }
}

public class LogManagerContext : IdentityDbContext<ApplicationUser>
{
    public DbSet<LogEvent> LogEvents { get; set; }
    public DbSet<Client> Clients { get; set; }
    public DbSet<LogEventsHistory> LogEventsHistory { get; set; }
    public DbSet<LogEventsLineHistory> LogEventsLineHistory { get; set; }
    public DbSet<LogRallyHistory> LogRallyHistory { get; set; }
    public DbSet<Flag> Flags { get; set; }
    protected override void OnModelCreating(ModelBuilder builder)
    {

        builder.Entity<LogEvent>().HasKey(x => x.LogId);
        builder.Entity<LogEvent>().ToTable("LogEvents");
        builder.Entity<Client>().HasKey(x => x.ClientId);
        builder.Entity<Client>().ToTable("Clients");
        builder.Entity<LogEventsHistory>().HasKey(x => x.HistoryId);
        builder.Entity<Flag>().HasKey(x => x.FlagId);
        builder.Entity<Flag>().ToTable("Flags");
        builder.Entity<LogRallyHistory>().HasKey(x => x.HistoryId);
        builder.Entity<LogEventsLineHistory>().HasKey(x => x.LineHistoryId);

        base.OnModelCreating(builder);
    }
Community
  • 1
  • 1
Beau D'Amore
  • 2,414
  • 4
  • 17
  • 45

6 Answers6

89

If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext.

The error message says your DbContext(LogManagerContext ) needs a constructor which accepts a DbContextOptions. But I couldn't find such a constructor in your DbContext. So adding the below constructor probably solves your problem.

public LogManagerContext(DbContextOptions options) : base(options)
{
}

Edit for comment

If you don't register IHttpContextAccessor explicitly, use below code:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 
Grigory Zhadko
  • 860
  • 1
  • 12
  • 22
adem caglin
  • 17,749
  • 8
  • 44
  • 67
  • ok, so I added that to the LogManagerContext.cs and now I get a different error with even less info: InvalidOperationException: HttpContext must not be null. get_Context And I still cannot step into the .PasswordSignInAsync method either – Beau D'Amore Jul 13 '16 at 14:38
  • 1
    Can you try to register IHttpContextAccessor? see https://github.com/aspnet/Mvc/issues/3936 – adem caglin Jul 13 '16 at 15:00
  • 1
    services.AddSingleton(); services.AddSingleton(); adding this to the Startup.cs fixed it. Thanks. If you want to repost that link I'll mark it as answer. – Beau D'Amore Jul 13 '16 at 17:21
65

I could resolve it by overriding Configuration in MyContext through adding connection string to the DbContextOptionsBuilder:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            IConfigurationRoot configuration = new ConfigurationBuilder()
               .SetBasePath(Directory.GetCurrentDirectory())
               .AddJsonFile("appsettings.json")
               .Build();
            var connectionString = configuration.GetConnectionString("DbCoreConnectionString");
            optionsBuilder.UseSqlServer(connectionString);
        }
    }
MohammadSoori
  • 1,409
  • 12
  • 12
  • Nice, I forgot maybe the most important line : `optionsBuilder.UseSqlServer(connectionString);` – mkb Feb 17 '18 at 08:08
  • 5
    please do not hard code connections string on OnConfiguring.. this will leak a security issue – alhpe Oct 03 '18 at 21:35
  • 10
    @alhpe It is awesome to say that do not hard code connection strings there as it will leak a security issue. Probably, you could have mentioned what the alternative solution should be. – letsbondiway Feb 10 '19 at 19:45
  • 1
    Use an OS environment variable and read it on your application – alhpe Feb 23 '19 at 18:44
  • I think this is not a good solution. There must be another way to inject this configuration. It will be wonderful if someone may provide a proper way – Ozan BAYRAM Aug 01 '19 at 18:41
  • Well, this is not a good solution but if you are in hurry, then it can work. Best would be to create the DBcontext in the Startup.cs in the Startup core project and then inject from there. – Kshitij Jhangra Aug 13 '19 at 07:14
  • thanks, this is the easiest out-of-the-box solution when using the VS2019 ASP.NET Core MVC template – Michael Nguyen Sep 20 '19 at 09:55
  • 9
    If you are missing `SetBasePath` or `AddJsonFile`, install those packages: `Microsoft.Extensions.Configuration.FileExtensions` `Microsoft.Extensions.Configuration.Json` – Mik Dec 12 '19 at 13:55
  • If you are missing UseSqlServer, install the package: Microsoft.EntityFrameworkCore.SqlServer – Anh Hoang Apr 06 '21 at 11:27
28

This is the solution i found.

https://github.com/aspnet/EntityFramework.Docs/blob/master/entity-framework/core/miscellaneous/configuring-dbcontext.md

Configure DBContext via AddDbContext

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<BloggingContext>(options => options.UseSqlite("Data Source=blog.db"));
}

Add new constructor to your DBContext class

public class BloggingContext : DbContext
{
    public BloggingContext(DbContextOptions<BloggingContext> options)
      :base(options)
    { }

    public DbSet<Blog> Blogs { get; set; }
}

Inject context to your controllers

public class MyController
{
    private readonly BloggingContext _context;

    public MyController(BloggingContext context)
    {
      _context = context;
    }

    ...
}
Ozan BAYRAM
  • 2,317
  • 1
  • 20
  • 29
  • 6
    Thank you Ozan, you are the first person I have found who has mentioned injecting the context into the controller. Have a great day! – kopo222 Mar 31 '20 at 15:28
  • 1
    Yes, no one actually points out this ONLY works via injection, and your back end classes can't see that injection unless they're injected. So any backend usage of the context fails even though it looks like you've done everything right. – Tod Jul 25 '20 at 13:00
  • It still gives the same error. I had no controllers in my API (Data, Application and Domain are separated into projects), so I added and nothing changed. – Nicke Manarin Nov 04 '20 at 19:07
2

In addition to the accepted answer, if anyone still getting the error even after doing followings correctly:

  • In Startup.cs : services.AddDbContext<ApplicationDbContext>(options => ... )
  • In ApplicationDbContext.cs : public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options){}

Check that DbContext class does not have any parameterless public constructor (need to delete it if any). FYI, you might be added parameterless public constructor for some reason i.e. Scaffolding DbContext.

Details: ASP.Net Core troubleshooting

Hassan Tareq
  • 800
  • 13
  • 32
1

Override constructor of DbContext Try this :-

public DataContext(DbContextOptions<DataContext> option):base(option) {}
Dilan
  • 2,190
  • 7
  • 16
  • 25
Raj Kumar
  • 11
  • 1
1

I know this is old but this answer still applies to newer Core releases.

If by chance your DbContext implementation is in a different project than your startup project and you run ef migrations, you'll see this error because the command will not be able to invoke the application's startup code leaving your database provider without a configuration. To fix it, you have to let ef migrations know where they're at.

dotnet ef migrations add MyMigration [-p <relative path to DbContext project>, -s <relative path to startup project>]

Both -s and -p are optionals that default to the current folder.

ChiefTwoPencils
  • 11,778
  • 8
  • 39
  • 65