Search code examples
asp.net-mvcasp.net-mvc-5asp.net-mvc-routingattributerouting

MVC 5 Attribute Routing: Removing Unnecessary Route Attribute From Controller Actions


I have a requirement where the resources on the home controller should be accessed without the need to enter the name of the controller in the URL. For instance, index action should be loaded when I navigate to mysite.com/ and contact page should be loaded using mysite.com/contact and so on.

The controller below satisfies this requirement but I wonder if there is a way to remove Route attributes that have the same name as the controller action?

For example, using [Route("contact")] for action contact does not make sense. When I remove this route attribute, the URL is generated as mysite.com/home/contact whereas I want this to be mysite.com/contact.

[RoutePrefix("")] // Remove the name of the controller from the URL
public class HomeController : Controller
{ 


    public ViewResult Index()
    {
        return View("Index");
    }

    [Route("contact")]
    public ViewResult Contact()
    {
        return View("Contact");
    }

    [Route("about")]
    public ViewResult About()
    {
        return View("About");
    }

    [Route("terms-and-conditions")]
    public ViewResult TermsAndConditions()
    {
        return View("TermsAndConditions");
    } 
}

FYI, here is my route config:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapMvcAttributeRoutes();

        routes.LowercaseUrls = true;

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
} 

and the Application_Start event:

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }

Solution

  • Instead of using an empty value as the route prefix, I ended up using the route attribute on specific controller actions like the following:

    public class HomeController : Controller
    {
        public ViewResult Index()
        {
            return View("Index");
        }
    
        [Route("contact-us")]
        public ViewResult Contact()
        {
            return View("Contact");
        }
    
        [Route("about-us")]
        public ViewResult About()
        {
            return View("About");
        }
    
        [Route("terms-and-conditions")]
        public ViewResult TermsAndConditions()
        {
            return View("TermsAndConditions");
        }
    }
    

    This ensures that each defined route is accessed from the root of the site.