Why doesn't this route to the default action? - c#

So I have this route mapped:
routes.MapRoute(
"Solutions",
"{lang}/Solutions/{controller}/{action}",
new { lang="en-US", controller = "WhatWeDo", action = "Index"}
);
When I go to"
/en-GB/Solutions/SolutionA/Index/
It routes just fine, but
/en-GB/Solutions/SolutionA/
Doesn't route at all. However, if I take out the lang parameter, so the route looks like
routes.MapRoute(
"Solutions",
"Solutions/{controller}/{action}",
new { controller = "WhatWeDo", action = "Index"}
);
and I go to
/Solutions/SolutionA/
It routes just fine. Any ideas? I'd like to not have to specify the default action all the time for this route. Thanks.

What order are you defining your routes in global.asax, this could have something to with the issue but my initial guess is that it's matching the default route as such
controller: en-GB
action: Solutions
id : SolutionA
What you might be able to do is setup some sort of regular expression matching on your routes to exclude your language from the "default" route? Try this link for more information about using regex for route filtering http://www.iridescence.no/post/Defining-Routes-using-Regular-Expressions-in-ASPNET-MVC.aspx

Related

MVC Attribute Routing RoutePrefix does not work with default routing

I have a work-around, but I'd really like to know why this doesn't appear to work in MVC. (.Net 4.6.1)
I have a controller which I want to use a RoutePrefix:
[RoutePrefix("entry")]
public class DefaultController : Controller
{
[HttpGet]
[Route(), Route("Index")]
public ActionResult Index()
{
// ...
}
}
In the route config:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "entry", action = "index", id = UrlParameter.Optional }
The issue is that with this configuration, running under local IIS to test, navigating to "localhost/testApp/entry" works, "localhost/testApp/entry/index" works, however the default "localhost/testApp/" results in a 404.
This has been doing my head in because on a fresh project with the default controllers and a default set to "home" and "index" the "localhost/testApp" would render Home/Index without an issue.
I narrowed it down to the RoutePrefix being the issue. If I remove the RoutePrefix and change the defaults to: new { controller = "default", action = "index", id = UrlParameter.Optional }
Then "localhost/testApp" works, but obviously this requires using /default for other routes rather than /entry.
Also, if I leave the prefix in (switching the default controller back to "entry") and add Route("~/") to the Index method, then "localhost/testApp" also works as according to the doco that a ~ route overrides the route prefix.
I'd like to know if there is an explanation why RoutePrefix doesn't seem to play nice with default routing? I'm fine with adding a ~/ route for that default action, but it seems I'm missing some understanding on how RoutePrefix is intended to be used.
Action attribute routing has the highest priority. If you use it only route attributes will be working, everything else will be ignored. You can to one action as many routes as you need.
Since you have 2 variants - Route() and Route("Index") it works only for 2 urls -"localhost/testApp/entry" and "localhost/testApp/entry/index".
if you remove Route() it will work only for one url-lcalhost/testApp/entry/index".
If you add 3rd Route("~/") it will work for 3rd url "localhost/testApp"
Sign ~ means that any prefixes should be ignored, it starts from root.
So you can not use default conventional routing on Index action since it is only obeys routing attributes.
Also, you have a controller [RoutePrefix("entry")] attribute routing too and it that next highest priority and because of this it overrides your convention routing in the config file. This is why default routing doesn't work for this controller and it doesn't go to Index automaticaly. To make default route work you need to remove route prefix and fix web config
defaults: new { controller = "default", action = "index", id = UrlParameter.Optional }
Current default controller = "entry" doesn't exist at all.
So you have two choices to have Index as default route action - remove all attribute routing and lost all another extra routes or add one more.
Thanks to Serge for helping point out a bad assumption I had about [RoutePrefix]. The problem here turns out that [RoutePrefix] is not a substitute name for a controller, (though that is how it behaves on the surface) but rather a prefix to each individual action. While the mapping in the URL will be identical:
Example 1:
public class EntryController
{
public ActionResult Index() { ... }
}
Example 2:
[RoutePrefix("Entry")]
public class DefaultController
{
[Route("Index")]
public ActionResult Index() { ... }
}
Both of these examples would resolve "localhost/testApp/entry/index", however only the first mapping would be considered as a match for {controller}/{action} and resolve a "defaults" mapping of "entry/index".
So if an action /w Attribute-based routing needs to be made a root default you need to explicitly declare it as the root using [Route()] if there is no [RoutePrefix], or [Route("~/")] if there is a [RoutePrefix]. since it won't be included in the {controller}/{action} routing. (Verified by removing the Default {controller}/{action} routing entirely).

How do I change the route of an ASP.NET MVC controller?

