5

Here's my default route:

routes.MapRouteLowercase(
                "Default",
                "{country}/{controller}/{action}/{id}",
                new {
                    country = "uk",
                    controller = "Home",
                    action = "Index",
                    id = UrlParameter.Optional
                },
                new[] { "Presentation.Controllers" }
                );

As we know, when someone visits www.domain.com/ MVC's routing will determine the default controller and action to execute based upon the above route, but the URL will remain the same. Is there a built in or elegant way to perform a 301 redirect from www.domain.com/ to www.domain.com/uk/{controller}/{action}/ for every route that uses defaults?

1
  • You could do a redirect from your default controller e.g. index action Commented Jul 17, 2012 at 9:20

2 Answers 2

15

I have created a custom route handler that does the redirect at the route level. Thanks to Phil Haack.

Here is the complete work.

Redirect route handler

public class RedirectRouteHandler : IRouteHandler
{
    private string _redirectUrl;

    public RedirectRouteHandler(string redirectUrl)
    {
        _redirectUrl = redirectUrl;
    }

    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        if (_redirectUrl.StartsWith("~/"))
        {
            string virtualPath = _redirectUrl.Substring(2);
            Route route = new Route(virtualPath, null);
            var vpd = route.GetVirtualPath(requestContext,
                requestContext.RouteData.Values);
            if (vpd != null)
            {
                _redirectUrl = "~/" + vpd.VirtualPath;
            }
        }

        return new RedirectHandler(_redirectUrl, false);
    } 
}

Redirect http handler

public class RedirectHandler : IHttpHandler
{
    private readonly string _redirectUrl;

    public RedirectHandler(string redirectUrl, bool isReusable)
    {
        _redirectUrl = redirectUrl;
        IsReusable = isReusable;
    }

    public bool IsReusable { get; private set; }

    public void ProcessRequest(HttpContext context)
    {
        context.Response.Status = "301 Moved Permanently";
        context.Response.StatusCode = 301;
        context.Response.AddHeader("Location", _redirectUrl);
    }
}

Route extensions

public static class RouteExtensions
{
    public static void Redirect(this RouteCollection routes, string url, string redirectUrl)
    {
        routes.Add(new Route(url, new RedirectRouteHandler(redirectUrl)));
    }
}

Having all these, I can do something like this while mapping routes in Global.asax.cs.

routes.Redirect("", "/uk/Home/Index");

routes.Redirect("uk", "/uk/Home/Index");

routes.Redirect("uk/Home", "/uk/Home/Index");

.. other routes
Sign up to request clarification or add additional context in comments.

1 Comment

Should the routes.Redirect go before all other routes (ex MapRoute)? Would this work for old .aspx page routing? foo.aspx -> /foo
7

In my projects, I usually have "IndexRedirect" as default action in my route (whose URL will never be visible) which does nothing but redirecting to the "real" index page (whose URL will always be visible).

You can create this action in a base class of all your controller classes.

2 Comments

This was the best solution!
A novel idea, wish I had thought of that myself!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.