How to catch all areas using MapRoute

I am new to MVC and editing an existing application. Currently, I see the following in RouteConfig.cs:

public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Util", "util/{action}", new {controller = "util"}); routes.MapRoute( "Catchall", "{*url}", new {controller = "Main", action = "CatchUrl"}); } } 

Inside the main controller, there is logic that basically executes RedirectToRoute and sets the scope, controller, action, and querystring called location to a specific value.

 public class MainController : Controller { public ActionResult CatchUrl() { var agencyId = 9; var routeValues = new RouteValueDictionary { {"area", "area1"}, {"controller", "dashboard"}, {"action", "index"}, {"location", "testLocation"} }; return RedirectToRoute(routeValues ); } } 

This seems to work fine when you give it an invalid area, it goes over to the standard ones correctly.

I also see the CustomAreaRegistration.cs file:

 public abstract class CustomAreaRegistration : AreaRegistration { public override void RegisterArea(AreaRegistrationContext context) { context.MapRoute( AreaName + "Ajax", AreaName + "/{controller}/{action}", new { action = "Index" } ); context.MapRoute( AreaName + "ShortUrl", AreaName + "/{controller}", new {action = "Index"} ); } } 

I am having trouble understanding how Area routing works and how it knows how to get to the right controller.

Also, I'm trying to get it so that when visiting

/{area}/ it executes some logic and returns you to the correct controller. How CatchUrl Works

My attempt:

  routes.MapRoute( "AreaIndex", "{module}/", new {controller = "Main", action = "Index"}); 

MainController:

 public class MainController : Controller { public ActionResult Index() { var requestHost = HttpContext.Request.Url?.Host; var location= requestHost == "localhost" ? Request.QueryString["location"] : requestHost?.Split('.')[0]; var routeValues = new RouteValueDictionary { {"area", ControllerContext.RouteData.Values["module"]}, {"controller", "dashboard"}, {"action", "index"}, {"location", location} }; return RedirectToRoute(routeValues ); } public ActionResult CatchUrl() { var routeValues = new RouteValueDictionary { {"area", "area1"}, {"controller", "dashboard"}, {"action", "index"}, {"location", "testLocation"} }; return RedirectToRoute(routeValues ); } } 

And I get

No route in the route table matches the specified values.

I'm not sure why CatchUrl works, but mine doesn't.

+5
source share
2 answers

Actually, I am not getting what you ask, but just looking at the code is not the standard way to create / use Areas in MVC 3.4 and 5.

You do not need to write logic inside each controller and perform redirections.

In my RouteConfig , I usually have a default route mapping. And when you have needs in the Regions, you can right-click on the MVC web project in Visual Studio and click "Add โ†’ Region". This will create a folder with the name of the area inside the Areas folder right below the root of the web project. And in the area folder you should find AreaRegistration.cs for the area name and mappings.

 public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "default", url: "{controller}/{action}/{id}", defaults: new { controller = "dashboard", action = "index", id = UrlParameter.Optional }, namespaces: new[] { "Company.Project.Web.UI.Controllers" } ); } } 

And let me say that you want to create an area called "admin":

 public class AdminAreaRegistration : AreaRegistration { public override string AreaName { get { return "admin"; } } public override void RegisterArea(AreaRegistrationContext context) { context.MapRoute( "admin_default", "admin/{controller}/{action}/{id}", new { action = "index", id = UrlParameter.Optional }, namespaces: new[] { "Company.Project.Web.UI.Areas.Admin.Controllers" } ); } } 

Finally, I think a screenshot might be useful. enter image description here

- updates -

Based on the comments, if you want the route /apple?location=home go to the Apple Controller and its Home method, and the route /orange?location=dashbard to the Orange Controller and its Dashboard method, it's better to define the route in RouteConfig .

Ideally, you want to have something like this in RouteConfig :

  routes.MapRoute( name: "Area-CatchAll", url: "{area}?location={controller}" ); 

But this is not possible, since MVC will erroneously say: "The route URL cannot begin with the character" / "or" ~ ", and it cannot contain"? "symbol"..

Instead, you can redirect traffic to the controller, and you can define the area and location as parameters.

 routes.MapRoute( name: "Area-CatchAll", url: "{area}", defaults: new { controller = "Area", action = "Translate" } ); public class AreaController : Controller { // The {area} from route template will be mapped to this area parameter. // The location query string will be mapped to this location parameter. public ActionResult Translate(string area, string location) { // This also assumes you have defined "index" method and // "dashboard" controller in each area. if (String.IsNullOrEmpty(location)) { location = "dashboard"; } return RedirectToAction("index", location, new { area = area }); } } 

Again, I would not have created such a route to redirect traffic to areas if I do not need it.

0
source

I'm trying to make sure that when visiting

/ {area} / it does some logic and takes you to the right controller. How CatchUrl Works

First of all, let's clarify this. The catch-all route is not routed; it is redirected. It gives an HTTP 302 response to the browser, which tells the browser to look for a new location on your server. This is not very effective, because it requires an additional trip over the network, but this is the only way to change the URL in the browser from the server (if this is what you intend to do).

Routing, on the other hand, accepts the initial request and sends it directly to a specific resource (controller action) without additional round trip on the network and without changing the URL in the browser.

Your routes are already configured to use

 /Area/Controller 

to find the right controller here:

 public abstract class CustomAreaRegistration : AreaRegistration { public override void RegisterArea(AreaRegistrationContext context) { context.MapRoute( AreaName + "Ajax", AreaName + "/{controller}/{action}", new { action = "Index" } ); context.MapRoute( AreaName + "ShortUrl", AreaName + "/{controller}", new {action = "Index"} ); } } 

(if you have a subclass of this for each area that sets the AreaName ).

If you really want to redirect (not redirect) the URL /module/ to the DashboardController.Index method in the corresponding area, you will change your ShortUrl to make the controller optional, and by default it will be DashboardController .

 public abstract class CustomAreaRegistration : AreaRegistration { public override void RegisterArea(AreaRegistrationContext context) { context.MapRoute( AreaName + "Ajax", AreaName + "/{controller}/{action}", new { action = "Index" } ); context.MapRoute( AreaName + "ShortUrl", AreaName + "/{controller}", new { controller = "Dashboard", action = "Index" } ); } } 

This will send the URL /Foo/ to the Foo area method of DashboardController.Index , but send the URL /Foo/Bar/ to the Foo area BarController.Index .

The above assumes that you are diligent enough to ensure that none of your AreaName matches the names of the controllers in the unearthly part of your project. If they are, you can never reach these unearthly controllers without any additional configuration, such as route restriction.

The MainController.Index method is not needed at all (unless you have a specific reason why you want to change the URL in the browser).

0
source

Source: https://habr.com/ru/post/1272112/


All Articles