MapRoute template syntax for multiple prefix rules - asp.net-core-mvc-2.0

I have several APIs (5 currently) being served from the same MVC Core application.
I'm trying to define a maproute like this, but I don't know the correct syntax, or if it even exist:
routes.MapRoute(
name: "apiDefault",
template: "{" + string.Join("|", _apis) + "}/{*url}",
defaults: new { controller = "Home", action = "ApiNotFound" });
I could add 5 identical rules, but I would prefer if I could avoid it.
Thank you in advance!

Solution was quite simple. I defined the prefix as a custom constraint:
routes.MapRoute(
name: "apiDefault",
template: "{api}/{*url}",
defaults: new { controller = "Home", action = "ApiNotFound" },
constraints: new RouteValueDictionary
{
{ "api", string.Join("|", _apis) }
});

Related

Is it possible to match any previously unmatched url in ASP.NET MVC 6 route mapping?

I want to custom unmatched 404 page, I specified the "template" parameter as "{*}" in router "all", aiming to catch all urls (such as "http://localhost:12345/aaa/bbb/ccc/ddd/") that are not matching to the "default" router. Is there any way to do so?
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{Controller:regex((?i)^((?!Error).)*$)}/{Action}/{id?}",
defaults: new { Controller = "Home", Action = "Index" })
//TODO: This Route is not working as expected.
.MapRoute(
name: "all",
template: "{*}", //<---------
defaults: new { Controllers = "Error", Action = "Unknown" });
});
You can try it like this "{*url}" or "/{*url}". I think it needs something after a wildcard so you could use the caught url as a parameter.

How is Url.Action picking routes?

I have these 2 routes:
routes.MapRoute(
name: "First",
url: "{controller}/{id}/{action}",
defaults: null,
constraints: new { id = #"^\d+$" }
);
routes.MapRoute(
name: "Second",
url: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
The route handling works ok but the url generation does not work fine in all cases.
I'm trying to use the #Url.Action("Index"):
when I'm on "Home/List" it generates "Home/Index"
when I'm on "Home/1/Edit" it generates "Home/1/Index"
I can see a pattern here, but I don't know why it generates the urls like this, I would like to have the second form only when I explicitly pass in the "id" parameter.
I can use the following to solve my problem, but I'm not so excited about passing in route names:
#Url.RouteUrl("Second", new { action = "Index" })
Is there anything else I can do to have the helper work as expected?

Hard Code MVC Route Value

I'm trying to utilize the HTML.ActionLinks in MVC. I have a route definition like so:
routes.MapRoute(
name: "RestaurantCommon",
url: "Rest/{siteName}/Admin/{action}/{id}",
defaults: new { controller = "AdminCommon", action = "Promotions", id = UrlParameter.Optional }
);
Is it possible to use ActionLinks to keep the "Rest" and "Admin" in the folder structure? Below is what I have. It works but doesn't keep the pattern I want (it works because of a default below the one I defined above)
<li>#Html.ActionLink("Burger Star", "Promotions", "AdminCommon", new { siteName="BurgerStar" }, null)</li>
Use #RouteLink
#Html.RouteLink("Burger Star", "RestaurantCommon", new { siteName = "BurgerStar" })

Aspnet MVC 4 routing challenges

I want customized routing based on Department Name and Product Name. for example /mobiles/nokia-6303
when i am calling products page it's working fine. when i am calling other than product page like Home page by default following controller and action method is executing
defaults: new { controller = "ContentPage", action = "ProductDetail" }
how to avoid this problem?
routes.MapRoute(
name: "ProductDetailsPage",
url: "/{DepartmentName}/{ProductName}",
defaults: new { controller = "ContentPage", action = "ProductDetail" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
Thanks in advance
Rajesh
Your routes are exactly the same. It's impossible to differentiate between /DepartmentName/ProductName and /Controller/Action. You need something else in the URL in order to differentiate between the two things, e.g.:
routes.MapRoute(
name: "ProductDetailsPage",
url: "/Products/{DepartmentName}/{ProductName}",
defaults: new { controller = "ContentPage", action = "ProductDetail" }
);
And then navigate to /products/departmentname/productname
Perhaps a slight modification to Ant P's excellent suggestion would be to place the text in between department name and product name?
routes.MapRoute(
name: "ProductDetailsPage",
url: "/{DepartmentName}/Products/{ProductName}",
defaults: new { controller = "ContentPage", action = "ProductDetail" }
);
Or to have details afterwards:
routes.MapRoute(
name: "ProductDetailsPage",
url: "/{DepartmentName}/{ProductName}/details",
defaults: new { controller = "ContentPage", action = "ProductDetail" }
);
Either of these URL approaches might get past your 'SEO team', since it is including soemwhat relevant information within the URL.
As other answers mention, the routing system can't differentiate between {controller}/{action} and {DepartmentName}/{ProductName}.
You can solve this problem by adding a constraint to a route. If a constraint isn't fulfilled, the route won't match the URL. You will probably need to create a custom implementation of IRouteConstraint. I see two options:
Create a constraint for the {controller}/{action} route, that will contain a list of possible names of controllers, that should be use the default URL pattern
Create a constraint for the {DepartmentName}/{ProductName} route, that will check the database (or some in-memory cache) whether department name and product name match some product
finally i have fixed this issue using routing config itself, please find the below code.
foreach (var d in departmentTranslation)
{
routes.MapRoute(
"ContentPage" + d.Name,
d.Name + "/{ProductName}",
new
{
controller = "ContentPage",
action = "ProductDetails",
id = d.DepartmentId,
ProductName = UrlParameter.Optional
});
}

asp.mvc 4 more routes

I have an web app build with asp.net MVC 4.
I want to have the following 3 types of routes:
/action
/action/id
/id/id2
In global.asax I have changed the routes as it follows:
routes.MapRoute(
name: "Without Action",
url: "{id}/{id2}",
defaults: new { controller = "Home", action = "City_Category" },
namespaces: new[] { "Namespace.Controllers" }
);
routes.MapRoute(
name: "Without Controller",
url: "{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "Namespace.Controllers" }
);
But when I try an {action}/{id} it goes to the first route defined in global.asax. Works only if url is {action} or {id}/{id2}.
How can I make to work all 3 routes?
Thanks!
If {id} and {id2} will always be numeric, you can add a constraint to the route so that it will only kick in when those values are digits:
routes.MapRoute(
name: "Without Action",
url: "{id}/{id2}",
defaults: new { controller = "Home", action = "City_Category" },
new { id = #"\d+", id2 = #"\d+" }
namespaces: new[] { "Namespace.Controllers" }
);
Another idea is to use http://attributerouting.net/, you can define routes by attributes, which is a very easy to define routes, especially if you end up with a lot of complex routes. I had about 30 route definitions and a lot of comments how the url looks like for each action. I could remove all comments and route definitions with these attributes.

Resources