跨视图重用自定义验证

时间:2014-09-23 16:01:57

标签: asp.net-mvc asp.net-mvc-5

我有一个ASP.NET MVC 5项目。我有一些自定义验证需求。我知道最后,我的HTML的可能结果如下:

<div class="form-group has-error">
  <label for="field">Field Label</label>
  <div id="field">
    <input name="field" class="form-control" type="text" autocomplete="off">
  </div>
  <div>
    Field label is invalid. You need to do something else.
  </div>
</div>

验证错误存储在Dictionary<string, string>的{​​{1}}中。我正在考虑做类似以下的事情:

ViewBag

我的问题是,我不知道在哪里定义@string fieldErrorMessage = getFieldError('field', ViewBag.ValidationErrors) <div class="form-group @if(fieldErrorMessage.length >0) { 'has-error' } "> <label for="field">Field Label</label> <div id="field"> <input name="field" class="form-control" type="text" autocomplete="off"> </div> @if (fieldErrorMessage.length > 0) { <div> @fieldErrorMessage </div> } </div> 。我想在多个视图中使用此功能。所以我不确定。在哪里定义它。或b。怎么称呼它。我甚至不确定我的应用方法是否有错误&#39;是正确的。我觉得我的伪代码比mvc代码更多。

1 个答案:

答案 0 :(得分:2)

页面中的嵌入式功能

要在页面中包含功能,您有两种选择。

扩展HtmlHelper

您可以延长HtmlHelper,以便拨打Html.getFieldError("field")。由于ViewBag位于HtmlHelper,因此您无需将其传递给该函数。证明这一点的最好方法是展示一个例子。

public static class ErrorValidation
{
   public static MvcHtmlString getFieldError(this HtmlHelper<TModel> h, string f)
   {
       if(h.ViewBag.ValidationErrors.ContainsKey(f))
       {
           return MvcHtmlString.Create(h.ViewBag.ValidationErrors[f]);
       }
       return MvcHtmlString.Empty;
   }
}

在视图中添加命名空间:

您可以在视图中添加一个命名空间,方法是在Views\Web.config文件中添加一行。然后,您可以使用您计划的静态方法。这是通过在<add namespace="MyProj.Validation" />内添加<configuration><system.web.webPages.razor><pages><namespaces>之类的内容来完成的。此外,您可以通过MyProj.Validation.getFieldError(...)每次调用对函数的完整参考来解决此问题。


依赖于MVC错误处理

您还可以使用已经内置到MVC中的API,它们允许自定义验证。

通过模型属性进行错误检查:

进行验证的最简单方法是向模型添加属性。如果您的模型具有必填字段,则只需在定义模型的类中的字段上方添加[Required]即可。 System.ComponentModel.DataAnnotations提供了大量验证属性。

如果您想进行自定义检查,可以通过实现抽象类ValidationAttribute来创建自己的属性。只需使用自定义逻辑定义IsValid函数。

如果您需要同时对模型中的多个字段进行验证检查,则可以使用模型实现IValidatableObject。为了简化这一点,在Validate函数中,您不需要创建列表并将所有错误添加到该列表中;只需将关键字ValidationResult放在行的开头即可返回每个yield对象。这看起来像......

public IEnumerable<ValidationResult> Validate(ValidationContext context)
{
    // Duplicate checks
    List<String> fields = new List<String>();
    for (var i=0; i<PhoneNumbers.Count; i++)
    {
        var item = PhoneNumbers[i];
        if (PhoneNumbers.IndexOf(item) != PhoneNumbers.LastIndexOf(item))
        {
            fields.Add("PhoneNumbers["+i+"]");
        }
    }
    if(fields.Count > 0)
    {
        yield return new ValidationResult("You cannot include duplicate phone numbers.", fields.ToArray());
    }
    // More validation checks
}

在控制器中执行错误检查:

您还可以在控制器中执行错误检查,这样可以根据操作的不同进行验证。这也允许您使用ModelState对象在模型中已经发生的验证。要向ModelState添加错误,只需致电ModelState.AddModelError()即可。为了在完成所有检查后检查模型是否有效,您可以检查ModelState.IsValid

在视图中显示错误:

ModelState对象中进行验证后,您可以使用Html对象在视图中显示错误。这允许您通过调用Html.ValidationSummary()生成错误列表,或使用Html.ValidationMessageFor(...)显示各个属性的错误。这是一个广泛的例子......

for (var x = 0; x < Model.PhoneNumbers.Count(); x++ )
{
    <tr>
        <td>@Html.EditorFor(m => m.PhoneNumbers.ElementAt(x))</td>
        @if(ViewData.ModelState["PhoneNumbers[" + x + "]"].Errors.Any())
        {
            <td>@Html.ValidationMessageFor(m => m.PhoneNumbers.ElementAt(x))</td>
        }
        else
        {
            <td>Ok!</td>
        }
    </tr>
}