Fetching data within an ASP.NET MVC ViewModel class?

前端 未结 6 1107
清歌不尽
清歌不尽 2021-01-30 18:36

For those that create ViewModels (for use by typed views) in ASP.NET MVC, do you prefer to fetch the data from a service/repository from within the ViewModel, or the controller

6条回答
  •  再見小時候
    2021-01-30 19:25

    Submitting this one late... Bounty is almost over. But...

    Another mapper to look at is Automapper: http://www.codeplex.com/AutoMapper

    And overview on how to use it: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/01/22/automapper-the-object-object-mapper.aspx

    I really like it's syntax.

    // place this somewhere in your globals, or base controller constructor
    Mapper.CreateMap();
    

    Now, in your controller, I would use multiple viewmodels. This enforces DRY by allowing you to reuse those viewmodels elsewhere in your application. I would not bind them all to 1 viewmodel. I would refactor to something like:

    public class EmployeeController()
    {
      private IEmployeeService _empSvc;
      private ISpouseService _peopleSvc;
    
      public EmployeeController(
          IEmployeeService empSvc, ISpouseService peopleSvc)
      {
        // D.I. hard at work! Auto-wiring up our services.  :)
        _empSvc = empSvc;
        _peopleSvc = peopleSvc;
    
        // setup all ViewModels here that the controller would use
        Mapper.CreateMap();
        Mapper.CreateMap();
      }
    
      public ActionResult Employee(int empNum)
      {
        // really should have some validation here that reaches into the domain
        //
    
        var employeeViewModel = 
            Mapper.Map(
              _empSvc.FetchEmployee(empNum)
            );
    
        var spouseViewModel =
            Mapper.Map(
              _peopleSvc.FetchSpouseByEmployeeID(empNum)
            );
    
        employeeViewModel.SpouseViewModel = spouseViewModel;
    
        return View(employeeViewModel);    
      }
    
      [AcceptVerbs(HttpVerbs.Post)]
      public ActionResult Employee(int id, FormCollection values)    
      {
        try
        {
          // always post to an ID, which is the employeeID
          var employee = _empSvc.FetchEmployee(id);
    
          // and bind using the built-in UpdateModel helpers.
          // this will throw an exception if someone is posting something
          // they shouldn't be posting. :)
          UpdateModel(employee);
    
          // save employee here
    
          this.RedirectToAction(c => c.Index());
        }
        catch
        {
          // check your domain model for any errors.
          // check for any other type of exception.  
          // fail back to the employee screen
          RedirectToAction(c => c.Employee(id));
        }
      } 
    }
    

    I generally try to stay away from saving multiple entities on a controller action. Instead, I would refactor the employee domain object to have AddSpouse() and SaveSpouse() methods, that would take an object of Spouse. This concept is known as AggregateRoots, controlling all dependancies from the root - which is the Employee() object. But, that is just me.

提交回复
热议问题