问题
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:
- Create a folder
~/Views/Shared/DisplayTemplates
. - Create a view named
LocationType
in the new folder you created with model typeLocationType
. Whenever you try a@DisplayFor(model => model.LocationType)
, the view you created forLocationType
will be rendered.
来源:https://stackoverflow.com/questions/11998537/asp-net-mvc-3-razor-displayfor-delegate