MVC4 中的模型验证






4.73/5 (20投票s)
在本文中,我们将了解如何在 ASP.NET MVC 应用程序中为模型应用基本验证。
引言
最常见的 Web 应用程序安全弱点是未能正确验证来自客户端或环境的输入。绝不应该信任来自客户端的数据,因为客户端有各种可能性来篡改数据。因此,需要确保数据不仅得到验证,而且业务规则也是正确的。
本文介绍了如何在 ASP.NET MVC 应用程序中实现验证。我将使用一个简单的表单来演示 MVC4 中的基本验证。在这里,我们将看到从客户端和服务器端验证数据的不同方法。
基本上,本文包含以下方法:
- 使用数据注解 (Data Annotations)
- 使用
ModelState
对象(显式模型验证) - 使用 jQuery 验证插件
- 使用 Fluent Validation 包
Using the Code
在 MVC 中,Model
是包含领域类和验证的类。验证在 Model 中起着核心作用。
首先,让我们创建一个带有示例模型、视图和控制器的应用程序。之后,我们将应用不同的方法来验证数据。
模型 (UserModel.cs)
namespace SampleApplication.Models
{
public class UserModel
{
public string Name { get; set; }
public string Email { get; set; }
public string MobileNo { get; set; }
}
}
视图 (User.cshtml)
@model SampleApplication.Models.UserModel
@{
ViewBag.Title = "User Details";
}
<br /><br />
@using (Html.BeginForm())
{
<fieldset>
<legend>Form</legend>
<div class="form-group">
@Html.LabelFor(model => model.Name, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.Name, new { @class = "form-control" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Email, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.Email, new { @class = "form-control" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.MobileNo, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.MobileNo, new { @class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="OK" />
</div>
</div>
</fieldset>
}
控制器 (UserController.cs)
namespace SampleApplication.Controllers
{
public class UserController : Controller
{
public ActionResult User()
{
return View();
}
}
}
使用数据注解 (Data Annotations)
在 ASP.NET MVC 中,验证模型的一种最佳方法是使用数据注解 (Data Annotations)。它在 System.ComponentModel.DataAnnotations 程序集中定义了一组属性和类。数据注解允许我们使用元数据来修饰模型类。这些元数据描述了一组用于验证属性的规则。
要使用 DataAnnotations
,我们需要向模型类添加对 System.ComponentModel.DataAnnotations 程序集的引用。
using System.ComponentModel.DataAnnotations;
namespace SampleApplication.Models
{
public class UserModel
{
[Required(ErrorMessage = "Please Enter Name")]
[Display(Name = "Name")]
public string Name { get; set; }
[Required(ErrorMessage = "Please Enter Email Address")]
[Display(Name = "Email")]
[RegularExpression(@"^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$",
ErrorMessage = "Please Enter Correct Email Address")]
public string Email { get; set; }
[Required(ErrorMessage = "Please Enter Mobile No")]
[Display(Name = "Mobile")]
[StringLength(10, ErrorMessage = "The Mobile must contains 10 characters", MinimumLength = 10)]
public string MobileNo { get; set; }
}
}
现在,我们需要启用 validationsummary
并在视图页面中添加验证消息。
@Html.ValidationSummary()
方法会在视图页面中显示模型的所有验证错误。
@Html.ValidationSummary(true)
@model SampleApplication.Models.UserModel
@{
ViewBag.Title = "User Details";
}
<br /><br />
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>Form</legend>
<div class="form-group">
@Html.LabelFor(model => model.Name, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.Name, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Email, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.Email, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Email)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.MobileNo, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.MobileNo, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.MobileNo)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="OK" />
</div>
</div>
</fieldset>
}
UserController.cs
namespace SampleApplication.Controllers
{
public class UserController : Controller
{
public ActionResult User()
{
return View();
}
[HttpPost]
public ActionResult ServerMeta(RegistrationMetaModel mRegister)
{
if (ModelState.IsValid)
{
return View("Completed");
}
else
{
return View();
}
}
}
}
使用 ModelState 对象(显式模型验证)
如果你想显式地验证模型,那么在控制器中的 ActionMethod
中使用 ModelState
Object 是最佳方法。只需以 (key, value) 对的形式向 ModelState
添加错误消息,当数据在模型中未经验证时,该消息将在视图中显示。
Model
类将显示如下:
namespace SampleApplication.Models
{
public class UserModel
{
public string Name { get; set; }
public string Email { get; set; }
public string MobileNo { get; set; }
}
}
现在我们将向 ModelState
对象添加 errormessage
。
using System.Text.RegularExpressions;
using System.Web.Mvc;
using SampleApplication.Models;
namespace SampleApplication.Controllers
{
public class UserController : Controller
{
public ActionResult User()
{
return View();
}
[HttpPost]
public ActionResult User(UserModel model)
{
if (string.IsNullOrEmpty(model.Name))
{
ModelState.AddModelError("Name", "Please Enter Name");
}
if (!string.IsNullOrEmpty(model.Email))
{
string emailRegex = @"^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$";
Regex re = new Regex(emailRegex);
if (!re.IsMatch(model.Email))
{
ModelState.AddModelError("Email", "Please Enter Correct Email Address");
}
}
else
{
ModelState.AddModelError("Email", "Please Enter Email Address");
}
if (string.IsNullOrEmpty(model.MobileNo))
{
ModelState.AddModelError("MobileNo", "Please enter your mobile no");
}
if (ModelState.IsValid)
{
return View("Completed");
}
else
{
return View();
}
}
}
}
视图 User.cshtml 将显示如下验证消息:
@model SampleApplication.Models.UserModel
@{
ViewBag.Title = "User Details";
}
<br /><br />
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>Form</legend>
<div class="form-group">
@Html.LabelFor(model => model.Name, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.Name, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Email, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.Email, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Email)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.MobileNo, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.MobileNo, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.MobileNo)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="OK" />
</div>
</div> </fieldset>
}
使用 jQuery 验证插件
客户端验证有助于应用程序减少服务器负载,还可以节省最终用户的时间。因此,对于客户端验证,我们使用以下 jQuery 验证插件。
- jquery.validate.min.js
- jquery.validate.unobtrusive.min.js
如果这些文件不存在于 Scripts 文件夹中,请将它们添加到你的应用程序中。
首先,我们需要在 web.config 文件中添加以下 config 设置:
<appSettings>
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>
在 MVC4 中,上述 appsetting 在 config 文件中默认是启用的。但在进行客户端验证之前,我们需要确保 ClientValidationEnabled
和 UnobtrusiveJavaScriptEnabled
的值为 true
。
现在,我们可以编写 clientside
JavaScript 代码来验证数据,或者使用DataAnnotations 属性。Model
中的
让我们利用客户端验证中的 DataAnnotations
API。因此,将 DataAnnotations
添加到模型中。
UserModel.cs
using System.ComponentModel.DataAnnotations;
namespace SampleApplication.Models
{
public class UserModel
{
[Required(ErrorMessage = "Please Enter Name")]
[Display(Name = "Name")]
public string Name { get; set; }
[Required(ErrorMessage = "Please Enter Email Address")]
[Display(Name = "Email")]
[RegularExpression(@"^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$",
ErrorMessage = "Please Enter Correct Email Address")]
public string Email { get; set; }
[Required(ErrorMessage = "Please Enter Mobile No")]
[Display(Name = "Mobile")]
[StringLength(10, ErrorMessage = "The Mobile must contains 10 characters", MinimumLength = 10)]
public string MobileNo { get; set; }
}
}
UserController.cs
namespace SampleApplication.Controllers
{
public class UserController : Controller
{
public ActionResult User()
{
return View();
}
[HttpPost]
public ActionResult ServerMeta(RegistrationMetaModel mRegister)
{
if (ModelState.IsValid)
{
return View("Completed");
}
else
{
return View();
}
}
}
}
在创建 MVC 项目时,应用程序会在 App_Start 文件夹下添加一个 BundleConfig.cs 文件。此类用于将脚本和样式包含在捆绑包中。
在 BundleConfig.cs 文件中,将验证插件包含到 BundleCollection
对象中。
捆绑代码如下:
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*"));
新 MVC 4 项目创建的页面模板(_Layout.cshtml)在页面底部包含此代码,但未加载 jQuery 验证库。
@RenderSection("scripts", required: false)
为了“启用”单个视图的 jQuery 验证,以下代码需要位于视图的末尾。
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
User.cshtml
@model SampleApplication.Models.UserModel
@{
ViewBag.Title = "User Details";
}
<br /><br />
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>Form</legend>
<div class="form-group">
@Html.LabelFor(model => model.Name, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.Name, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Email, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.Email, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Email)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.MobileNo, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.MobileNo, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.MobileNo)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="OK" />
</div>
</div> </fieldset>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
使用 Fluent Validation 包
FluentValidation 库提供了一种简单的方法来单元测试验证规则,可以将验证规则完全从底层模型中分离出来。特别是在需要将依赖项注入验证规则时,这会很有帮助。
现在我们将通过替换 Model
中的 DataAnnotations
来使用 FluentValidation
类库。
Fluent Validation 可作为 Nuget 包使用,因此搜索 FluentValidation.MVC4
并从 Nuget 包管理器中安装。安装后,你将在应用程序中找到两个新程序集,分别名为 Fluent Validation 和 Fluent Validation.Mvc。
添加一个名为 UserModelValidator
的新类,并将所有验证规则放在其中。
namespace SampleApplication.Models
{
public class UserModelValidator : AbstractValidator<UserModel>
{
public UserModelValidator()
{
RuleFor(x => x.Name)
.NotNull();
RuleFor(x => x.Email)
.NotNull()
.EmailAddress();
RuleFor(x => x.MobileNo)
.NotNull()
.Length(6, 10);
}
}
?}
带有数据注解的现有模型
using System.ComponentModel.DataAnnotations;
namespace SampleApplication.Models
{
public class UserModel
{
[Required(ErrorMessage = "Please Enter Name")]
[Display(Name = "Name")]
public string Name { get; set; }
[Required(ErrorMessage = "Please Enter Email Address")]
[Display(Name = "Email")]
[RegularExpression(@"^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$", ErrorMessage = "Please Enter Correct Email Address")]
public string Email { get; set; }
[Required(ErrorMessage = "Please Enter Mobile No")]
[Display(Name = "Mobile")]
[StringLength(10, ErrorMessage = "The Mobile must contains 10 characters", MinimumLength = 10)]
public string MobileNo { get; set; }
}
}
现在,通过在 Validator
属性中指定,将 UserModelValidator
验证类链接到 UserModel
类,如下所示:
[FluentValidation.Attributes.Validator(typeof(UserModelValidator))]
public class UserModel
{
[Display(Name = "Name")]
public string Name { get; set; }
[Display(Name = "Email")]
public string Email { get; set; }
[Display(Name = "Mobile")]
public string Mobileno { get; set; }
}
最后一步是在你的 global.asax 文件中调用 FluentValidationModelValidatorProvider.Configure()
方法。
namespace SampleApplication
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
FluentValidationModelValidatorProvider.Configure();
}
}
}
有关 FluentValidation
的更多信息,请参阅以下链接:
- http://fluentvalidation.codeplex.com/wikipage?title=Validators&referringTitle=Documentation
- http://www.beabigrockstar.com/blog/using-fluent-validation-with-asp-net-mvc-part-2-unit-testing
错误消息显示如下:
我参考了以下链接:
- http://stackoverflow.com/questions/15046117/how-to-manually-enable-jquery-validation-with-asp-net-mvc
- http://www.beabigrockstar.com/blog/using-fluent-validation-with-asp-net-mvc-part-1-the-basics
- http://www.dotnet-tricks.com/Tutorial/mvc/F16Q301112-Server-Side-Model-Validation-in-MVC-Razor.html
历史
我很快就会发布使用 AngularJS 在 MVC 中进行数据绑定的内容。希望这对像我一样的初学者有所帮助。