I have several views in an MVC3 project that allow a user to enter a Url into a text input and save it as data on an entity.
We need to validate that the input is a validly formed Url.
I first started with using the [Url] annotation from http://dataannotationsextensions.org/ but for some strange reason, the client-side validation fails if the user inputs any uppercase characters. So to alleviate that I added a jQuery event that forces the input to lowercase as the user types. Turns out this isn’t optimal either because the user can paste in a Url that has been shortened by a Url shortening service such as tinyUrl, etc. and those uppercase characters are necessary for the translation.
So I went instead with a regular expression:
[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")]
This works fine for allowing uppercase characters. But it’s not perfect. With this Regex these are all considered valid:
As you can see, some of these aren’t truly valid.
The biggest problem with these Urls is when displaying the Url back in a Display View. If the Url text does not have the http:// prepended to the Url then the link that is created in the View ends up looking like this:
http://www.mydomain.com/controller/action/www.asp
or
http://www.mydomain.com/controller/action/asp.net
which are both invalid obviously.
For example, this bit of Razor code will create a link like the two above if the Url does not have http:// prepended
....
<a href="@item.Link" target="blank">@item.LinkName</a>
...
But if the entered Url has http:// prepended the Url generated in the display view actually is a real Url such as
http://www.asp.net
http://asp.net
http://www.asp - this is actually an invalid address as well but it renders out correctly.
Surely, showing a Url that was saved into a db and then shown on a View isn’t as difficult as this and also allowing a user to save a well formed Url but also abbreviating it such as:
asp.net
www.asp.net
without having to include the prepended protocol.
Update
Here is the definition of my Url field in my ViewModel using the annotation from http://dataannotationsextensions.org/
[Required]
[StringLength(128)]
[Url(false)] // false denotes whether the protocol is required or not
public string URL { get; set; }
So you don’t think I’m nuts, here is a screenshot using uppercase and no uppercase. Tested in IE8 and Chrome so far and I get the same results

Solved, the 2 DLLs DataAnnotationsExtensions.dll and DataAnnotationsExtensions.ClientValidation.dll from http://dataannotationsextensions.org/ that I was using were version 1.0 and did not allow for uppercasing in the
[Url]annotation. I updated to version 1.1 on both as this is the version demo’d on the website and the problem is now fixed.Using
[Url]will now allow me to enforcehttp://if I absolutely have to as well as allowing uppercase characters.Using
[Url(false)]will allow the user to not have to enterhttp://and I can prepend it in code.