Nilmag
Nilmag

Reputation: 573

Cannot get my ViewModel to work in MVC ASP.NET

I am having alot of difficult getting my viewmodel to work correctly. As a bit of context i am using a viewmodel to use two models from another project. These models contain the User information and thier chosen Device in a localdb. However i cannot currently use a view to display the data from both of those models on one view so i created a viewmodel.

However I am current recieving:

Error: 'System.Collections.Generic.IEnumerable' does not contain a definition for 'UserID' and no extension method 'UserID' accepting a first argument of type 'System.Collections.Generic.IEnumerable' could be found (are you missing a using directive or an assembly reference?)

This error is occurring for all of the model objects. If i can get around it it will be the first step to a functioning view model. Any help would be greatly appreciated.

User.cs - Model (in project: FaceToFace)

namespace FaceToFace.Model
{
    public class User
    {
        public int UserID { get; set; }
        public string CodeName { get; set; }
        public bool UseBriefInstructions { get; set; }
        public ICollection<RegimeItem> RegimeItems { get; set; }
        public Device Device { get; set; }
        public virtual ICollection<Grading> UserGradings { get; set; }
        public User()
        {
            this.RegimeItems = new List<RegimeItem>();
            Device = new Device();
        }   
    }
    public class RegimeItem
    {
        public int RegimeItemID { get; set; }
        public Exercise RegimeExercise { get; set; }
    }
}

Device.cs - Model (in project: FaceToFace)

namespace FaceToFace.Model
{
    public class Device
    {
        public int DeviceID { get; set; }
        public string Name { get; set; }
    }
}

UserDeviceViewModel.cs (in project: FaceToFaceWebsite)

namespace FaceToFaceWebsite.Models
{
    public class UserDeviceViewModel
    {
        public UserDeviceViewModel()
        {
            User = new User();
            Devices = new List<SelectListItem>();
        }
        public User User { get; set; }
        public IList<SelectListItem> Devices { get; set; }
    }
}

PatientController.cs - Only a segment of the entire page to avoid spam (Project: FaceToFaceWebsite)

namespace FaceToFaceWebsite.Controllers
{
    public class PatientController : Controller
    {
        private F2FData db = new F2FData();
        public ActionResult Index()
        {
            var viewModel = new List<FaceToFaceWebsite.Models.UserDeviceViewModel>();  
            return View(viewModel);
        }
    }
}

Views/Patient/Index.cshtml (facetofacewebsite)

@model IEnumerable<FaceToFaceWebsite.Models.UserDeviceViewModel>
@*@model FaceToFaceWebsite.Models.UserDeviceViewModel*@
@*@model IEnumerable<FaceToFace.Model.User>*@

<h2>Your Patients</h2>
@*Showing @Model.Count() users*@

<p>@Html.ActionLink("Add New User", "Create")</p>

<table>
    <tr>
        <th>@Html.DisplayNameFor(model => model.UserID)</th>
        <th>@Html.DisplayNameFor(model => model.CodeName)</th>
        <th>@*@Html.DisplayNameFor(model => model.Device.Name)*@Device</th>
        <th>@Html.DisplayNameFor(model => model.DeviceID)</th>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <td>@Html.DisplayFor(modelItem => item.UserID)</td>
            <td>@Html.DisplayFor(modelItem => item.CodeName)</td>
            <td>@Html.DisplayFor(modelItem => item.Name)</td>
            <td>@Html.DisplayFor(modelItem => item.DeviceID)</td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id = item.UserID }) |
                @Html.ActionLink("Details", "Details", new { id = item.UserID }) |
                @Html.ActionLink("Delete", "Delete", new { id = item.UserID })
            </td>
        </tr>
    }
</table>

So what i REALLY need to know is that by using model properties from another project, what do i have to do differently. What am i currently doing wrong? what should i do so that the USER information and the DEVICE information can be show.

UPDATE

Thanks to Stephen Muecke, the solution to the issue of the index view not displaying the user db data was solved by changing the Action result in the index controller to:

public ActionResult Index()
        {
            var viewModel = db.Users.Select(u => new UserDeviceViewModel() { User = u, Device = u.Device }).ToList();

            return View(viewModel);
        }

Upvotes: 0

Views: 4292

Answers (5)

nikudale
nikudale

Reputation: 417

As per given code snippet, your View mapping and data model not sync up.

can you just follow below steps

  1. clear all views.
  2. first display only user level info
  3. Verify user level info are you able to? next proceed further device level
  4. put device level loop for your devices collection (make sure your Device collection model m not sure about your "SelectedListItem"

Upvotes: -1

user3559349
user3559349

Reputation:

UserDeviceViewModel contains a property named User not UserID (which is a property of User. Your loop needs to be

@foreach (var item in Model)
{
    <tr>
        <td>@Html.DisplayFor(m => item.User.UserID)</td>
        <td>@Html.DisplayFor(m => item.User.CodeName)</td>

Note you table headers wont work in this case.

Note also you are not really using a true 'view model'. A view model contains only those properties which you need for display/edit in a view (not just for dumping other models). Based on the view code you have shown it should be something like

public class UserDeviceViewModel
{
    public int UserID { get; set; }
    public string CodeName { get; set; }
    public int DeviceID { get; set; }
    public IList<SelectListItem> Devices { get; set; }
}

Although you view contains a reference to property Name (not sure what this is - perhaps DeviceName?) and your view does not use Devices (have you omitted some of the view?)

Upvotes: 1

Dawood Awan
Dawood Awan

Reputation: 7348

Well you could pass the Correct type of ViewModel to your View:

In your View you have:

@model IEnumerable<FaceToFaceWebsite.Models.UserDeviceViewModel>

And in Controller you have:

var viewModel = new FaceToFaceWebsite.Models.UserDeviceViewModel(); 
            return View(viewModel);

Try passing a List of your ViewModel:

var viewModel = new List<FaceToFaceWebsite.Models.UserDeviceViewModel>(); 
            return View(viewModel);

OR:

In your View change this:

@model IEnumerable<FaceToFaceWebsite.Models.UserDeviceViewModel>

To:

@model FaceToFaceWebsite.Models.UserDeviceViewModel

WHY are you getting that ERROR Message?

Because your ViewModel doesn't have UserId, CodeName etc.

BUT your User Class has UserId and CodeName

So In ViewModel you will access like this:

ViewModel.User.UserId and ViewModel.User.CodeName:

Like This:

<th>@Html.DisplayNameFor(model => model.User.UserID)</th>
<th>@Html.DisplayNameFor(model => model.User.CodeName)</th>

Upvotes: 1

sino
sino

Reputation: 776

You are passing List (IEnumerable<FaceToFaceWebsite.Models.UserDeviceViewModel>) , while your view code expected to be FaceToFaceWebsite.Models.UserDeviceViewModel

Upvotes: 1

Marko
Marko

Reputation: 11002

Remove the Ienumerable!

@model FaceToFaceWebsite.Models.UserDeviceViewModel

Look in your controller:

public ActionResult Index() { var viewModel = new FaceToFaceWebsite.Models.UserDeviceViewModel();

return View(viewModel); }

Upvotes: 1

Related Questions