[英]ASP.NET MVC - Validate Form Input
我是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);
}
}
我的代码正在验证是否提供该字段。 但是,我需要添加一些业务规则。 例如,我需要确保“最大值”大于“最小值”。 如果不是,那么我需要给用户一个错误。 我打算有更复杂的验证方案。
我的问题是, 如何在ASP.NET MVC中处理这些高级验证方案?
如果您要进行很多验证,我建议您深入研究Fluent Validation库。
安装后,您需要在MVC应用程序的Application_Start
事件期间配置FluentValidationModelValidatorProvider
(位于FluentValidation.Mvc
命名空间中)。
这使Fluent Validation可以挂接到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; }
}
这是所有内置验证及其易于创建的自定义数据库驱动验证的列表。
您需要从IValidatableObject派生您的类,看看这篇有用的文章:
http://weblogs.asp.net/scottgu/class-level-model-validation-with-ef-code-first-and-asp-net-mvc-3
一种方法是拥有一个方法(在控制器或单独的验证器类上,您将模型提供给该验证器进行验证)。
这样,您可以根据需要进行许多复杂的验证(击中数据库/服务/文件等,而不会污染您的POCO View模型)
为简单起见,让它内联到控制器中:
[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的)。
我倾向于有一个I <ControllerName> ControllerValidator类(因此对于Homecontroller,它是IHomeControllerValidator),由一个<Controllername> Validator(HomeValidator)具体类实现,并通过unity / dependencyResolver在控制器构造中注入。
做工精美。
最后一个扩展是具有<TValidator>的基本控制器类,该类接受验证器类实例实例,并将其存储在使用该基本类的所有控制器的一致位置。
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)
{
}
}
高温超导
在视图模型中使用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;
}
}
当Minimum > Maximum
时,这将强制ModelState.IsValid
为false。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.