Object template - Html.Display using ViewBag

2019-05-29 17:41发布

问题:

I've got following display template for object (source):

@model object

@if (Model == null) {
    @ViewData.ModelMetadata.NullDisplayText
} else if (ViewData.TemplateInfo.TemplateDepth > 1) {
    @ViewData.ModelMetadata.SimpleDisplayText
} else {
    foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForDisplay && !ViewData.TemplateInfo.Visited(pm))) {
        if (prop.HideSurroundingHtml) {
            @Html.Display(prop.PropertyName)
        } else {   
            <div>
                <strong>@prop.GetDisplayName():</strong> @Html.Display(prop.PropertyName)
            </div>
        }
    }
}

Which works great, until there is same key in ViewBag. For example following class

public class Article {
    public string Title { get; set; }
    public string Text { get; set; }
}

should display (and will display with empty ViewBag)

Title: Awesome title
Text: Awesome text

however it displays following when ViewBag.Title is set to "Detail"

Title: Detail
Text: Awesome text

It is caused by @Html.Display(prop.PropertyName) that seem to prefer ViewBag value against model value. Any suggestions? I can't use Html.DisplayFor because I have only property name stored in string variable, not as expression for given model.

I guess I could clear viewbag and restore it later, but that doesn't look like good solution to me.

Edit: View looks like this:

@model Article

@{
    ViewBag.Title = "Detail";
}

@Html.DisplayForModel()

回答1:

As for ViewBag.Title itself you could move assignment to it at the end of a page:

@model Article

@Html.DisplayForModel()

@{
    ViewBag.Title = "Detail";
}

As for other ViewBag items you could use item names which are uncommon (with several leading underscores etc.)



回答2:

Found solution: http://haacked.com/archive/2010/05/05/asp-net-mvc-tabular-display-template.aspx - @Html.DisplayFor(m => prop.Model) works as expected. Who knew there was Model property in metadata..