MVC – 自定义验证(从 XML 文件获取条件错误消息)






4.67/5 (6投票s)
通过数据注解在 ASP.Net MVC 应用程序中创建自定义验证,并从 XML 文件获取自定义错误消息。
引言
在本文中,我们将讨论使用数据注解在 MVC 中进行自定义验证。此外,我们不会硬编码错误消息,而是从 XML 文件获取自定义错误消息。该 XML 文件将支持多语言和多地域的消息。
有时 MVC 提供的默认数据验证不足以满足需求,我们需要自定义验证消息,例如根据语言和地域显示自定义错误消息。
为了展示代码基础,我们将利用 Visual Studio 2013 提供的默认 MVC Web 应用程序,并添加必要的代码来定制该应用程序中可用的注册页面的验证。
创建基本的 MVC 默认应用程序
打开 Visual Studio 2013 IDE,并按如下方式创建一个新项目:
选择 ASP.Net Web 应用程序:
选择 MVC 作为模板,然后单击“确定”,无需更改任何其他选项。
这将为您提供一个随时可用的小型应用程序,我们可以将其用作添加代码的基础。我使用了注册页面来创建自定义验证。
使用代码
现在创建两个自定义验证器,一个用于自定义必需字段验证,另一个用于自定义不允许特殊字符验证。
以下是我们为实现此目的将要创建的新类文件。
在现有的 Models 文件夹内创建一个名为“Helpers”的新文件夹,我们将使用此文件夹来存放所有我们将要创建的新类文件。
添加一个名为 RequiredValidation 的类。所有验证注解,如 Required、EmailAddress,最终都派生自 ValidationAttribute 基类。因此,我们也将 RequiredValidation 类派生自 ValidationAttribute 基类。
这里重写了基类提供的 IsValid 函数以创建自定义验证。它接受两个参数,第一个是 ValidationContext,它将提供要验证的属性的显示名称;第二个是要验证的值。
在这里,我们在检查值是否为 Null 或为空,如果是,则返回自定义消息。此自定义消息在此示例中是“控件的显示名称 - <来自资源文件的消息>”。
为了获取自定义消息,使用了 GetResourceString 函数,该函数在最后进行解释,它接受四个参数:资源文件路径、资源键、语言和状态。
以下代码中的 ValidationResourceFile 包含 XML 文件的路径,所有错误消息都将添加到其中。该 XML 文件的结构和 GetResourceString 函数将在最后进行解释。
namespace WebAppCustomValidation.Models.Helpers
{
public class RequiredValidationAttribute : ValidationAttribute
{
public static string ValidationResourceFile = "/App_Data/ValidationMessages.xml";
public RequiredValidationAttribute() : base("{0}"){}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if(value == null || value.ToString().Trim() == "")
{
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName) + " - " + Models.Helpers.ValidationHelper.GetResourceString(ValidationResourceFile, "Required", "EN", "XY"));
}
return ValidationResult.Success;
}
}
}
同样,对于不允许某些特定特殊字符,创建一个名为 CharNotAllowed 的新类。这里不允许的字符将与数据注解本身一起传递,并如上所示获取到 _invalidchars 中。
如上所示,ValidationResourceFile 包含错误 XML 文件的路径。(我将此文件路径传递给所有验证规则中的函数,如果整个项目中只有一个文件,您可以将其保留在 ValidationHelper 中)。
这里,从控件传入的值被检查是否包含任何设置为不允许的特殊字符。如果在值中找到任何此类字符,则返回自定义错误文本作为错误消息。此自定义错误消息如上所示,基于键、语言和状态从错误 XML 文件中获取。(GetResourceFunction 已用于此目的,稍后解释)
namespace WebAppCustomValidation.Models
{
public class CharNotAllowedAttribute : ValidationAttribute
{
public static string ValidationResourceFile = "/App_Data/ValidationMessages.xml";
private readonly string _invalidChars;
public CharNotAllowedAttribute(string invalidChars)
: base("{0}")
{
_invalidChars = invalidChars;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if(value != null)
{
for(int i = 0 ; i < _invalidChars.Length; i++)
{
if(value.ToString().Contains(_invalidChars[i]))
{
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)
+ " - " +
Models.Helpers.ValidationHelper.GetResourceString(ValidationResourceFile,
"Invalid_Chars", "EN", "XY"));
}
}
}
return ValidationResult.Success;
}
}
}
现在创建一个名为 ValidationHelper.cs 的另一个类。这将用于根据提供的语言和状态获取与给定键对应的错误消息。
在添加此类之前,让我们看一下在此代码示例中使用的错误 XML 文件。请参考下面的 XML 示例,其中 expression 标签包含所有我们需要检查的条件,在我们的案例中,我们使用的是语言和状态,如果需要,我们可以添加更多并进一步自定义消息。
任何 ValidationMessage 都可以有多个 TargetRules,对应不同的键。GetResourceString 函数根据语言和状态从下面的 XML 中获取所需的
<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfMessages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ValidationMessage ID ="Invalid_Chars">
<TargetableRules>
<TargetableRule>
<Expression>
<lang>EN</lang>
<state>AB,CD</state>
</Expression>
<Message>Invalid charactors found! (AB,CD)</Message>
</TargetableRule>
<TargetableRule>
<Expression>
<lang>EN</lang>
<state>BC,DF,XY</state>
</Expression>
<Message>Invalid charactors found! (BC,DF,XY)</Message>
</TargetableRule>
<TargetableRule>
<Expression>
<lang>FR</lang>
<state>AB,CD,BC</state>
</Expression>
<Message>Invalid charactors found! [fr] (AB,CD,BC)</Message>
</TargetableRule>
</TargetableRules>
</ValidationMessage>
<ValidationMessage ID ="Required">
<TargetableRules>
<TargetableRule>
<Expression>
<lang>EN</lang>
<state>AB,DF,XY</state>
</Expression>
<Message>Field required! (AB,DF,XY)</Message>
</TargetableRule>
<TargetableRule>
<Expression>
<lang>FR</lang>
<state>AB,CD</state>
</Expression>
<Message>Invalid charactors found! [fr] (AB,CD)</Message>
</TargetableRule>
</TargetableRules>
</ValidationMessage>
</ArrayOfMessages>
现在,在 ValidationHelper 类中添加 GetResourceString 函数。
从 xDocument 中的路径加载 XML,并通过 LINQ 查询获取给定键的 ValidationMessage 节点。然后,通过另一个 LINQ 查询获取语言和状态匹配的元素。
这将提供针对给定键、语言和状态过滤后的节点。获取 Message 元素的 قيمة 并将其转换为字符串并返回。
namespace WebAppCustomValidation.Models.Helpers
{
public class ValidationHelper
{
public static string GetResourceString(string resourceFile, string resourceKey,
string lang, string state)
{
string retValue = string.Empty;
XDocument xDoc = XDocument.Load(resourceFile);
var MessageResource = from m in xDoc.Descendants("ValidationMessage")
.Where(r => (string)r.Attribute("ID") == resourceKey)
select m;
var Msg = from m in MessageResource.Descendants("Expression")
.Where(r => (string)r.Element("lang").Value == lang
&& (bool)r.Element("state").Value.Contains(state) == true)
select m.Parent;
foreach (XElement element in Msg.Descendants("Message"))
{
retValue = element.Value.ToString();
}
return retValue;
}
}
}
将新的验证方法用作注解。
public class RegisterViewModel
{
[RequiredValidation]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[RequiredValidation]
[CharNotAllowed("@#")]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
示例代码
代码示例附在文章中,请参阅 Models 文件夹内的“Helpers”文件夹。此文件夹包含所需的类。示例错误 XML 位于 App_Data 文件夹中。