Once again I’m validating some text inputs, this time I need to verify that a user has entered a GUID in a valid format. While I can’t verify that the user has entered the correct GUID, I can check to make sure that I have the right characters in the string.
The choice is between a method in the .Net Framework for parsing GUID values or using a regular expression. The commonly accepted formats for a GUI are the following
- {0C885DD3-7DD9-484B-9B20-3E6552BCA144}
- 0C885DD3-7DD9-484B-9B20-3E6552BCA144
- 0C885DD37DD9484B9B203E6552BCA144
You usually see it written as 32 hexadecimal characters, separated by hypens into 5 groups. There are some other variations, but this is what you see for text representations of GUIDs.
Going via the .Net Framework, we can use the Guid.TryParse() method. This method takes two parameters, the string to parse and an out parameter that gets the parsed GUID. TryParse() returns true if it can parse the string, false if the string input is not a valid GUID format. It happily takes GUIDs in all three formats list above.
The regular expression that I found for GUID validation is, as with almost all regular expressions, a hideous mess of seemingly random characters. A well crafted regular expression should look like line noise from a 300 baud modem. This regular expression would validate a GUID:
^[{]?[0-9a-fA-F]{8}[-]?([0-9a-fA-F]{4}[-]?){3}[0-9a-fA-F]{12}[}]?$
That’s not very friendly when you first see it. Lets break it down:
^$
The ^ and $ characters match the start and the end of string, everything else takes place with the string to match. We are basically saying, use the entire string input to validate against.
[{]?
This says match the “{” character and the question mark states that it is optional
[0-9a-fA-F]{8}[-]?
This says match 8 characters using all of the digits and the letters from A to F. It’s case insensitive and there is an optional “-“.
([0-9a-fA-F]{4}[-]?){3}
This says match 4 characters with an optional hyphen, 3 times in a row.
[0-9a-fA-F]{12}
This matches the final block of 12 characters (with optional hyphen)
[\)|}]?$
We end with an optional match for “}”.
The source for this regular expression was one submitted by Nicolas Berardi on the RegExLib site. There were a few other GUID validation strings on that site, his looked the best. I did change his expression, it was also allowing for “(” and “)” in addition to the curvy brackets. I don’t think that makes the GUID valid, so I removed it. The “{” and “}” are not part of the IETF 4122 standard, if you are matching UUIDs, then you may want to take out the part that allows for those characters.
The problem is that it would validate text inputs that shouldn’t validate. If your GUID string had a single hyphen, it would pass the regex test, but would fail when used by the .Net Framework. It was also much slower than the TryParse() code, roughly 25 times slower on average.
For user interaction, the performance hit would be negligible. If you were doing a batch import program and were validating the data, you’re going to take a performance penalty hit when you use regular expressions.
The following code shows both implementations with some samples to parse:
The last two sample strings should fail the parsing. The last one only is short one character, the one before it has only one hyphen. The TryParse method works correctly for all of the values, the RegEx fails on the one with a single hyphen. You should be able to tweak the expression by testing for 5 hyphens or for no hyphens. Then you would get this easy to remember version:
^[{|\(]?[0-9a-fA-F]{8}[-]([0-9a-fA-F]{4}[-]){3}[0-9a-fA-F]{12}[\)|}]?|[{|\(]?[0-9a-fA-F]{8}([0-9a-fA-F]{4}){3}[0-9a-fA-F]{12}[\)|}]?$
For C# code, I’ll stick with TryParse(). The RegEx version, I’ll save for Javascript. If you wanted to validate GUID text entry in a browser, the same expression can be used.
For the record, having the user enter in GUID values is a mind boggling UX failure. In this case, this is for an admin tool where the admin user would be copying and pasting in the GUID value from an email.
In case dotnetfiddler falls down, the source code is available on Github Gist.