Editor template not being rendered when using a custom "ViewModel"

Topics: Customizing Orchard, General, Troubleshooting, Writing modules
Sep 25, 2012 at 11:12 PM

OK, this one is wierd...

I have a template that when I pass the part as the model will render as expected.

@model MyNamespace.Models.MyPart
@using Orchard.ContentManagement;

@{ Layout.Title = T("My Title").ToString(); }

<fieldset>
    <legend>@T("My Model")</legend>
    
    <div class="editor-label">
        @Html.LabelFor(m => m.Name, @T("Name"))
    </div>
    <div class="editor-field">
        @Html.EditorFor(m => m.Name)
        @Html.ValidationMessageFor(m => m.Name, "*")
    </div>
    
    <div class="editor-label">
        @Html.LabelFor(m => m.Number, @T("Number"))
    </div>
    <div class="editor-field">
        @Html.EditorFor(m => m.Number)
        @Html.ValidationMessageFor(m => m.Number, "*")
    </div>
</fieldset>

As soon as I change the Model to a custom "ViewModel" the editor template is no longer rendered.

@model MyNamespace.ViewModels.MyPartViewModel
@using Orchard.ContentManagement;

@{ Layout.Title = T("My Title").ToString(); }

<fieldset>
    <legend>@T("My Model")</legend>
    
    <div class="editor-label">
        @Html.LabelFor(m => m.Name, @T("Name"))
    </div>
    <div class="editor-field">
        @Html.EditorFor(m => m.Name)
        @Html.ValidationMessageFor(m => m.Name, "*")
    </div>
    
    <div class="editor-label">
        @Html.LabelFor(m => m.Number, @T("Number"))
    </div>
    <div class="editor-field">
        @Html.EditorFor(m => m.Number)
        @Html.ValidationMessageFor(m => m.Number, "*")
    </div>
    <div class="editor-label">
        @Html.LabelFor(model => model.SelectedPriorityId, T("Priority"))
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(
            model => model.SelectedPriorityId,
            Model.Priorities.Select(
                s => new SelectListItem {
                    Selected = s.Id == Model.SelectedPriorityId,
                    Text = s.Description,
                    Value = s.Id.ToString()
                }
            ),
            "- None -")
        @Html.ValidationMessageFor(model => model.SelectedPriorityId)
    </div>
</fieldset>

I am attempting to create a custom ViewModel so that I can add a property that I can use to populate the drop down list.

It works using this code:

protected override DriverResult Editor(MyPart part, dynamic shapeHelper)
{
    return ContentShape("Parts_MyPart",
        () => shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: part, Prefix: Prefix));
}

It does NOT work when I use this code:

protected override DriverResult Editor(MyPart part, dynamic shapeHelper)
{
    return ContentShape("Parts_MyPart",
        () => shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: BuildEditorModel(part), Prefix: Prefix));
}

private MyPartViewModel BuildEditorModel(MyPart part)
{
    MyPartViewModel _model = new MyPartViewModel(part);
    _model.Priorities = _myDataService.GetPriorities();
    return _model;
}

Anyone have any ideas?

Thanks,

Mike

Coordinator
Sep 26, 2012 at 12:05 AM

What does MyPartViewModel look like? What happens exactly? Does it fail silently, do you get an exception, or anything in app_data\logs?

Sep 26, 2012 at 8:11 PM

It was failing silently, however it did put an entry in the error log which pointed me in the right direction.

In case anyone cares...the problem was me attempting to set the MyPartViewModel.SelectedPriorityId in the ctor from the part that was passed in...the only problem was that the part.Priority record was null so part.Priority.Id was (silently) throwing a null ref exception.

I was relying on VS to catch and show me any exceptions and since there were none I figured it was simply me not understanding the whole shape/template naming/location convention.

Painfully obvious once I checked the logs...

Thanks!