Search code examples
asp.net-mvcasp.net-mvc-routing

Routing to controller with a required, non-empty Guid parameter


I would like to map http://localhost/Guid-goes-here to ResellerController and fire Index action of that controller only when Guid-goes-here is not the empty Guid.

My routing table looks like this:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Reseller",
        "{id}",
        new { controller = "Reseller", action = "Index", id = Guid.Empty }  
        // We can mark parameters as UrlParameter.Optional, but how to make it required?
    );

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

}

The action on the ResellerController looks like this:

public ActionResult Index(Guid id)
{
    // do some stuff with non-empty guid here
}

Once the application has started, navigating to http://localhost routes me to the ResellerController with the empty Guid as the argument to the Index action's id parameter.


Solution

  • public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
        routes.MapRoute(
            "Reseller",
            "{id}",
            new { controller = "Reseller", action = "Index", id = UrlParameter.Optional },
            new { id = @"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$" }
        );
    
        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );
    }
    

    or if you want a more robust constraint than some cryptic regex:

    public class GuidConstraint : IRouteConstraint
    {
        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            var value = values[parameterName] as string;
            Guid guid;
            if (!string.IsNullOrEmpty(value) && Guid.TryParse(value, out guid))
            {
                return true;
            }
            return false;
        }
    }
    

    and then:

    routes.MapRoute(
        "Reseller",
        "{id}",
        new { controller = "Reseller", action = "Index", id = UrlParameter.Optional },
        new { id = new GuidConstraint() }
    );