MVC redirect to default route

11,961

Solution 1

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

Solution 2

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.

Share:
11,961
Spikeh
Author by

Spikeh

I'm a Software Architect and DevOps specialist working in the Microsoft stack. I've been a software developer since 1998, working across a vast array of industries. I am fluent in C#, JavaScript, TypeScript, SQL, Powershell, HTML5 and CSS3, but also use many other frameworks, libraries and technologies day to day. My company focuses on improving business processes by analysing and implementing bespoke software to free up people's time. I also enjoy gaming, game development, cycling, hiking and nature.

Updated on June 04, 2022

Comments

  • Spikeh
    Spikeh almost 2 years

    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?