Not touching the parameter part of an rewritten url.

May 15, 2012 at 4:27 PM
Edited May 15, 2012 at 5:04 PM

I like the idea of lowercase URL's, but i don't like the idea that the query parameters are being touched. You solve this issue nicely by checking for the question mark in in the URL. But what if my URL has been rewritten?

When something like /products/view?item=00R48A403 is rewritten to /products/view/{item} I prefer an URL like /products/view/00R48A403 over /products/view/00r48a403. (note the capitals in the product id). In this case it's not up to the route module anymore to decide to go lowercase.

The following code change does exactly that. I've only altered your code file "LowercaseRoute.cs" for a tiny tiny bit. You're completely free to use this as is, change it, or completely ignore it.

Kind regards,
Stephan Meijer

 

// new class property to support untouched url parameters
private static readonly string[] SystemParameters = new[] { "area", "controller", "action" };
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
   VirtualPathData path = base.GetVirtualPath(requestContext, values);

   if (path != null)
   {
      string virtualPath = path.VirtualPath;
      var lastIndexOf = virtualPath.LastIndexOf("?");

      if (lastIndexOf != 0)
      {
         if (lastIndexOf > 0)
         {
            string leftPart = virtualPath.Substring(0, lastIndexOf).ToLowerInvariant();
            string queryPart = virtualPath.Substring(lastIndexOf);
            path.VirtualPath = leftPart + queryPart;
         }
         else
         {
            // start changes to support untouched url parameters
             var parameters = values.Where(x => SystemParameters.Contains(x.Key) == false).ToList();

             if (parameters.Any())
             {
                 var queryPart = string.Join("/", parameters.Select(x => x.Value));
                 var leftPart = virtualPath.Substring(0, virtualPath.Length - queryPart.Length)
                                  .ToLowerInvariant();
                 path.VirtualPath = leftPart + queryPart;
             }
             else
             {
                 path.VirtualPath = path.VirtualPath.ToLowerInvariant();
             }
            // end changes
         }
      }    
   }

   return path;
}

 

Coordinator
May 15, 2012 at 4:40 PM

Hmmm... never really considered this case, but you bring up an excellent point. And with a pretty slick solution to boot.

I tend to agree with you here on aesthetic grounds. Would have to make it very clear in the docs what's happening, otherwise people might get confused.

Thanks very much for the input... let me run it through some tests and if it's all cool I will include it.

May 15, 2012 at 5:02 PM
Edited May 15, 2012 at 5:06 PM

If you really wanna use this, you probably want to promote the "defaults" object to a class property. You don't want to create hundred objects if one will do :)

I'll change code sample above.

internal class LowercaseRoute : Route
{
     private static readonly string[] SystemParameters = new[] { "area", "controller", "action" };
...