我正在尝试创建一个HtmlHelper,它将创建与Bootstrap兼容的表单字段。我的第一个目标是创建一个HtmlHelper来创建周围的div:
<div class="control-group"> ... </div>
遵循这里的优秀建议,并在这里我设法让它相对快速地工作。但它并不总是奏效。
我有一个具有复杂属性的ViewModel,所以在我的表单中我访问了字段m=>m.Complex.Element
。在我的助手中,我检查元素是否有验证错误。我使用ModelMetadata.FromLambdaExpression(expression, html.ViewData)
。我收到的元数据的属性名称为Element
,而不是Complex.Element
。
当我检查ModelState的这个属性时,我找不到它,因为ModelState保留了全名 - Complex.Element
。
我可以寻找部分匹配,希望没有其他元素,但这似乎是一个令人讨厌的错误等待发生。如何从表达式中获取完整的属性名称?
答案 0 :(得分:29)
MVC消息来源是公开的,这是一件好事。获取ModelState属性名称的正确方法是使用
var propertyName = ExpressionHelper.GetExpressionText(expression);
答案 1 :(得分:6)
我之前使用以下内容来获取当前模型,但您可能需要将属性名称附加到此属性中以获取该属性。
ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix;
否则拔出反射器/ ilspy / what并检查您的EditorFor / TextBoxFor或编辑器所呈现的任何方法。
答案 2 :(得分:4)
我已经将两个答案的组合用于我需要的属性。总之,这两个答案都提供了我可以在两个视图和嵌套编辑器模板中使用的工作属性。这是我的榜样:
public static MvcHtmlString HasErrorClassFor<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression)
{
string expressionText = ExpressionHelper.GetExpressionText(expression);
string htmlFieldPrefix = htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix;
string fullyQualifiedName;
if (htmlFieldPrefix.Length > 0)
{
fullyQualifiedName = string.Join(".", htmlFieldPrefix, expressionText);
}
else
{
fullyQualifiedName = expressionText;
}
bool isValid = htmlHelper.ViewData.ModelState.IsValidField(fullyQualifiedName);
if (!isValid)
{
return MvcHtmlString.Create("has-error");
}
return MvcHtmlString.Empty;
}