0

Service

public void ConfigureServices(IServiceCollection services)
{
    string cs = Configuration.GetConnectionString("Skillcheck"); 
    services.AddDbContext<TicketsystemContext>(options => options.UseSqlServer(cs));
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

Context

public TicketsystemContext()
{
}

public TicketsystemContext(DbContextOptions<TicketsystemContext> options)
    : base(options)
{
}

// ... rest of the context

Exception

System.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. at Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, IDbContextOptions contextOptions, DbContext context)
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider() at Microsoft.EntityFrameworkCore.DbContext.get_ChangeTracker() at Microsoft.Extensions.Internal.PropertyHelper.CallNullSafePropertyGetter[TDeclaringType,TValue](Func`2 getter, Object target) at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.BindModelCoreAsync(ModelBindingContext bindingContext) at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)
at Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<g__Bind|0>d.MoveNext()

Exception when I remove the empty constructor from the context

System.InvalidOperationException: Could not create an instance of type 'Skillcheck.Models.TicketsystemContext'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Alternatively, give the 'c' parameter a non-null default value. at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.CreateModel(ModelBindingContext bindingContext) at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.BindModelCoreAsync(ModelBindingContext bindingContext) at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)
at Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<g__Bind|0>d.MoveNext()

  • cs in the Service isn't null and reads the string from appsettings.json successfully
  • after services.AddDbContext the context is in the ServiceCollection and it doesn't throw
  • using the generic DbContextOptions instead of DbContextOptions < TicketsystemContext > in the context constructor doesn't work
  • explicitly adding a IHttpContextAccessor doesn't work either

I temporarily solved it by overriding OnConfiguring, but I want to understand why it's not working. I'm using .Net Core 2.1 on VS2017.

Solution

The error was that instead of

private TicketsystemContext _c;

public HomeController(TicketsystemContext c)
{
    _c = c;
}

public IActionResult Index()
{
    return View(_c.User.First());
}

I used

public IActionResult Index(TicketsystemContext c)
{
    return View(c.User.First());
}

which works when overriding OnConfiguring, but doesn't when configuring while injecting.

7
  • Your code does look ok. Have you explicitly registered IHttpContextAccessor as well? services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>(); Commented Dec 5, 2018 at 14:13
  • 1
    @Mausam: That is totally unnecessary and has nothing to do with the issue here. Commented Dec 5, 2018 at 15:09
  • Which line throw the second error? A reproducable demo would be helpful. Commented Dec 6, 2018 at 3:15
  • @Mausam I've already tried that, but have forgot to mention it. I've added it now. Commented Dec 6, 2018 at 8:35
  • @TaoZhou The Run in CreateWebHostBuilder(args).Build().Run(); throws it. The Startup.Configure Method doesn't show any problems, so it throws after that. I think Chris is onto something so I'll wait until I try to reproduce. Commented Dec 6, 2018 at 8:37

2 Answers 2

4

Well, the first error is due to the inclusion of a parameterless constructor. That should not be present. Dependency injection will always choose the constructor with the least dependencies to satisfy, which would be the parameterless, but you need DbContextOptions<TContext> injected.

The second error indicates that you're including the context as a param in an action method. I'm not sure why you're doing that, but you shouldn't. Your context should be injected into the controller itself and set to an ivar on that, so you actions can utilize the ivar. You may be able to prefix the param with [FromServices] to indicate that the modelbinder should ignore it and it should be injected from the service collection, instead, but method injection is an anti-pattern.

Sign up to request clarification or add additional context in comments.

3 Comments

I'm not sure where I'm using an action method. I've added the complete ConfigureService for clarity.
It would be in one of your controllers, not your Startup. In other words, after you remove the parameterless constructor, you're good. The second error is an entirely different issue.
The parameterless constructor didn't matter but I'll keep what you said in mind. In the end it was what you said, with injecting directly into the controller. I just didn't understand the lingo, before the code from Tao.
1

You are injecting TicketsystemContext into Index action directly.

In general, you should inject TicketsystemContext as dependence into contructor like below:

public class HomeController : Controller
{
    private readonly TicketsystemContext context;
    public HomeController(TicketsystemContext context)
    {
        this.context = context;
    }
    public IActionResult Index()
    {
        return View(context.User.First());
    }
}

If you perfer inject TicketsystemContext to action, you could try the suggestion from @Chris Pratt by code below:

public IActionResult Index([FromServices]TicketsystemContext c)
{
    return View(c.User.First());
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.