I’m working on web application based on .NET Core 2.0.
I have class ReportModel
, which I use for binding parameters in controller method. And I also have some functionality in the same class (method Get()
starts doing somethings, based on provided binded parameters), e.g:
[HttpGet]
public JsonResult GetReport(ReportModel model)
{
return new JsonResult( new { model.Get().ToString() });
}
Now I’m moving on .NET 5
and want to add IConfiguration
via DI to ReportModel
.
I’ve expected it to work the follwing way: add constructor for ReportModel
with IConfiguration
for DI to provide configuration:
public class ReportModel
{
private readonly IConfiguration _configuration;
public ReportModel(IConfiguration configuration)
{
_configuration = configuration;
}
...
But when I try to run GetReport(ReportModel model)
method it returns exception:
InvalidOperationException: Could not create an instance of type 'ViewData.Models.Data.ReportModel'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Record types must have a single primary constructor. Alternatively, give the 'data' parameter a non-null default value.
A little explanation: there are few more classes, which I use this way (binding params to properties and storing functionality inside same class), so I don’t really want to add each method Get()
additional parameter for IConfiguration
.
How am I supposed to do this properly? Am I missing something? Or It’s just don’t work this way?
I’m sorry if I use any of terminology wrong, would be glad if you point me the wrong stuff. Thanks.
4
Answers
So I listened the advice of @Camilo. My plan is to split
ReportModel
intoReportParams
(DTO class) andReportProvider
(business logics class). Then, add constructor forReportProvider
in order to provideIConfiguration
via Dependency Injection by callingActivatorUtilities.CreateInstance<ReportProvider>()
Model splitting:
ReportController:
It’s a great question. You’re on the right track.
In my opinion, the
ReportModel
simply shouldn’t use dependency injection. The model should just be a property bag that models the incoming parameters.Have logic be performed in a controller action (or otherwise handled some other way).
It doesn’t work that way.
First of all, models are not supposed to have dependencies injected, they are just a class for getting the input from the request.
This is also wrong, though:
... GetReport(ReportModel model)
. This relies on the fact that ASP.NET Core injects a new ReportModel by default – if this behavior changes, your code magically stops working.Your code should look like this instead:
Along with an appropriate class that builds the report, something like:
default DI container that is used in net core can only inject dependency inside of the constructor, in this case a controller constructor, not inside of an action, since action doesn’t have a constructor. So change your code like this
and don’t forget to add DI to the startup