14

我正在尝试创建一个 HtmlHelper 来创建与 Bootstrap 兼容的表单字段。我的第一个目标是创建一个 HtmlHelper 来创建周围的 div:

<div class="control-group"> ... </div>

遵循这里和这里的优秀建议,我设法让它相对快速地工作。但它并不总是有效。

我有一个具有复杂属性的 ViewModel,所以在我的表单中我访问了 field m=>m.Complex.Element。在我的助手中,我检查元素是否存在验证错误。我用ModelMetadata.FromLambdaExpression(expression, html.ViewData). 我得到的元数据有属性名称Element,而不是Complex.Element

当我检查该属性的 ModelState 时,我找不到它,因为 ModelState 保留全名 - Complex.Element

我可以寻找部分匹配,希望没有其他元素,但这似乎是一个等待发生的讨厌的错误。如何从表达式中获取完整的属性名称?

4

3 回答 3

31

MVC 源是公开的,这是一件好事。获取 ModelState 属性名称的正确方法是使用

var propertyName = ExpressionHelper.GetExpressionText(expression);
于 2012-10-07T06:12:33.123 回答
6

我之前使用以下内容为当前模型获取它,但您可能必须将属性名称附加到此属性才能为该属性获取它。

ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix;

否则,拉出反射器/ilspy/whatever 并检查您的 EditorFor/TextBoxFor 或呈现您的编辑器的任何方法。

于 2012-10-07T00:19:50.773 回答
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;
}
于 2013-09-12T11:42:52.963 回答