1

My Controller's HttpPost methods all take ViewModels as parameters. Obviously the ViewModel needs a parameter-less constructor.

I also need my DbContext service to be injected into my ViewModels via their parameterized constructors.

How is everyone else handling this seemingly impossible situation?

David Liang
  • 20,385
  • 6
  • 44
  • 70
Terrence
  • 2,732
  • 2
  • 18
  • 12
  • 1
    Your question seems related to this one: https://stackoverflow.com/questions/45775740/can-i-use-dependency-injection-in-a-viewmodel-for-dbcontext-core2-0. But I would argue that if you need to inject your DbContext into a ViewModel, then your VM is doing too much. – Bryan Lewis Dec 28 '20 at 16:46
  • I guess you are suggesting populating the ViewModel from some other class that can have the dbcontext injected? Thx. – Terrence Dec 28 '20 at 17:09
  • yeah, I would populate the VM in a business logic class/service and return that to the controller; or if necessary, in the Controller directly (if it's not a lot of code, I try to keep my controllers very thin) – Bryan Lewis Dec 28 '20 at 17:26
  • 1
    `ViewModel` in asp.net is a bit different from `ViewModel` in some other patterns (e.g: `MVVM` used in wpf). The `ViewModel` here mainly contains just the data so that the `View` (Razor view/page) can use to render the HTML content. In the other way back (handling request sent from the client), the VM will become where you get the data sent by the client (with the help of the ASP.NET/core framework doing a preprocess called `model binding` for u). The client-server way requires the VM to have a parameterless constructor whereas the other way does not. We usually use one same VM for both ways. – Hopeless Dec 28 '20 at 17:34

1 Answers1

0

View models in an MVC context are usually expected to be POCOs and just act as some kind of a data transfer object between the controller and the view. As such, they should rarely contain any logic, and definitely not require some external dependencies like your database context.

Instead, you should consider having something else that is responsible of consuming your database context to create a view model. This could be some service class, or just direct logic within the controller action.

This could for example look like this:

public class ExampleController : Controller
{
    private readonly DataContext _db;
    public ExampleController(DataContext db)
    {
        _db = db;
    }

    public async Task<IActionResult> Index()
    {
        var items = await _db.Items.Where(i => i.State == ItemState.Active).ToArrayAsync();

        var vm = new IndexViewModel
        {
            Items = items,
            Date = DateTime.Today,
        };
        return View(vm);
    }
}
poke
  • 369,085
  • 72
  • 557
  • 602