marcusstarnes
marcusstarnes

Reputation: 6531

How to get a trailing slash appended to page routes?

This is a near identical problem I am having to that of this query, albeit mine is a Web Forms scenario (using routing in .NET 4) as opposed to MVC.

Add a trailing slash at the end of each url?

The solution that someone mentions there is only half provided unfortunately as the link to the complete solution is broken.

At the moment, any trailing slash from my page routes is removed when I get the route url. This is especially problematic when I want to use the following type of inline syntax on my web form:

<a runat="server" href='<%$RouteUrl:RouteName=Posts %>'>

Again here the trailing slash is removed, despite it being present in my route table.

Can anyone please help provide a clean, efficient solution to this problem? Ideally, like the 'nearly complete' solution provided in the other Stack Overflow thread I've put above?

Upvotes: 2

Views: 2511

Answers (2)

valse
valse

Reputation: 11

to make the generated urls always lowercase and with a final trailing slash I add the TidyRouting library to my solution, then I simply replace the "MapRoute" method with the new "MapTidyRoute".

Upvotes: 0

marcusstarnes
marcusstarnes

Reputation: 6531

I have now found the solution to my original question. I found the following article which describes how you can ensure all of your Url's are in lowercase, so I just used this example code, but appended a trailing slash where it performs the ToLowerInvariant().

So, my 2 helper classes now look like this:

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);
    }
}

Within my global.asax, instead of using 'MapRoute' within my RegisterRoutes routine, I call my new MapRouteLowercase method instead (passing in the same parameters), e.g.

routes.MapRouteLowercase("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

The original article that I got this code from can be found here:

http://goneale.com/2008/12/19/lowercase-route-urls-in-aspnet-mvc/

Upvotes: 3

Related Questions