ASP.NET MVC 3 Razor DisplayFor Delegate

倖福魔咒の 提交于 2019-12-11 01:34:22

问题


I'm getting this error:

Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.

Here's my code (custom HTML helper, wrapping DisplayFor so i can choose a template):

public static string DisplayLocationTypeFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, LocationType>> expression, bool plural = false)
{
   return plural ? 
      htmlHelper.DisplayFor(expression, "LocationTypePlural").ToHtmlString() :
      htmlHelper.DisplayFor(expression).ToHtmlString();
}

When i use it like this, it works:

@Html.DisplayLocationTypeFor(model => model.LocationType)

Because the model has a property for LocationType.

But when i do this in another custom HTML helper:

public static MvcHtmlString SearchPreferenceButtonForModel<TModel>(this HtmlHelper<TModel> htmlHelper)
{
   // .. other code
   foreach (var property in htmlHelper.ViewData.ModelMetadata.Properties)
   {
      if (property.PropertyName == "LocationType")
         htmlHelper.DisplayLocationTypeFor(model => ((LocationType)Enum.ToObject(typeof(LocationType), property.Model)), true);
   } 
}

It errors.

I can change my DisplayLocationTypeFor helper to use htmlHelper.Display instead, but i'm not sure how.

Any ideas?

What i'm trying to do, is that i have a specific way of rendering out the LocationType model, that i want to happen across the site. Internally, the template uses a resource file, and some other smarts based on the URL. In other words, there is logic - which i don't wanted repeated.

This way, all my views/templates call into this template as a standard way of rendering the LocationType.


回答1:


You need to read the error message:

Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.

It's telling you that only certain types of (very simple!) lambda expressions are permitted in a Razor template. If you have something more complex, you need to compute the value before you try to pass it to the template. Something like this should work:

if (property.PropertyName == "LocationType") {
  LocationType locationType = (LocationType) Enum.ToObject(typeof(LocationType), property.Model));
  htmlHelper.DisplayLocationTypeFor(model => locationType, true);
} 



回答2:


You can achieve that by composing a display template for LocationType model.

Here is an answer that says how to achieve that. In short:

  1. Create a folder ~/Views/Shared/DisplayTemplates.
  2. Create a view named LocationType in the new folder you created with model type LocationType. Whenever you try a @DisplayFor(model => model.LocationType), the view you created for LocationType will be rendered.


来源:https://stackoverflow.com/questions/11998537/asp-net-mvc-3-razor-displayfor-delegate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!