Search code examples
c#asp.net-mvcroutesurl-routingasp.net-mvc-routing

Prevent access to unwanted default URLs in Routing


My project consists of areas which all have a default Index action.
This action, though, I want only to be accessible with the following URL pattern:

/{area}/

Its controller is DefaultController and the action name is Index.
Right now I seem to be able to access this index action with both the following URLs:

/import/Default and /import/Default/Index. Only /import or /import/ should be a valid URL in this example case.

Is there any way to prevent this?

ImportAreaRegistration.cs

public override void RegisterArea(AreaRegistrationContext context) 
{
   context.MapRoute(
         name: "Import_default",
         url: "import/{controller}/{action}",
         defaults: new { controller = "Default", action = "Index" },
         namespaces: new string[] { "Tax.Areas.Import.Controllers" }
   );
}

DefaultController.cs

namespace Tax.Areas.Import.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;

    [RouteArea("import")]
    public class DefaultController : Controller
    {
        public ActionResult Index()
        {
            ...
        }
    }
}

Solution

  • You can prevent unwanted routes using the IgnoreRoute extension method on the RouteCollection. It is important that this step be done before you register your area routes so they are executed in the proper order.

    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
            // Ignore unwanted routes first
            routes.IgnoreRoute("{area}/Default");
            routes.IgnoreRoute("{area}/Default/Index");
    
            // Then register your areas (move this line here from Global.asax)
            AreaRegistration.RegisterAllAreas();
    
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }
    }
    

    Alternatively, you can ignore routes within the RegisterArea method by doing the following:

    public override void RegisterArea(AreaRegistrationContext context) 
    {
        context.Routes.Add(new Route("import/Default", new StopRoutingHandler()));
        context.Routes.Add(new Route("import/Default/Index", new StopRoutingHandler()));
    
        context.MapRoute(
            name: "Import_default",
            url: "import/{controller}/{action}",
            defaults: new { controller = "Default", action = "Index" },
            namespaces: new string[] { "Tax.Areas.Import.Controllers" }
        );
    }