1

I am working on a .NET MVC application and am trying to write a route in global.asax.cs. The goal is, I want any URL that contains an uppercase character to run through said route. The idea is, the router will lowercase the URL and redirect it. My approach is to use a regular expression to handle this. Here's what I have:

routes.MapRoute(
    "CanonicalizationRoute", 
    "{*url}", 
    new 
    { 
        controller = "CanonicalRouter", 
        action = "Reroute" 
    }, 
    new 
    { 
        url = @"[A-Z]+" 
    });

Doesn't seem to do the trick...any thoughts on how best to handle this?

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
kawai
  • 11
  • 2

2 Answers2

0

If you're just looking to support lower-case routes (basically making your routes case-insensitive), you might check out the below. We're currently using this and it works great.

Firstly you will need a RouteExtensions.cs file, or named anything you like with the following (compatible as at ASP.NET MVC RC1):

using System;
using System.Web.Mvc;
using System.Web.Routing;

namespace MyMvcApplication.App.Helpers
{
    public class LowercaseRoute : System.Web.Routing.Route
    {
        public LowercaseRoute(string url, IRouteHandler routeHandler)
            : base(url, routeHandler) { }
        public LowercaseRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
            : base(url, defaults, routeHandler) { }
        public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler)
            : base(url, defaults, constraints, routeHandler) { }
        public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler)
            : base(url, defaults, constraints, dataTokens, routeHandler) { }

        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            VirtualPathData path = base.GetVirtualPath(requestContext, values);

            if (path != null)
                path.VirtualPath = path.VirtualPath.ToLowerInvariant();

            return path;
        }
    }

    public static class RouteCollectionExtensions
    {
        public static void MapRouteLowercase(this RouteCollection routes, string name, string url, object defaults)
        {
            routes.MapRouteLowercase(name, url, defaults, null);
        }

        public static void MapRouteLowercase(this RouteCollection routes, string name, string url, object defaults, object constraints)
        {
            if (routes == null)
                throw new ArgumentNullException("routes");

            if (url == null)
                throw new ArgumentNullException("url");

            var route = new LowercaseRoute(url, new MvcRouteHandler())
            {
                Defaults = new RouteValueDictionary(defaults),
                Constraints = new RouteValueDictionary(constraints)
            };

            if (String.IsNullOrEmpty(name))
                routes.Add(route);
            else
                routes.Add(name, route);
        }
    }
}

Then a using reference in your Global.asax.cs file to the above class, and you’re all set to create a lowercase route. You can see a below example of a lowercase route and anytime this route is called your URL will be lowercased.

        routes.MapRouteLowercase(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new {controller = "Home", action = "index", id = ""} // Parameter defaults
            );

and optionally if you are interested in converting any incoming URL’s to lowercase (manually typed by the user or called links) you can use this in your Application_BeginRequest() method (Remember, this is not needed for lowercase routes themselves, the code above will handle that):

    protected void Application_BeginRequest(Object sender, EventArgs e)
    {
        // If upper case letters are found in the URL, redirect to lower case URL.
        // Was receiving undesirable results here as my QueryString was also being converted to lowercase.
        // You may want this, but I did not.
        //if (Regex.IsMatch(HttpContext.Current.Request.Url.ToString(), @"[A-Z]") == true)
        //{
        //    string LowercaseURL = HttpContext.Current.Request.Url.ToString().ToLower();

        //    Response.Clear();
        //    Response.Status = "301 Moved Permanently";
        //    Response.AddHeader("Location", LowercaseURL);
        //    Response.End();
        //}

        // If upper case letters are found in the URL, redirect to lower case URL (keep querystring the same).
        string lowercaseURL = (Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath);
        if (Regex.IsMatch(lowercaseURL, @"[A-Z]"))
        {
            lowercaseURL = lowercaseURL.ToLower() + HttpContext.Current.Request.Url.Query;

            Response.Clear();
            Response.Status = "301 Moved Permanently";
            Response.AddHeader("Location", lowercaseURL);
            Response.End();
        }
    }

Answer originally came from this SO post.

The content on this answer was taken from a blog post that is no longer available but can be viewed on archive.org here.

Community
  • 1
  • 1
Andrew Flanagan
  • 4,267
  • 3
  • 25
  • 37
-1

By any chance are you running IIS 7? The URL Rewrite module provides a nice way of handling this outside of your application (configured in the web.config file). Here's a blog post about it, including your specific need.

Untested, but as for your code issue, maybe the regex needs to allow characters besides uppercase letters? ".*[A-Z]+.*"

Chris Shaffer
  • 32,199
  • 5
  • 49
  • 61