Possible to create catch all route for a controller? - c#

For a specific controller, is it possible to route any action that does not exist to the index?
For example if I have
fashionController/
fashionController/shoes/
fashionController/bags/
fashionController/otherStuff/
I want to be able to only setup the Index view & action and that anything else will just use the Index automatically without having to create separate views/actions for anything else.

Yes.
There is no requirement that controller or action name are part of Url. For example you can route all "fashion/*" to the same action with following route.
routes.MapRoute(
"AllToIndex",
"fashion/{argument1}",
new { controller = "fashion", action = "Index", argument1 = "" }
);
Note that routes matched in order they are added, so if you register this route after default "{controller}/{action}" one it will never be matched. Generally more specific routes should go before more generic once and last should be optional "cath'em all" one with "{*path}" math.

Related

Add route prefix to all actions in controller using one attribute

Here is my controller
public class SpecializationsController : Controller
{
public ActionResult Action1()
{
//body
}
public ActionResult Action2()
{
//body
}
Default url for Action1 is of course /Specialization/Action1. I want to add prefix to all Actions in my controller to make my ulr like /prefix/Specialization/Action1.
I tried to add [RoutePrefix("prefix")] to my controller but it doesn't work. I would like to avoid adding [Route] attribute for each action in my controller. So how can I add this prefix?
I would create Areas:
Areas are an ASP.NET MVC feature used to organize related functionality into a group as a separate namespace (for routing) and folder structure (for views). Using areas creates a hierarchy for the purpose of routing by adding another route parameter
I know you may think this is an overkill for simply having a "prefix" but the reason I suggest this approach is because if you have the need to add a "prefix", chances are you have the need to separate the views, models etc. as well.
You need to add a route to your route collections instead of using route attributes
routes.MapRoute(
"Route",
"prefix/{controller}/{action}",
new { controller = "Specializations", action = "Index" });

Request matched multiple actions resulting in ambiguity for actions with different parameters in ASP.NET 5 / MVC 6

I have a simple route in my project:
routes.MapRoute(
name: "api",
template: "api/{controller}/{action}");
In my controller I have two actions:
[HttpGet]
public string Get(string value)
{
return value;
}
[HttpGet]
public string Get(int id)
{
return id.ToString();
}
Now when I try to do a url like api/controller/get?id=1 it does not work because the framework cannot distinguish between two actions. As far as I remember it did work pretty well in ordinary web api because it's obvious that this url matches only one of the actions based on it's parameter. Did I do something wrong or it's not supported in the new MVC6?
Did I do something wrong or it's not supported in the new MVC6?
MVC Action Selector dosen't regard Action's parameters during select action. Therefore you can't have two actions correspond one route template. Except e.g actions have different Action Constraints (HttpPost, HttpGet).
Choose action logic in code.
In theory choosen logic between some actions based on parameters have to be into SelectBestActions method, but it do nothing

MVC URL path extensions

I was just wondering whether its possible to have something like this: I have an Area named Admin and a Controller named 'Edit'. Within this controller I have my Index() which simply lists a bunch of hyperlinks that is treated by the 'Brand' action.
Therefore my url so far is: Admin/Edit/{Brand}.
My question is whether it is possible to have for example: Admin/Edit/{Brand}/Create (as well as edit and delete). This isn't to delete brands, its just to create things within those brands?
I approach that my approach may be misguided and this may necessitate being split into multiple controllers or whatever so don't think that I would like a workaround to make it work this way.
You could define the following route in your area registration:
context.MapRoute(
"Admin_default",
"Admin/{controller}/{brand}/{action}",
new { action = "Index" }
);
And if you wanted to have other controllers than Edit in this area which have the default route, you could register 2 routes but you will have to define a constraint for the {brand} token or the routing engine won't be able to disambiguate between a brand and a controller action name.

MVC 3 AREAS - Hierarchial workflows

For the project that I am working on, we have companies. Companies have contacts and facilities. Based on the business rules, the flow is you select a company to access the contacts or facilities.
EDIT:
Entities are companies, facilities and contacts.
As each entity has it's own workflows, so they all have their one AREA in the code. What would be a clean way to make sure tha the routing url would be something like below:
/Company/1234/contact/456
/Company/1234/facility/679
If there was a way to next areas that would seem like a good way, but could make the code messy.
I don't think you need to use areas
To do what you want could be done by defining routes in the global.asax for each "subcontroller" to help the engine. (I have assumed that Contact and Facility are separate controllers?)
It does mean being very specific about what pattern goes to what route, but I think the below will do what you need.
Add these 2 new routes in the global asax (above the default route):
routes.MapRoute(
"ContactRoute", // Route name
"Company/{id}/Contact/{action}/{contactId}", // URL with parameters
new { controller = "Contact", action = "Index"
} // Parameter defaults
);
routes.MapRoute(
"FacilityRoute", // Route name
"Company/{id}/Facility/{action}/{facilityId}", // URL with parameters
new { controller = "Facility", action = "Index"
} // Parameter defaults
);
I'm not 100% on the code, you might need to define the contactId and facilityId as optional, but I hope it gives you an idea?

Why does RedirectToRoute("Default") not redirect to the root?

Given these routes:
routes.MapRoute("Test", "test", new { controller = "Test", action = "Index" });
routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
If I call RedirectToRoute("Default") from the Index action of the TestController it redirects to /test but I expected it to redirect to /
I checked the result of calling RedirectToRoute("Default") before returning it during a debugging session.
RedirectToRouteResult result = RedirectToRoute("Default");
It has a property RouteName with a value "Default" and a property RouteValues with no elements (Count = 0). I checked using Reflector, and null is passed internally as the RouteValueDictionary.
Again, I would expect that given the defaults for the route defined in my application, it would redirect to Index view on the HomeController.
Why doesn't it redirect to /?
The RouteValueDictionary filled in to the current action is being used to fill in the Controller, Action, ID. This is usually the functionality you want and lets you do things like <%:Html.ActionLink("MyAction")%> without needing to specify your controller in a view.
To force it to the complete fall back default just use:
RedirectToRoute("default", null");
The second argument is for your routevalues and by specifying it you override the preexisting values.
However I would say the preferred way would be to have a Home route which will not take any parameters. This means your redirects will not need a load of nulls floating around and a call to RedirectToRoute("Home") is also nice and explicit.
Edit
This is a really old answer and as a couple of people have mentioned doesn't seem to have been working for them. For what it's worth I now don't use this pattern and explicitly override controller and area when I need to break out. Not only does it apparently work better but when you come back to the code it's good to see explicitly that you're coming out of this context and mean to blank out certain routevalues.
For the record I have also tended more towards named route based URL generation over convention based generation.
I don't think that "null" parameter Chao mentions has ever worked for me. Perhaps it did in prior MVC versions, but now in MVC 5.2 this is the only way I can get it to work:
RedirectToRoute("Default", new { controller = "", action = "" });
Without looking at the actual code to see what is going on it can be a bit tricky to know why, but this forum post does shed some light. The answerer says that under the covers it might be creating a RouteValueDictionary which would contain the controller and action you are currently in, which in your case would be a controller of Test and an action of Index. Then, when you call RedirectToRoute("Default"), the controller and the action in the RouteValueDictionary will be used when matching the default route and you will be taken to the Index action in your Test controller.
Now you could always do a Redirect("/") to take you to the main page of your site.

Categories