ASP.NET MVC - 验证表单输入

时间:2015-02-20 13:57:19

标签: c# asp.net-mvc

我是ASP.NET MVC的新手。我试图验证一些用户输入。我观点背后的模型如下:

public class ViewModel
{
  [Required]
  public int? Minimum { get; set; }

  [Required]
  public int? Maximum { get; set; }
}

我的视图(.cshtml文件)看起来像这样

@model Website.Models.ViewModel
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    ...
<div class="row">
  <div class="col-sm-6"><input class="form-control input-sm" id="Minimum" name="Minimum" type="text" /></div>                            
  <div class="col-sm-6"><input class="form-control input-sm" id="Maximum" name="Maximum" type="text" /></div>
</div>
   ...

<br />
<button type="submit" class="btn btn-primary">Save</button>
}

我的控制器,看起来像这样:

public class MyController 
{
  public ActionResult Edit(int? id)
  {
    var model = new ViewModel();
    return View(model);
  }

  [HttpPost]
  public ActionResult Edit(ViewModel model)
  {
    if (ModelState.IsValid) {
      var result = await model.SaveAsync();
      return RedirectToAction("Edit", new { id = result.DemandId, u = "true" });
    }
    return View(model);
  }
}

我的代码正在验证是否提供了该字段。但是,我需要添加一些业务规则。例如,我需要确保Maximum超过最小值。如果不是,那么我需要给用户一个错误。我打算有更复杂的验证方案。

我的问题是,我应该如何在ASP.NET MVC中处理这些高级验证方案?

4 个答案:

答案 0 :(得分:3)

如果您要进行大量验证,我建议您深入了解Fluent Validation库。

安装完成后,您需要在MVC应用程序的FluentValidationModelValidatorProvider事件期间配置FluentValidation.Mvc(位于Application_Start名称空间中)。

这使得Fluent验证可以挂钩ModelState并触发ModelState.IsValid等。

protected void Application_Start() {

    /* Your other initializing code */

    FluentValidationModelValidatorProvider.Configure();
}

然后创建验证器

public class ViewModelValidator : AbstractValidator<ViewModel> {

    public ViewModelValidator() {
        RuleFor(x => x.Minimum).NotNull();
        RuleFor(x => x.Maximum).NotNull.GreaterThan(x => x.Minimum)
    }

}

并将其挂钩到您的ViewModel。

[Validator(typeof(ViewModelValidator))]
public class ViewModel
{
     [Required]
     public int? Minimum { get; set; }

     [Required]
     public int? Maximum { get; set; }
}

这是一个list of all inbuilt validation,它也很容易创建自定义数据库驱动验证。

答案 1 :(得分:1)

您需要从IValidatableObject派生您的类,看看这篇有用的文章:

http://weblogs.asp.net/scottgu/class-level-model-validation-with-ef-code-first-and-asp-net-mvc-3

答案 2 :(得分:1)

一种方法是使用一种方法(在控制器上或单独的验证器类中,您可以将模型提供给验证)。

通过这种方式,您可以进行尽可能详细的验证(点击数据库/服务/文件等,而不会污染您的POCO 查看模型)

为简单起见,让它内联到控制器:

[HttpPost]
public ActionResult Edit(ViewModel model)
{
    ValidateEditViewModel(model);
    if (ModelState.IsValid) {

在ValidateEditViewModel中:

private void ValidateEditViewModel(ViewModel model){
    if(model.. // something is wrong)
    {
        // this sets ModelState.IsValid = false
        ModelState.AddModelError("< PropertyNameThatIsInError >", "The item is removed from your cart");  
    }
}

更好的是有一个验证器类,它通过DI注入控制器,然后在整个过程中使用(这是更可测试和SOLID)。

我倾向于有一个&lt; ControllerName&gt; ControllerValidator类(因此,对于Homecontroller,IHomeControllerValidator),它由&lt; Controllername&gt; Validator(HomeValidator)具体类,并通过unity / dependencyResolver注入控制器构造。

工作得很漂亮。

对此的最后一个扩展是使基本控制器类为&lt; TValidator&gt;它接受验证器类实例实例并将其存储在使用此基类的所有控制器的一致位置。

public class BaseController<TValidator> : Controller{
    protected TValidator validator;
    public BaseController(TValidator validator){
         this.validator = validator;
    }
}

所以HomeController是

public class HomeController : BaseController<IHomeControllerValidator>
{
    public HomeController(IHomeControllerValidator validator) : base(validator)
    {
    }
}

HTH

答案 3 :(得分:0)

在视图模型中使用IValidatableObject界面。

public class ViewModel : IValidatableObject
{
    [Required]
    public int? Minimum { get; set; }

    [Required]
    public int? Maximum { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        var results = new List<ValidationResult>();

        if (this.Minimum > this.Maximum)
        {
            results.Add(new ValidationResult("Maximum must be larger than Minimum"));
        }

        return results;
    }
}

这会在ModelState.IsValid时强制Minimum > Maximum为假。