Hi Folks! In this post I will show you how to create a route in MVC that acccepts an @ symbol in the URL.
Last time I discussed about how to use routing with GUID ids, because they can be easily ruled against a regular expression.
Let's get down to the code, shall we? Again, I have a controller running this thing called CategoriesController.cs that expects a title in the id parameter. It basically finds a category from it and display posts under it. It also works with a parameter called key that is supposed to hold posts GUIDs (that matters for this post, because I will define two routes with constraints).
One way I was able to make it work was validating the parameter containing the @ symbol. That will affect the code when trying to use the route with the Url.RouteUrl method. So, for starters, I have to trim that off of the string id.
What's tricky about routing in MVC is that all roads matter (and a buggy one won't lead someone to Rome, as per say) and even the order they are added matter too. For god's sakes, routes with really complex regular expressions can affect the performance of your website, because once the application goes down into the MVC stuff, all URLs will be validated against them, so put everything into consideration before coming up with different routes and stuff like that.
The general rule is: more strict routes/rules go first, more generic ones should go to the bottom of the queue. Pretty much the same idea of handling exceptions in your code (the exception catch should be the last one).
Category titles are simple texts, so coming up with a regular expression for them would not work, because MVC will try to reach for a controller name anyways. How to solve that? In this case, I decided to use a prefix for the parameters and @ was the winner (I recall seeing some websites using @ in their URLs, whether their sites use ASP.NET or not).
Not all special characters can be used in the URLs.
The RouteConfig.cs
In the RegisterRoutes method, I created two routes for this occasion: one that handles the /@microsoft for a bunch of posts and another handling the /@microsoft/{guid} (if the user wants to see a specific post under the same context and continue browsing). What's important is the thing functions with 2 different, but similar URLs.
My first attempt was to create only one route, with an optional key parameter. But I jaggered that up (I tried and I tried and I tried) and that's how I put into the works. Again, that might not be the ideal situation, but it can be other routes affecting each other and how the website reads the URLs and determine the right controller.
And it wouldn't work by simply adding @ at the beginning of the URL parameter, I had to define a regular expression for the /{id} with the symbol and an extra route for the /{id}/{key} case. Let's take a look at the view using the route with Url.RouteUrl.
First thing should be noticed is the "@" + whatever. The route definition says so, so the code needs to add it to the parameter, even though the "by-categories-at-1" name was specified. Second thing is the Server.UrlDecode: ASP.NET will encode the thing (see the reference here). So in order to use as is, decoding it is!
Let's take a look at the second route being used! But this time with the key parameter... notice again, even though we have the route name there, the id value still needs to be "@" + whatever.
And this is pretty much it! Hope you guys find it useful... feel free to leave a comment and or ask questions!