views:

67

answers:

2

Hi,

I've been looking into view models for mvc and I'm looking for the best way to do them. I've read loads of different articles but none seem to be clear as the "best way." So far example I might have a Customer model with the following properties:

  • First Name
  • Last Name
  • Title
  • Location

Where location is a foreign key to a location table in the database.

I want to be able to edit this customer but only the first name, last name and location. I'm not bothered about the title in the edit. So in my view I will need to pass a customer and a selected list.

Now from what I've read I have the following options (there's probably many more).

So my question is basically which is the best one?

1)

Add a select list to the ViewData["Location"] and just create a strongly typed view of customer?

2)

Create a view model where I pass a customer and select list (the data access is done in the controller):

public class ViewModelTest
{
    public Customer Customer { get; set; }
    public SelectList Locations { get; set; }

    public ViewModelTest(Customer customer, SelectList locations)
    {
        Customer = customer;
        Locations = locations;
    }
}

3)

Create a view model where I pass a customer and list of locations and create the select list in the view model.

public class ViewModelTest
{
    public Customer Customer { get; set; }
    public SelectList Locations { get; set; }

    public ViewModelTest(Customer customer, List<Location> locations, string selectedLocation)
    {
        Customer = customer;
        Locations = new SelectList(locations, "LocationID", "LocationName", selectedLocation);
    }
}

4)

Pass a customer and repository and do the data access in the view model.

public class ViewModelTest
{
    public Customer Customer { get; set; }
    public SelectList Locations { get; set; }

    public ViewModelTest(Customer customer, IRepository repository, string selectedLocation)
    {
        Customer = customer;
        Locations = new SelectList(repository.GetLocations(), "LocationID", "LocationName", selectedLocation);
    }
}

5)

Create the view model with just the properties I need:

public class ViewModelTest
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public SelectList Locations { get; set; }

    public ViewModelTest(Customer customer, SelectList locations)
    {
        FirstName = customer.FirstName;
        LastName = customer.LastName ;
        Locations = locations;
    }
}

6)

Or some other combination of the above or another way.

All opinions welcome.

+1  A: 

Here's what I may suggest: have a view model which reflects the fields of strongly typed view:

public class SomeViewModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Location { get; set; }
    public IEnumerable<SelectListItem> PossibleLocations { get; set; }
}

And in your controller action populate this view model:

public ActionResult Index()
{
    var customer = Repository.GetCustomer();
    var locations = Repository.GetLocations();
    var viewModel = new SomeViewModel
    {
        FirstName = customer.FirstName,
        LastName = customer.LastName,
        Location = customer.Location,
        PossibleLocations = new SelectList(locations, "LocationID", "LocationName", customer.Location);
    };
    return View(viewModel);
}

[HttpPost]
public ActionResult Index(SomeViewModel viewModel)
{
    // TODO: Handle the form submission
    return View(viewModel);
}

Of course doing the mapping between the model and the view model manually as shown my example could become quite cumbersome and in this case I would recommend you looking at AutoMapper.

Darin Dimitrov
+1  A: 

I'd have my ViewModel as this

public class SomeViewModel 
{ 
    public Customer Customer { get; set; } 
    public IEnumerable<Location> PossibleLocations { get; set; } 
} 

My controller like this:

public ActionResult Index()   
{     
    var viewModel = new SomeViewModel   
    {   
        Customer = Repository.GetCustomer(),
        PossibleLocations = Repository.GetLocations()
    };   
    return View(viewModel);   
}

and then you can access everything in your Customer object in the view like this:

Customer name - <%: Model.Customer.FirstName %> <%: Model.Customer.LastName %>
Location - <%: Html.DropDownList("LocationID", new SelectList(Model.PossibleLocations as IEnumerable, "LocationID", "LocationName", Model.Location.LocationID))%>
BritishDeveloper