This post was originally published on Coding Glamour.

ASP.NET MVC kent een vrij krachtige routing-engine om URL's te routen naar de actie die daarbij hoort. Naast puur URL's mappen kan je tevens constraints toevoegen om je routings wat te finetunen. Bijvoorbeeld praktisch voor de volgende situatie:

/koop/amsterdam/appartement-12345-straat-1/fotos/
-> moet naar ObjectController.Detail

/koop/amsterdam/appartement-12345-straat-1/reageer/
-> moet naar ObjectController.Contact

Door een constraint toe te voegen, kan je onderscheid maken tussen deze twee URL's:

// bijvoorbeeld
routes.MapRoute(
    "object-contact",
    "{aanbod}/{plaats}/{type}-{id}-{adres}/{pagina}",
    /* ... */,
    new { pagina = @"reageer|bezichtiging" });
// als pagina iets anders is dan reageer / bezichtiging matcht de route niet

Probleem: wanneer je URL's van binnen als volgt zijn (omdat ASP.NET voor elke URL in je website opslaat of er een fysieke file voor is, en bij miljoenen unieke URL's is dat een huge leak dat niet automatisch wordt geflusht):

/koop/?id=12345&pagina=reageer

zijn constraints niet meer mogelijk, want dit wordt niet ondersteunt op QueryString parameters. Daarom: de QueryStringConstraint! In gebruik heel simpel. Voor bovenstaande URL kan je de volgende route schrijven:

routes.MapRoute("object-contact",
    "{aanbod}",
    /* ... */,
    new { pagina = new QueryStringConstraint("bezichtiging|reageer") });

En de werking is exact hetzelfde als normaal. The codez:

public class QueryStringConstraint : IRouteConstraint
{
    private readonly Regex _regex;
    public QueryStringConstraint(string regex)
    {
        // ctor slaat de regex op voor further use
        _regex = new Regex(regex, RegexOptions.IgnoreCase);
    }
    public bool Match (HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        // zit de paramName uberhaupt in de QS
        if(httpContext.Request.QueryString.AllKeys.Contains(parameterName))
        {
            // doe dan check op de meegegeven regex
            return _regex.Match(httpContext.Request.QueryString[parameterName]).Success;
        }
        // anders return false
        return false;
    }
}