Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do Lists in a view model? + dataannotations

I am using asp.net mvc 3, data annotations and auto mapper.

I want to have all my annotations on properties in my view model once the properties pass validation I use auto mapper to map it back to my domain object.

I have a viewmodel that has properties that I want to have a collection of since I want to generate a table from them. I also want to use them later to use as a form to add rows to this table.

So what do I do? How do I take these properties and make a collection of them?

public class UserViewModel()
{
    [Required()]
    public string UserName = {get; set;}
    [Required()]
    public string FirstName = {get; set;}
    [Required()]
    public string LastName = {get; set;}
}

I want to use these properties to generate my table and be used for a form.

The only thing I can think of is doing this

   public class AddUserViewModel()
    {
        [Required()]
        public string UserName = {get; set;}
        [Required()]
        public string FirstName = {get; set;}
        [Required()]
        public string LastName = {get; set;}
    }

   public class UserViewModel()
   {
       public List<User> Users {get; set;}
       public AddUserViewModel {get; set;}

       public UserViewModel()
       {
           Users = new List<Users>();
       }
   }

So basically I have it as a separate view model that is enclosed into another viewmodel that contains a list of Users(my domain model)

That way I use my domain model to generate the table and my AddUserViewModel for my adding of users.

Seems kinda redundant so I am not sure if there is a better way.

Edit

I have something like this

 var viewModel = new UserViewModel();
 List<Users> users=  UserService.GetAllUsers();
 viewModel = Mapper.Map<Users, UserViewModel>(users);
 return View("Index", viewModel);

I also tried

var viewModel = new UserViewModel();
 List<Users> users=  UserService.GetAllUsers();
 viewModel.AddUserViewModel = Mapper.Map<Users, AddUserViewModel>(users);
 return View("Index", viewModel);

Edit 2

I have this and it compiles but I get this error

        SomeViewModel viewModel = new SomeViewModel ();       
        List<User> users=  userService.GetAllUsers();
        viewModel.UserViewModel = Mapper.Map<List<User>, List<UserViewModel>>(users);
        return View("Index", viewModel);


Trying to map Domain.User to ViewModels.UserViewModel.
Missing type map configuration or unsupported mapping.
Exception of type 'AutoMapper.AutoMapperMappingException' was thrown.
like image 982
chobo2 Avatar asked Jan 30 '11 19:01

chobo2


1 Answers

Why would you want to return a list of domain objects in your view model? That's not what view models are supposed to be. View models should reference only other view models. So you have a nice UserViewModel which represents a user. Now you need to work with multiple users in your view, so either you pass an IEnumerable<UserViewModel> or if you need some other properties you design a view model for this:

public class UserViewModel
{
    [Required]
    public string UserName = { get; set; }
    [Required]
    public string FirstName = { get; set; }
    [Required]
    public string LastName = { get; set; }
}

public class SomeViewModel
{
    public List<UserViewModel> Users { get; set; }
    public string SomeOtherProperty { get; set; }
}

and now your controller action might look like this:

public ActionResult Foo()
{
    SomeModel model = _repository.GetModel();
    SomeViewModel viewModel = Mapper.Map<SomeModel, SomeViewModel>(model);
    return View(viewModel);
}

Now inside your view you could simply use a display template for this Users property (Html.DisplayFor(x => x.Users)) to show a list of them.


UPDATE:

After seeing your update here's how to proceed in terms of good practices:

public ActionResult Foo()
{
    IEnumerable<Users> users = _repository.GetUsers();
    IEnumerable<UserViewModel> usersViewModel = Mapper
        .Map<IEnumerable<Users>, IEnumerable<UserViewModel>>(users);
    return View(usersViewModel);
}

I've also used an AutoMap attribute in a sample project which could simplify your code to this:

[AutoMap(typeof(IEnumerable<Users>), typeof(IEnumerable<UserViewModel>))]
public ActionResult Foo()
{
    IEnumerable<Users> users = _repository.GetUsers();
    return View(users);
}

This attribute will automatically run after the controller action and before the view is rendered and would use AutoMapper to replace the model with the corresponding view model.

like image 120
Darin Dimitrov Avatar answered Nov 03 '22 11:11

Darin Dimitrov