检查特定表单字段是否有效。

10

我已经搜索了一段时间,但还没有找到解决方案。

我是一个ASP.NET和MVC4/Razor2的新手,因此我主要是在编辑默认项目。

无论如何,我的问题是,我正在使用Twitter Bootstrap,如果底层字段无效,则需要在

中添加一个error CSS类。

到目前为止,我有这个:

    <div class="control-group error">
      @Html.LabelFor(m => m.Password, new { @class = "control-label" })
      <div class="controls">
        @Html.PasswordFor(m => m.Password)
        @Html.ValidationMessageFor(m => m.Password, null, new { @class = "inline-help error" })
      </div>
    </div>

当字段无效时,我应该做些什么才能使 Razor 在片段的第一个 div 中插入 error 类?

更新:我找到了一种方法来实现它,但与其余代码相比,感觉不太对。是否有更好的方法或者这就是唯一的方法?

<div class="control-group@((!ViewData.ModelState.IsValidField("Password")) ? " error" : "")">
4个回答

9

像这样:

public static class HtmlHelperExtensions
{
    public static MvcHtmlString AddClassIfPropertyInError<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper, 
        Expression<Func<TModel, TProperty>> expression, 
        string errorClassName)
    {
        var expressionText = ExpressionHelper.GetExpressionText(expression);
        var fullHtmlFieldName = htmlHelper.ViewContext.ViewData
            .TemplateInfo.GetFullHtmlFieldName(expressionText);
        var state = htmlHelper.ViewData.ModelState[fullHtmlFieldName];
        if (state == null)
        {
            return MvcHtmlString.Empty;
        }

        if (state.Errors.Count == 0)
        {
            return MvcHtmlString.Empty;
        }

        return new MvcHtmlString(errorClassName);
    }
}

那么在您看来:
<div class="control-group @Html.AddClassIfPropertyInError(x => x.Email, "error")">
    <label class="control-label">Email</label>
    <div class="controls">
        <input type="text" placeholder="Email" name="Email" />
        <span class="help-inline">@Html.ValidationMessageFor(x => x.Email)</span>
    </div>
</div>

我之前问过这个问题,那时只是一个小项目,现在已经转移了。你的解决方案看起来不错,只是我现在没有时间测试它,可能以后会。 - willtrnr
谢谢,虽然我使用了简单的htmlHelper.ViewContext.ViewData.ModelState.IsValidField(expressionText)。 - MorioBoncz

6

除了Loki说的之外,我找到了一个不错而且整洁的解决方案来处理ModelState类并检索特定信息以实现我所需的每个验证逻辑:

假设您想要检查模型中名为“InnerClass”的类和字段“Name”的验证:

if (ModelState["InnerClass.Name"].Errors.Count > 0)
{
    foreach (var error in ModelState["InnerClass.Name"].Errors)
    {
        message = error.ErrorMessage;
        isValidFlag = false;
    }
}

除了上述条件外,您也可以使用以下条件:

ModelState.IsValidField("InnerClass.Name")

ModelState类有很好的方法来检索验证信息,因此通过使用提到的方法,您可以通过一些小技巧从中获得更多信息。

希望这对您有所帮助!


那就是关键所在:在 ModelState.IsValidField(...) 调用中,你需要引用正确的 className.fieldName,否则它每次都会返回 true,无论验证状态如何。 - Alex

1

您还可以检查是否有验证消息,快速且简单...

<div class="control-group @(Html.ValidationMessageFor(m => m.Password) != null ? "error" : "")">

我喜欢这个,如果/否则的选项也不错,只要它能正常工作! - Richard Housham

1
你需要查询视图数据(ViewData)中的模型状态字典(ModelStateDictionary)的IsValidField方法。
对于不属于层次结构的模型,你更新中的答案可行。
对于层次结构中的模型,你需要指定相对于整个模型的字段名称。
要获取模型属性的字段名称,请使用Html.NameFor(...) API。
ViewData.ModelState.IsValidField( Html.NameFor(m => m.Password).ToString() )

让我们更进一步,通过添加一个实用方法来扩展HtmlHelper,当字段无效时输出文本。

namespace System.Web.Mvc.Html
{
    public static class GeneralExtensions
    {
        public static MvcHtmlString TextForInvalidField<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string text)
        {
            if(htmlHelper.ViewData.ModelState.IsValidField(htmlHelper.NameFor(expression).ToString()))
            {
                return MvcHtmlString.Empty;
            }
            return MvcHtmlString.Create(text);            
        }
    }
}

最终结果(来自您的原始示例)将如下所示:

<div class="control-group @Html.TextForInvalidField(m => m.Password, "error")">
  @Html.LabelFor(m => m.Password, new { @class = "control-label" })
  <div class="controls">
    @Html.PasswordFor(m => m.Password)
    @Html.ValidationMessageFor(m => m.Password, null, new { @class = "inline-help error" })
  </div>
</div>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接