It told me to do that. And silly me, I took the advice.
Maybe it wasn’t silly advice at all. But when, like me, you’ve been used to programming ASP.NET for years (which does NOT follow this advice) and you flip over to use the Uri class to represent URI instead of raw strings (like ASP.NET still does), you will be in for a few surprises that may hurt you down the road.
Don’t get me wrong. This is a bit of a rant, and I recommend using System.Uri. But I can recommend using it only after you’re aware of the gotchas.
1) System.Uri is not at all friendly to relative URI.
Many of the most useful properties that help you parse a URI are simply not supported for relative URI. Get used to your code compiling fine and then at runtime seeing InvalidOperationException thrown when you try to access helpful properties such as Uri.Query, etc. Sure seems like it would be helpful to have an HttpUri derived class that *would* know how to work with relative HTTP URI. I would certainly use it!
My recommendation to avoid surprises here? Test evey line of code that uses System.Uri with relative URI. Now some code will be specifically designed to work only with absolute URI, and in that case, you should use the Uri.IsAbsoluteUri property to confirm your assumption as part of that code.
2) Beware converting System.Uri to its string value.
Use Uri.AbsoluteUri to pull out the string value when you know you’ve got an absolute URI.
If the Uri could be relative, AbsoluteUri will throw InvalidOperationException (because, well, it’s not an absolute URI). But don’t fall back and call Uri.ToString instead like I did. Prefer Uri.OriginalString which acts more like Uri.AbsoluteUri in that it does not transform the URI before returning it like Uri.ToString does (Uri.ToString unescapes the URI which could leave you with a bug that only shows up occasionally).
3) Take what the debugger shows you about System.Uri with a grain of salt.
The debugger appears to call Uri.ToString to show you the value of a URI. This will confuse the heck out of you when you’re looking at a URI that you KNOW contains escaped characters, because it will appear as if the URI has been unescaped. If you think you’re a victim of this treachery, set your watch on the OriginalString property of your Uri instead and breathe a sigh of relief that you are not crazy after all.
Microsoft should practice what they preach.
If ASP.NET used the URI class like FxCop tells us we should, it’d be much harder to run into problems with (2) because developers wouldn’t be worried about converting back and forth between System.Uri and strings. Indeed when you program ASP.NET it’s actually harder to write correct code using System.Uri because of these required conversions. You certainly do need to think a lot harder when using System.Uri. I think the ASP.NET team should talk with the FxCop team and get their story straight. Either use URI everywhere, or strings everywhere. Expecting imperfect developers (like me) to deal with this boundary is just asking for trouble, IMHO.
Thanks for listening to my little rant. I hope this spares somebody else the headaches I’ve endured trying to use System.Uri in my ASP.NET web apps.
Posted
Oct 10 2009, 11:28 AM
by
keith-brown