在本文中,将探讨如何在ASP.NET MVC中创建自定义验证器,并在服务器端检查表单中特定字段的值。这些验证是在服务器端进行的,因此无论客户端验证如何,应用程序都应进行服务器端验证。规则是除非经过验证,否则所有用户输入都是不可信的。因此,应在客户端、应用程序服务器级别以及数据库服务器(SQL Server / Oracle存储过程)进行验证。
应该对MVC应用程序的工作原理有基本的了解,尽管包含了如何创建第一个MVC应用程序的步骤,但本文是为那些了解MVC的用户准备的。这段代码是在VS 2010 .NET框架4.0中编写并测试的,但逻辑应该在更高版本中保持大致相同。
首先,从创建MVC应用程序开始。
Employee类的架构应该如下所示:
public class Employee
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public string Department { get; set; }
public int PhoneNumber { get; set; }
public string DateOfBirth { get; set; }
public string JoiningDate { get; set; }
}
将从用户那里获取上述类的所有属性的输入。将在本教程的后面部分讨论这个问题。在此阶段编译项目,否则第3步将无法工作。
现在将添加视图并将其映射到这个Employee类。右键单击视图文件夹,然后转到添加 -> 新文件夹。在视图文件夹下创建一个名为Home的文件夹。现在右键单击Home文件夹,然后转到添加 -> 视图。将视图命名为index并按照下面截图中的设置进行设置。记得点击“创建一个强类型的视图”,并从下拉菜单中选择Employee类。如果在下拉菜单中看不到任何东西,请构建项目。
现在打开视图并进行如下更改:
@model MvcApplicationDataValidation.Models.Employee
@{
ViewBag.Title = "index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.ValidationSummary(true)
<table>
<tr><td>Employee Id</td>
<td>@Html.TextBoxFor(m => m.EmployeeId)</td>
<td>@Html.ValidationMessageFor(m => m.EmployeeId)</td>
</tr>
<tr><td>Employee Name</td>
<td>@Html.TextBoxFor(m => m.EmployeeName)</td>
<td>@Html.ValidationMessageFor(m => m.EmployeeName)</td>
</tr>
<tr><td>Department</td>
<td>@Html.TextBoxFor(m => m.Department)</td>
<td>@Html.ValidationMessageFor(m => m.Department)</td>
</tr>
<tr><td>Phone Number</td>
<td>@Html.TextBoxFor(m => m.PhoneNumber)</td>
<td>@Html.ValidationMessageFor(m => m.PhoneNumber)</td>
</tr>
<tr><td>Date Of Birth (dd/mm/yyyy)</td>
<td>@Html.TextBoxFor(m => m.DateOfBirth)</td>
<td>@Html.ValidationMessageFor(m => m.DateOfBirth)</td>
</tr>
<tr><td>Joining Date (dd/mm/yyyy)</td>
<td>@Html.TextBoxFor(m => m.JoiningDate)</td>
<td>@Html.ValidationMessageFor(m => m.JoiningDate)</td>
</tr>
<tr><td></td>
<td><input type="submit" value="Submit"/></td>
</tr>
</table>
}
这个视图的HTML如下所示:
注意,视图中的所有字段都映射到了模型的属性。
现在MVC应用程序的基本结构已经完成。将为这个表单的输入字段添加验证。
在MVC中有一个内置功能,对这些字段有一些预定义的验证。
验证是作为模型类(Employee)属性上的属性添加的,代码如下所示:
[Required]
[StringLength(50, MinimumLength = 3)]
public string Department { get; set; }
这里,Required属性将使这个字段成为必填项,StringLength属性将使Department的值最大值为50,最小长度为3。如果点击提交按钮,如果让Department文本框为空,或者最小长度小于3,或者最大值大于50,应该看到错误消息。
到目前为止,已经实现了内置的MVC验证属性。现在将创建自己的自定义验证。
将验证“出生日期”和“加入日期”的日期格式。期望的格式是dd/mm/yyyy。还将验证加入日期应该大于出生日期,还将验证出生日期应该小于当前日期。在这里将了解如何编写自定义验证器。一旦理解了编写自定义验证器,可以通过编写自定义验证在MVC中执行任何类型的验证。
5.在项目中添加一个名为Validators的新文件夹。将在这个文件夹中保存自定义验证类。
6.在这个文件夹中添加一个新类,并将其命名为DateValidatorAttribute,并添加以下代码:
public class DateValidatorAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
try
{
string strValue = value.ToString();
var dateTime = DateTime.Parse(strValue);
string pattern = @"(^(((0[1-9]|1[0-9]|2[0-8])[\/](0[1-9]|1[012]))|((29|30|31)[\/](0[13578]|1[02]))|((29|30)[\/](0[4,6,9]|11)))[\/](19|[2-9][0-9])\d\d$)|(^29[\/]02[\/](19|[2-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)";
Match match = Regex.Match(strValue, pattern);
if (match.Success)
{
var property = validationContext.ObjectType.GetProperty("JoiningDate");
if (property == null)
return new ValidationResult(string.Format("Property '{0}' is Null", "JoiningDate"));
var objJoiningDate = property.GetValue(validationContext.ObjectInstance, null);
string strJoiningDate = objJoiningDate == null ? "" : objJoiningDate.ToString();
Match matchJoiningDate = Regex.Match(strJoiningDate, pattern);
if (matchJoiningDate.Success)
{
var joiningDate = DateTime.Parse(strJoiningDate);
if (dateTime > joiningDate)
return new ValidationResult("Date of Birth can not be greater than Joining date");
if (dateTime > DateTime.Now)
return new ValidationResult("Date of Birth can not be greater todays date");
}
else
return new ValidationResult("Invalid date format");
}
else
return new ValidationResult("Invalid date format");
return ValidationResult.Success;
}
catch (Exception)
{
return new ValidationResult("Invalid date format");
}
}
}
应该继承.NET ValidationAttribute类,以便可以编写自己的验证逻辑。现在将重写ValidationAttribute类的IsValid方法。
object value包含HTML字段的文本。这个HTML字段的值已经映射到了Employee类的属性。
首先将值转换为字符串并解析为DateTime.parse函数,以检查值是否有效,无论格式如何。现在使用了正则表达式来验证字符串是否在格式dd/mm/yyyy中。可以修改正则表达式以包含其他格式。
到目前为止,已经验证了日期是有效的并且格式正确。接下来将验证这个值不大于加入日期,也不大于当前日期。
var property = validationContext.ObjectType.GetProperty("JoiningDate");
上述代码获取了Employee类中JoiningDate属性的属性。现在将获取这个属性的值(这是用户在视图中的加入日期文本框中输入的)。
var objJoiningDate = property.GetValue(validationContext.ObjectInstance, null);
现在有了值的对象,将把它转换为字符串并再次进行正则表达式匹配以匹配模式。将检查加入日期是否也在正确的格式dd/mm/yyyy中。一旦所有验证通过,将把它们转换为DateTime格式并进行验证。
var joiningDate = DateTime.Parse(strJoiningDate);
if (dateTime > joiningDate)
return new ValidationResult("Date of Birth can not be greater than Joining date");
if (dateTime > DateTime.Now)
return new ValidationResult("Date of Birth can not be greater todays date");