Home > other >  How to use DI in Model (or VM)?
How to use DI in Model (or VM)?

Time:12-04

I had tried to separate DAL and inject it to DI in Program.cs like below

services.AddScoped<IDataLoadServices, DataLoadServices>(); 

Then to get data from DB and put it into Model (maybe can call it ViewModel) I need to get these services from the constructor of Model class like below

class MyModel{
    public IList Countries{get;set;}
    
    public int SelectedCountryCode{get;set;
    
    //default Ctor
    //call When creating by Model Binding
    public MyModel(){
      
    }
    //call when creating by Factory
    [ActivatorUtilitiesConstructor]
    public MyModel(IDataLoadServices ser){
         Countries = ser.LoadMyListFromDB();           
    }
}

In Controller Action I can create a MyModel instance by using FactoryServices.(not shown here) after that passing to View successfully.

@model MyModel
<form method="post" asp-controller="MyController">
  ...
  <select asp-for="SelectedCountryCode" asp-items="@(new SelectList(Model.Countries, "CountryCode", "CountryName"))">            
  </select>
  <input type="hidden" asp-for="SelectedCountryCode" />
 ...

In Controller Action for post-Submit

[HttpsPost]
public IActionResult Submited(MyModel model){
   //model.Countries == null
   //model.SelectedCountryCode == 0 ????
}

The problem I think that is MyModel was created in Model Binding Stage with Default Contructor so that It cant get Countries list and somehow can't resolve SelectedCountryCode.

  1. Is that Right ?
  2. Any idea for bypassing this problem ?

CodePudding user response:

Most of the data your views display should be passed in from the controller. I would keep the model as bare as possible. Instead, inject the IDataLoadServices into the controller.

public class WorldController : Controller
{
    private readonly IDataLoadServices _service;

    public WorldController(IDataLoadServices service)
    {
         _service = service          
    }
}

Check out the docs on this. Dependency injection into controllers in ASP.NET Core

CodePudding user response:

  1. Is that Right ? --> It could be, but you could remove that default ctor from the model. Cause it will be created by default.

  2. Any idea for bypassing this problem ? --> There are many ways to do this.

  • You can load the list of Countries in the startup.cs class using Options pattern (say you have a class with country code and country name) and then use that class inside the model constructor. Option Pattern
  • Inject the IDataLoadServices in the controller class constructor.
  • Related