在ASP.NET MVC 4 - Razor视图中,DataAnnotations验证(正则表达式)

51

当在正则表达式中使用特殊字符时,DataAnnotations验证程序在ASP.NET MVC 4 Razor视图中不起作用。

模型:

[StringLength(100)]
[Display(Description = "First Name")]
[RegularExpression("^([a-zA-Z0-9 .&'-]+)$", ErrorMessage = "Invalid First Name")]
public string FirstName { get; set; }

Razor 视图:

@Html.TextBoxFor(model => Model.FirstName, new { })
@Html.ValidationMessageFor(model => Model.FirstName)

不引人注目的验证在视图中呈现为:

<input type="text" value="" tabindex="1" style="height:auto;" name="FirstName" maxlength="100" id="FirstName" data-val-regex-pattern="^([a-zA-Z0-9 .&amp;amp;&amp;#39;-]+)$" data-val-regex="Invalid First Name" data-val-length-max="100" data-val-length="The field FirstName must be a string with a maximum length of 100." data-val="true" class="textfield ui-input-text ui-body-d ui-corner-all ui-shadow-inset valid">

上述HTML中的正则表达式模式未按照Model的RegularExpression指定的方式呈现,即使输入有效数据(Sam's)也会导致错误。

我该如何处理?

--更新--

我已根据@Rick的建议更新了代码。

[StringLength(100)]
[Display(Description = "First Name")]
[RegularExpression("([a-zA-Z0-9 .&'-]+)", ErrorMessage = "Enter only alphabets and numbers of First Name")]
public string FirstName { get; set; }

查看源代码显示如下:

<input data-val="true" data-val-length="The field FirstName must be a string with a maximum length of 100." data-val-length-max="100" data-val-regex="Enter only alphabets and numbers of First Name" data-val-regex-pattern="([a-zA-Z0-9 .&amp;amp;&amp;#39;-]+)" id="FirstName" maxlength="100" name="FirstName" type="text" value="" />

我仍然遇到同样的问题。


我们刚遇到一个类似的问题,我们想要在错误消息中输出" "。 - TweeZz
我已确认MVC 3工具更新和MVC 4 Beta之间的差异。我已经提交了一个错误报告,我们正在调查中。 - RickAndMSFT
我们现在正在将我们的主要产品回滚到MVC3,因为这个问题(我们进行了大量本地化,所以客户端双重编码的á等字符对我们来说是一个很大的障碍)。希望能够得到连接文章的链接,以便我们可以监控这个问题... - Terry_Brown
嗨,Prasad。你解决了这个问题吗? - hopper
1
嗨,teahupoo,我们在项目中将其作为已知问题保留,就像微软现在所做的一样。仍在寻找解决方案。让我们希望微软能尽快提供修复。 - Prasad
显示剩余2条评论
9个回答

36

更新于2012年7月9日 - 看起来这个问题在RTM版本中已经被修复。

  1. 我们已经隐含了^$,所以您不需要添加它们。(包括它们似乎不是一个问题,但您不需要它们)
  2. 这似乎是ASP.NET MVC 4/Preview/Beta中的错误。我已经提交了一个错误报告。

查看源代码会显示以下内容:

data-val-regex-pattern="([a-zA-Z0-9 .&amp;&#39;-]+)"                  <-- MVC 3
data-val-regex-pattern="([a-zA-Z0-9&#32;.&amp;amp;&amp;#39;-]+)"      <-- MVC 4/Beta

看起来我们进行了双重编码。


Rick,去掉^和$后问题解决了吗?即使我已经去掉它们,我仍然面临同样的问题。我已经更新了我的问题并附上了实现代码。 - Prasad
不,它不会改变任何东西。你能把这个标记为正确答案吗? - RickAndMSFT
2
Rick,我不确定是否将其标记为答案,直到它解决了这个问题 :) - Prasad
是否存在指向该 Bug 的链接?我想跟踪它,以便知道何时修复。 - Phil Hale
错误已在即将公开的RC版本中修复。 - RickAndMSFT
显示剩余3条评论

13

尝试转义这些字符:

[RegularExpression(@"^([a-zA-Z0-9 \.\&\'\-]+)$", ErrorMessage = "Invalid First Name")]

仍然是相同的结果:<input type="text" value="" tabindex="1" style="height:auto;" name="FirstName" maxlength="100" id="FirstName" data-val-regex-pattern="^([a-zA-Z0-9 \.\&amp;\&#39;\-]+)$" data-val-regex="无效的名字" data-val-length-max="100" data-val-length="FirstName字段必须是一个最大长度为100的字符串。" data-val="true" class="textfield ui-input-text ui-body-d ui-corner-all ui-shadow-inset input-validation-error"> - Prasad
如果在正则表达式中放入双重反斜杠会怎样? - Darin Dimitrov
你可以在引号前面加上双斜杠"\\"或者@符号,就像Darin在他的示例中所做的那样。 - Dismissile
@Darin,它会将我在正则表达式中添加的任何特殊字符转换,就像我在问题中提到的那样。 - Prasad

