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 on that basically does a RedirectToRoute
and sets the area, controller, action, and querystring called location
to a certain 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 correctly goes to the default one.
I also see a file called CustomAreaRegistration.cs:
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 the Area routing works and how it knows how to go to the correct controller.
Furthermore, I am trying to get it so that when you visit
/{area}/
it does some logic and redircts you to the correct controller. Similar to 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 supplied values.
I am not sure why CatchUrl works and mine does not.
I actually don't get what you're asking, but by just looking at the code, that's not the standard way to create/use Areas
in MVC 3,4 and 5.
You shouldn't need to write logics inside each controller and do the redirects.
In my RouteConfig
, I usually just have the default route mapping. And when you have the needs for Areas, you can right click on the MVC web project in Visual Studio and click'Add -> Area'. That will create a folder with the area name inside an Areas folder right under the root of the web project. And within the area folder, you should find the 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's say 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" }
);
}
}
Lastly, I think a screenshot might be helpful.
-- updates --
Based on the comments, if you want the route /apple?location=home
to go to Apple Controller and its Home method, while the route /orange?location=dashbard
to go to Orange Controller and its Dashboard method, it's better to define a route in RouteConfig
.
Ideally you wish you can have something like this in RouteConfig
:
routes.MapRoute(
name: "Area-CatchAll",
url: "{area}?location={controller}"
);
But that's not possible as MVC will error out saying "The route URL cannot start with a '/' or '~' character and it cannot contain a '?' character.".
Instead, you can direct the traffic to a 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 wouldn't create route like that to redirect traffic to areas, if I don't have to.