I have a typical ASP.NET MVC controller, but I just want to change its route. The default route now is:
Blog/{controller}/{action}/{id}
I want to change the route of a specific controller to
Blog/Admin/{controller}/{action}/{id}"
I tried to achieve this by adding the Route, RouteArea and RoutePrefix attributes to the controller but without any success.
How can I achieve this?
Add this route prior to the default
routes.MapRoute(
name: "BlogAdmin",
url: "Blog/Admin/{action}/{id}",
defaults: new { controller = "YourSpecificControllerName", action = "Index or other default action name", id= UrlParameter.Optional });
Since this is for a specific you don't need {controller} part in your url. If you still want to specify it change the url argument to "Blog/Admin/YourSpecificControllerName/{action}/{id}" where YourSpecificControllerName is the name of your controller.
Also since the order of rote registration matters make sure that this route registered prior to the the default one

How can I route requests to a page controller for routes that don't exists in ASP.NET MVC 4

How can I route requests to a default PageController for routes that do not map to a controller or action? But for routes that do match a controller or action, have those behave as normal, using ASP.NET MVC?
Basically I have a CMS backend that I have developed and I need to be able to inspect the route, to see if it matches a route for a page, stored in the database and if so, forward the request to the default PageController, which handles loading the pages content from the database. There are also CORE pages, that do have their own Controllers and Actions defined, and if you enter a route that doesn't match a pages route in the database, I need it to revert to the default behavior of ASP.NET MVC and look for the {controller}/{action}.
I have searched and searched online, with not much luck finding how I could do this. Any help would be greatly appreciated.
Set your routes up so the ones for existing controllers and actions are first, then have a catchall that maps to your PageController:
// More specific routes go here
routes.MapRoute(
null,
"{controller}/{action}/{id}", // URL with parameters
new { action = "Index", id = UrlParameter.Optional }, // Don't put a default for controller here
// You need to constrain this rule to all of your controllers, so replace "ControllerA" with an actual controller name, etc
new { controller = "ControllerA|ControllerB|ControllerC" }
);
routes.MapRoute(
null,
"{*path}",
new { controller = "Page", action = "Index" }
);
Anything that isn't matched by the first rule and any rules you put before it will fall back to your page controller, with the path in a path parameter on your index action method.

Understanding routing in ASP.NET MVC

I'm trying to wrap my mind around the way ASP.NET MVC implements routing.
From what is my current understanding, it seems my route string much have a "{controller}" and "{action}", otherwise it doesn't work?
How would I define the route that using a SearchController and Search action taking both SearchKeywords and SearchCaseSensitive arguments had the following URL?
domain/SearchKeywords/CaseSensitive
Even simpler, how do I map domain to controller SearchController and to Search?
From what is my current understanding,
it seems my route string much have a
"{controller}" and "{action}",
otherwise it doesn't work?
Values for the controller and action tokens are required. You have 2 options for providing the values:
1) Using {controller} and {action} tokens on the URL template. e.g.:
routes.MapRoute(null, "{controller}/{action}");
2) Using default values for controller and action. e.g.:
routes.MapRoute(null, "some-url",
new { controller = "Search", action = "Search" }
);
How would I define the route that
using a SearchController and Search
action taking both SearchKeywords and
SearchCaseSensitive arguments had the
following URL?
domain/SearchKeywords/CaseSensitive
The URL host (or domain) is not considered by the routing system, only the application relative path. You can do this:
routes.MapRoute(null, "{SearchKeywords}/{CaseSensitive}",
new { controller = "Search", action = "Search" }
);
You can also provide defaults for SearchKeywords and CaseSensitive, if you want to make either of them optional.
You can add controller = "Search", action = "Search" to the defaults (the last parameter).
The routing engine will use values in defaults to fill in for parameters that aren't in the URL.
If you want to have a 'domain' parameter in your route, you must put this at the top of the route registration. The 'domain' parameter in the second anonymous object is a constraint and here is set to be a regular expression that tests to see if the domain is either of the possible domains "DefaultDomain" or "OtherDomain".
routes.MapRoute("DomainRoute", "{domain}/{controller}/{action}",
new {domain = "DefaultDomain", controller = "Search", action = "Search"},
new {domain = "DefaultDomain|OtherDomain"});

URL routing in asp.net mvc

i have a ApplicationController class with an action called Admin
so my url is www.mysite.com/Application/Admin
is there anyway i can have the routing be www.mysite.com/Admin and go to this method.
i know i can do this by creating an AdminController but for this one function i thought it was easier to just put in another controller
Put this above your default route:
routes.MapRoute(
"ShortRoute",
"{action}",
new { controller = "Application", action = "Index"}
);
You can set the Application controller and the Admin method as the default controller and action, using parameter defaults:
routes.MapRoute(
"Default", // Route name
"{action}", // URL with parameters
new { controller = "Application", action = "Admin" }
);
If this is your last route, it will match any request that does not have a controller name and an action name in it. In this particular example, even a request without an action will execute your Admin action, since it's the default action.
Note that routes with parameter defaults can create strange behavior in your existing routes, if you have any. You can always use the ASP.NET MVC Routing Debugger to test which routes match a given URL.

Categories

Resources