Home > Net >  Trying to add dependency injection for binding object
Trying to add dependency injection for binding object

Time:01-11

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.

CodePudding user response:

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).

CodePudding user response:

How am I supposed to do this properly? Am I missing something? Or It's just don't work this 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:

public class ReportsController
{
    private readonly IReportModelService _reportModelService;

    public ReportsController(IReportModelService reportModelService)
    {
        _reportModelService = reportModelService;
    }

    [HttpGet]
    public IActionResult GetReport()
    {        
        return new JsonResult(_reportModelService.GetReport());
    }
}

Along with an appropriate class that builds the report, something like:

public class ReportModelService: IReportModelService
{
    private readonly IConfiguration _configuration;

    public ReportModelService(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public string GetReport()
    {
        // your logic here
    }
}

CodePudding user response:

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

public class ReportController
{
   private readonly ReportModel _model

  public ReportController(ReportModel model )
  {
   _model=model;
  }  

    [HttpGet]
    public JsonResult GetReport()
    {
        return new JsonResult( new { _model.Get().ToString() });
    }
}

and don't forget to add DI to the startup

services.AddScoped<ReportModel>();
  •  Tags:  
  • Related