Martin McMahon
Martin McMahon

Reputation: 333

Changing from using Model to ViewModel

I have an index page that lists all users. This has the following in the Users controller -

 public ViewResult Index()
        {
            return View(userRepository.AllIncluding(user => user.Roles));
        }

and then the view starts with

@model IEnumerable<TRS.Models.User>

and then uses

 @foreach (var item in Model) {

to loop through all users in my model.

I now need to change my model to a ViewModel that contains both the User model and an extended UserDetails model.

I have changed my Index view to use the view model -

@model IEnumerable<TRS.ViewModels.RegisterViewModel>

But I don't know how I should be going about filling the ViewModel in my controller -

public ViewResult Index()
        {

            var viewModel = new RegisterViewModel
            {
                UserName = "???"
                FirstName = "???"
                LastName = "???"
            };

            return View(viewModel);
        }

I assume I need to create an instance of the view model and then pass it to the view. But I don't understand how I can get data against each individual item. I'll obviously need to get all data for all users here and then loop through them in my view. Any ideas what I should be going in the controller above? What should replace the "???" with that will fill the viewModel with all the data? Or is this the wrong approach?

Thanks

Edit - Models added -

public class User
    {
        [Key]
        public string UserName { get; set; }

        public virtual ICollection<Role> Roles { get; set; }
        public virtual UserDetails UserDetails { get; set; }
}


 public class UserDetails
    {

        [Key]
        public string UserName { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }

        [Required]
        public virtual User User { get; set; }
}

Edit - From View -

<td>
                @foreach (Role role in item.Roles){
                @role.RoleName <br />
    }</td> 

Upvotes: 0

Views: 157

Answers (4)

Darin Dimitrov
Darin Dimitrov

Reputation: 1039060

public ActionResult Index()
{
    var usersVm = userRepository
        .AllIncluding(user => user.Roles)
        .Select(user => new RegisterViewModel
        {
            UserName = user.UserName
            FirstName = user.UserDetails.FirstName
            LastName = user.UserDetails.LastName
        });
    return View(usersVm);
}

Upvotes: 1

motime
motime

Reputation: 564

it is unclear from your question what UserDetails look like.

You should not use IEnumerable<RegisterViewModel> in your view. The RegisterViewModel should be the container of everything you will need in the view:

    public ViewResult Index()
    {
        var usersDetails = GetUserDetails(userRepository.AllIncluding(user => user.Roles));

        var viewModel = new RegisterViewModel
        {
            UserDetails = usersDetails.ToList(),
            SomeMoreDataRequiredByTheView= "1"
        };

        return View(viewModel);
    }

   //you can use automapper to do this dirty job.
   private IEnumerable<UserDetails> GetUserDetails(IEnumerable<User> users)
   {
       foreach(var user in users)
       {
           yield return new UserDetails()
           {
               FullName = user.FirstName + " " + user.LastName,
               // Other stuff you want

           };
       }
   }

Upvotes: 0

iBoonZ
iBoonZ

Reputation: 1035

Your viewModel

    Public Class RegisterViewModel
   {
      Public IEnumerable<TRS.Models.User> AllUsers {get;set;}
      Public IEnumerable<TRS.Models.UserDetails> UserDetails {get;set;}
   } 

Then in your controller

public ViewResult Index()
{

    var viewModel = new RegisterViewModel
    {
        AllUsers = userRepository.AllIncluding(user => user.Roles).ToList()
    };

    var DetailList = new list<TRS.Models.UserDetails>();
    foreach(var user in viewModel.AllUsers)
    {
        DetailList.add(new userDetails
       {
          name = user.Name,
          age = user.age, 
          ....
       }
    }

    viewModel.UserDetails = DetailList;

    return View(viewModel);
}

Upvotes: 0

dove
dove

Reputation: 20674

Automapper was created for this very thing. I'd highly recommend it.

Take a read of getting started section of wiki.

Once you have it configured your controller code would look something like this:

List<RegisterViewModel> registrants = 
                  Mapper.Map<List<User>, List<RegisterViewModel>>(users);

Though you might want to consider a viewmodel that has a list of registrants on them but that is up to you.

Upvotes: 0

Related Questions