2

I'm having problems with the routings in my MVC project not working...

I want all my views in the Views > Shared folder like this:

Error.cshtml (default)
Index.cshtml (default)
Overview.cshtml (custom that I made)
Recordings.cshtml (custom that I made)

I've then created one shared controller to handle all views like this:

public class SharedController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Error()
    {
        return View();
    }

    public ActionResult Overview()
    {
        return View();
    }

    public ActionResult Recordings()
    {
        return View();
    }
}

My RouteConfig.cs looks like this:

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

    // Map to specific pages under Shared controller:
    routes.MapRoute("SharedPages", "{action}/{id}",
        new { controller = "Shared", action = @"Overview|Recordings", id = UrlParameter.Optional });

    // Use the default rout for all other pages:
    routes.MapRoute("Default", "{controller}/{action}/{id}",
        new { controller = "Shared", action = "Index", id = UrlParameter.Optional }
    );

    // Show the Error page for anything else (404):
    routes.MapRoute("Error", "{*url}",
        new { controller = "Shared", action = "Error" }
    );
}

I want the routing to work like this:

://(url)/ (root - no action specified) --> Shared/Index.cshtml
://(url)/Index --> Shared/Index.cshtml
://(url)/Overview --> Shared/Overview.cshtml
://(url)/Recordings --> Shared/Recordings.cshtml
://(url)/whatever (or if an error occurs) --> Shared/Error.cshtml

But it's not working as expected. If I go to ://(url)/ (root), I get a HTTP 404 - The resource cannot be found. If I go to for example ://(url)/Overview, it's working fine.

How can I make it work like I want?

Nkosi
  • 235,767
  • 35
  • 427
  • 472

1 Answers1

1

The order of how you map route is important and first matched route wins. That means that even if there is no resource there one it matches the route it will use it.

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

    // Use specific rout for all other pages:
    routes.MapRoute("WhateverA", "WhateverA/{action}/{id}",
        new { controller = "WhateverA", action = "Index", id = UrlParameter.Optional }
    );

    routes.MapRoute("WhateverB", "WhateverB/{action}/{id}",
        new { controller = "WhateverB", action = "Index", id = UrlParameter.Optional }
    );

    // Map to specific pages under Shared controller:
    routes.MapRoute("RootPages", "{action}/{id}",
        new { controller = "Shared", action = "Index", id = UrlParameter.Optional });

    // Show the Error page for anything else (404):
    routes.MapRoute("Error", "{*url}",
        new { controller = "Shared", action = "Error" }
    );
}

The problem with the Default and SharedPages routes is that they conflict with each other. You may need to provide specific routes for other controllers if they exist. Other wise the other option is to use Attribute Routing for the other controllers and convention-based routing for your root routes and error

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

    //Attribute routing
    routes.MapMvcAttributeRoutes();

    // Map to specific pages under Shared controller:
    routes.MapRoute("RootPages", "{action}/{id}",
        new { controller = "Shared", action = "Index", id = UrlParameter.Optional });

    // Show the Error page for anything else (404):
    routes.MapRoute("Error", "{*url}",
        new { controller = "Shared", action = "Error" }
    );
}

With controllers decorated accordingly

[RoutePrefix("WhatEver")]
public class WhatEverController : Controller {
    //GET whatever
    [HttpGet]
    [Route("")]
    public ActionResult Index() { ... }
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • Anything with zero, 1, 2 or 3 segments in the url will match the `Default` and the `SharedPages` route will never be hit –  Feb 16 '17 at 01:46
  • @StephenMuecke, Yeah because of the defaults. good catch. will have to re-look at this answer. – Nkosi Feb 16 '17 at 01:47
  • If OP wants to omit the controller name, then I a specific route is required for each method, or a route constraint (assuming there are other controllers) –  Feb 16 '17 at 01:51
  • I had gotten around a similar situation by having to use specific routes for each controller. luckily that project did not have many controllers. I was just about to suggest that – Nkosi Feb 16 '17 at 01:52