Reputation: 764
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()
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.
Upvotes: 0
Views: 3526
Reputation: 30056
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());
}
Upvotes: 1
Reputation: 239460
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.
Upvotes: 4