5
尝试在表达式开头使用@符号。这样,您就不需要键入转义字符,只需将正则表达式复制粘贴到""中,并放置@符号。像这样:
[RegularExpression(@"([a-zA-Z\d]+[\w\d]*|)[a-zA-Z]+[\w\d.]*", ErrorMessage = "Invalid username")]
public string Username { get; set; }

2

这个方法对我有效,可以试一下

[RegularExpression("^[a-zA-Z &\-@.]*$", ErrorMessage = "--Your Message--")]

1
尽可能地,请努力提供额外的解释,而不仅仅是代码。这样的答案往往更有用,因为它们帮助社区成员,特别是新开发人员更好地理解解决方案的原因,并可以帮助防止需要回答后续问题的需要。 - Rajan

1
你用的是什么浏览器?我在IE8和Chrome中输入了你的示例,当我输入值Sam's时,它都能够成功验证。
 public class IndexViewModel
 {
    [Required(ErrorMessage="Required")]
    [RegularExpression("^([a-zA-Z0-9 .&'-]+)$", ErrorMessage = "Invalid First Name")]
    public string Name { get; set; }
 }

当我使用IE开发者工具栏和Chrome开发者模式检查DOM时,它不会显示任何特殊字符。


我在Firefox、IE和Chrome中尝试了一下。我的应用程序是使用asp.net mvc 4(C#)开发的。http://www.asp.net/mvc/mvc4 - Prasad
如果你排除了不显眼的jQuery脚本,你的验证是否能正常工作? - Dismissile
当我排除“jquery.validate.unobtrusive.min.js”时,客户端验证无法正常工作。 - Prasad
客户端没有触发?还是Sam的验证仍然不正确? - Dismissile
由于客户端未正常工作,它无法正确验证Sam。 - Prasad

1
我们过去也遇到过类似的问题(就像TweeZz所提到的那样)。在我们的情况下,我们通过自定义的htmlHelper扩展方法来控制TextBoxFor的输出,该方法构建MvcHtmlString,在其中一个步骤中,我们需要添加这些不显眼的验证属性,这是通过实现完成的。
var attrs = htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata)

调用此方法后,属性将进行HTML编码,因此我们只需检查是否存在正则表达式验证器,如果有,则对该属性进行HTML解码,然后将它们合并到tagBuilder中(用于构建“input”标记)

if(attrs.ContainsKey("data-val-regex"))
    attrs["data-val-regex"] = ((string)attrs["data-val-regex"]).Replace("&amp;","&");
tagBuilder.MergeAttributes(attrs);

我们只关心 & 符号,这就是为什么进行了字面替换。


1
一般来说,我们需要更多地控制某些属性的呈现(http://stackoverflow.com/questions/6016500/changing-the-generated-id-and-name-attributes),因此我们决定复制粘贴(并修改)某些帮助方法的MVC源代码。似乎没有其他方法了... - TweeZz

0

尝试使用这些值的ASCII代码:

^([a-zA-Z0-9 .\x26\x27-]+)$
  • \x26 = &
  • \x27 = '

格式为\xnn,其中nn是两位十六进制字符代码。您还可以使用\unnnn来指定Unicode字符的四位十六进制字符代码。


即使使用这个,我还是无法得到它:<input type="text" value="" tabindex="1" style="height:auto;" name="FirstName" maxlength="100" id="FirstName" data-val-regex-pattern="^([a-zA-Z0-9 .&amp;&#39;-]+)$" data-val-regex="Invalid First Name" data-val-length-max="100" data-val-length="The field FirstName must be a string with a maximum length of 100." data-val="true" class="textfield ui-input-text ui-body-d ui-corner-all ui-shadow-inset input-validation-error"> - Prasad

0
问题在于正则表达式模式被 HTML 编码了两次,一次是在构建正则表达式时,另一次是在视图中呈现时。
目前,尝试将您的 TextBoxFor 包装在Html.Raw中,像这样:
@Html.Raw(Html.TextBoxFor(model => Model.FirstName, new { }))

尽管我使用了@Html.Raw,但正则表达式仍然被编码渲染。它在我的ASP.NET MVC 3应用程序中运行良好,问题只出现在MVC4应用程序中。 - Prasad
使用@Html.Raw,正则表达式是否仍然被双重编码?在MVC3中,我使用AntiXSS作为默认编码器。我的正则表达式只被编码一次,并且可以正常工作,没有任何问题。 - counsellorben
即使我使用@Html.Raw,它也会进行编码。我正在使用ASP.NET MVC 4。http://www.asp.net/mvc/tutorials/aspnet-mvc-4-mobile-features - Prasad

0

在模型类中尝试这个

    [Required(ErrorMessage = "Enter full name.")]
    [RegularExpression("([A-Za-z])+( [A-Za-z]+)", ErrorMessage = "Enter valid full name.")]

    public string FullName { get; set; }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接