确定数据输入是有效的URL

时间:2012-08-09 15:45:19

标签: asp.net-mvc-3 url razor

我在MVC3项目中有几个视图,允许用户将Url输入到文本输入中并将其作为数据保存在实体上。

我们需要验证输入是否是有效形成的URL。

我首先使用http://dataannotationsextensions.org/中的[Url]注释开始,但由于某些奇怪的原因,如果用户输入任何大写字符,则客户端验证将失败。因此,为了减轻这种情况,我添加了一个jQuery事件,在用户输入时强制输入为小写。事实证明这不是最佳选择,因为用户可以粘贴已被缩短了Url缩短服务(如tinyUrl等)的Url,并且这些大写字符是翻译所必需的。

所以我改为使用正则表达式:

[RegularExpression(@"^((ht|f)tp(s?)\:\/\/|~/|/)?([\w]+:\w+@)?([a-zA-Z]{1}([\w\-]+\.)+([\w]{2,5}))(:[\d]{1,5})?((/?\w+/)+|/?)(\w+\.[\w]{3,4})?((\?\w+=\w+)?(&\w+=\w+)*)?", ErrorMessage = "Please enter a valid Url")]

这适用于允许大写字符。但它并不完美。有了这个正则表达式,这些都被认为是有效的:

  1. www.asp
  2. asp.net
  3. http://asp.net
  4. http://www.asp.net
  5. http://www.asp
  6. 正如您所看到的,其中一些并非真正有效。

    这些网址的最大问题是在显示视图中显示网址时。如果网址文字没有在网址前加http://,那么在视图中创建的链接最终会如下所示:

    http://www.mydomain.com/controller/action/www.asp 
    

    http://www.mydomain.com/controller/action/asp.net
    

    显然都​​是无效的。

    例如,如果Url没有http://前置

    ,那么Razor代码会创建一个类似上面两个的链接
    ....
    <a href="@item.Link" target="blank">@item.LinkName</a>
    ...
    

    但如果输入的网址前面有http://,则在显示视图中生成的网址实际上是一个真实的网址,例如

    http://www.asp.net
    http://asp.net
    http://www.asp - this is actually an invalid address as well but it renders out correctly.
    

    当然,显示保存到数据库然后在视图上显示的Url并不像这样困难,并且允许用户保存格式正确的Url,但也可以缩写它,例如:

    asp.net
    www.asp.net
    

    无需包含前置协议。

    更新

    以下是使用http://dataannotationsextensions.org/

    中的注释在我的ViewModel中定义我的Url字段
    [Required]
    [StringLength(128)]
    [Url(false)] // false denotes whether the protocol is required or not
    public string URL { get; set; }
    

    所以你不认为我疯了,这是一个使用大写但没有大写的截图。到目前为止在IE8和Chrome中测试过,我得到了相同的结果

    Screenshot

2 个答案:

答案 0 :(得分:0)

来自http://dataannotationsextensions.org/

[Url]使用大写字母对我来说非常合适。但如果由于某种原因你不想使用它,你可能会剽窃它使用的正则表达式:

public class MyViewModel
{
    [RegularExpression(@"^(https?|ftp):\/\/(((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-fA-F]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-fA-F]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-fA-F]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-fA-F]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-fA-F]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$")]
    public string Url { get; set; }
}

答案 1 :(得分:0)

解决了,我使用的http://dataannotationsextensions.org/中的2个DLL DataAnnotationsExtensions.dll和DataAnnotationsExtensions.ClientValidation.dll是版本1.0,并且不允许在[Url]注释中使用大写。我更新到版本1.1,因为这是在网站上演示的版本,现在问题已解决。

使用[Url]现在允许我强制执行http://,如果我绝对必须允许大写字符。

使用[Url(false)]将允许用户无需输入http://,我可以将其添加到代码中。