2

I'm trying to change my ASP.NET MVC project from straight Views and Models to using a ViewModel intermediate layer. Basically, what I'm doing includes having a Person with zero or more Events associated to them. I'm changing to the ViewModel because I want to put a partial view on the Person Details page that shows all of the associated Events.

I have a Person model class and one for Event, and this is my ViewModel:

public class PersonEventViewModel
{
    public PersonEventViewModel(Person person)
    {
        Person = person;
    }

    public Person Person { get; set; }
    public IEnumerable<Event> Events { get; set; }

}

This worked fine for converting my single record pages. On pages such as Person Details, I had to change lines like @Html.DisplayFor(model => model.CreatedOn) to @Html.DisplayFor(model => model.Person.CreatedOn) so it would find the properties correctly, but it worked. On the partial view I'm trying to make, however, I can't seem to get them to show the properties of the model in there. It looks more or less like this:

@model IEnumerable<Proj.ViewModels.PersonEventViewModel>

<table class="table">
    <tr>
        <th>@Html.DisplayNameFor(model => model.RecordedOn)</th>
        <th>@Html.DisplayNameFor(model => model.RecordedBy)</th>
        <th>@Html.DisplayNameFor(model => model.Comments)</th>
    </tr>
@foreach (var item in Model) {
    <tr>
        <td>@Html.DisplayFor(modelItem => item.RecordedOn)</td>
        <td>@Html.DisplayFor(modelItem => item.RecordedBy)</td>
        <td>@Html.DisplayFor(modelItem => item.Comments)</td>
    </tr>
}

This worked when it was using the Events model directly, but now it doesn't seem to matter what I put in between model and the property, it always tells me that it can't resolve it.

Also, I'm not sure how to pass the ViewModel to the partial view. I haven't yet figured out what to put here:

@Html.RenderPartial("_PersonEventList", ?????)

My various attempts to pass the model or model info have all been met with errors.


Per request, this is the source of my details page, where I'm attempting to put the partial view of the Events.

@model Proj.ViewModels.PersonEventViewModel
@{ ViewBag.Title = "Details"; }
<h2>Details</h2>
<div>
    <h4>Person</h4> <hr/>
    <dl class="dl-horizontal">
        <dt>@Html.DisplayNameFor(model => model.Person.FirstName)</dt>
        <dd>@Html.DisplayFor(model => model.Person.FirstName)</dd>
        @*...and so on through the fields...*@
    </dl>
</div>
<p> @Html.ActionLink("Edit Record", "Edit", new {id = Model.Person.PersonId}) </p>

@Html.RenderPartial("_PersonEventList", Model)
techturtle
  • 2,519
  • 5
  • 28
  • 54

2 Answers2

0

Assuming you want "events" in your partial, the partial should take a List<Event> as it's model:

@model IEnumerable<Event> (or List<Event>)

Then in your main view:

@Html.RenderPartial("_PersonEventList", Model.Events)
Barry Franklin
  • 1,781
  • 1
  • 27
  • 45
  • So everywhere I was reading (SO and elsewhere) seems to say that data like this should be passed via a strongly-typed ViewModel, but this looks like you're suggesting just going back to the Model itself. Or am I missing something? – techturtle Dec 27 '16 at 15:11
  • Also, I tried switching to your suggested code, but if I use the `RenderPartial` command I get the ubiquitous `Cannot implicitly convert type 'void' to 'object'` error (which tells me nothing). If I leave it at `@Html.Partial` then it seems to be OK with that. Haven't been able to figure out why, but since I can't get the partial view to work, I can't tell if it'll make any difference. – techturtle Dec 27 '16 at 15:17
  • What happens when you just do @Html.Partial("_PersonEventList", Model.Events)? – Barry Franklin Dec 27 '16 at 17:07
  • I get a cryptic error: `Unable to create a constant value of type 'Proj.Models.Person'. Only primitive types or enumeration types are supported in this context.` This occurs when trying to view the Person Detail page (where the partial view lives). Everything else seems to work OK. – techturtle Dec 27 '16 at 17:12
0

As @Barry Franklin stated, you should change your partial to accept a list of Events. Another thing I wanted to mention is that you should probably be using Partial and not RenderPartial. RenderPartial needs to be encased in brackets and have a ; at the end of it in order for it to work (Html.Partial vs Html.RenderPartial & Html.Action vs Html.RenderAction).

@Html.Partial("_PersonEventList", Model.Events)

You also need to update the partial code:

    @model IEnumerable<Proj.ViewModels.Event>

<table class="table">
@foreach (var item in Model) {
    <tr>
        <td>@Html.DisplayFor(modelItem => item.RecordedOn)</td>
        <td>@Html.DisplayFor(modelItem => item.RecordedBy)</td>
        <td>@Html.DisplayFor(modelItem => item.Comments)</td>
    </tr>
}
Community
  • 1
  • 1
The Pax Bisonica
  • 2,154
  • 2
  • 26
  • 45
  • First off, `@model IEnumerable` doesn't work because there isn't a ViewModel called Event. If I make that the PersonEventViewModel, then it says there isn't anything called Event or Events. If I make it Proj.Models.Event then Visual Studio is all OK with it, and it even seems to run fine, until I try to view a Details page. Then it throws up with the error `Unable to create a constant value of type 'Proj.Models.Person'. Only primitive types or enumeration types are supported in this context.` on the line `@foreach (var item in Model) {`. No idea what this error means. – techturtle Dec 27 '16 at 16:02
  • just replace it with the namespace that your event model lives in – The Pax Bisonica Dec 27 '16 at 17:09
  • I only added that as an example, you can adjust what is needed based on your project – The Pax Bisonica Dec 27 '16 at 17:09
  • I think the main thing to take away from it is how you are using RenderPartial, if you don't want to do it like this @{ Html.RenderPartial() } then use Html.Partial – The Pax Bisonica Dec 27 '16 at 17:09
  • I did that, but I'm getting that weird `unable to create a constant value...` error. Any ideas on that? I haven't found anything useful about it online. – techturtle Dec 27 '16 at 17:10
  • is the events property being set? Can you provide code from your controller method? – The Pax Bisonica Dec 27 '16 at 17:11
  • Just did a debug on the part where I'm setting the ViewModel and the Person is coming out fine, but the error I'm seeing in the Details View is actually being generated by the ViewModel in the Event portion. Guess that at least I know where the error is, though it's a completely separate problem from what I originally posted. – techturtle Dec 27 '16 at 17:21