I want to change the site I'm working on so that when someone creates an article, the path would be "Articles/ViewArticle/2016-10-04/test" instead right now it's just "Articles/ViewArticle/test". When I implemented it, I got an instant 404.
I tried creating this route before & after the Default Route, but still no go:
routes.MapRoute(
name: "ArticlesDefault",
url: "{controller}/{action}/{date}/{id}",
defaults: new { controller = "Articles", action = "ViewArticle", date = UrlParameter.Optional, id = UrlParameter.Optional }
);
I should note that the "id" is actually stored in the database as [date]/ArticleTitle.
Would anyone be able to help?
Use attribute routing instead. By using attribute routing you can construct the routes using the values of parameters passed to action methods.
More information on attribute routing is here https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/
if you do not want to use attribute routing, you can use constraints parameter of MapRoute method
Edit:
You can try any one of following approach
Without using attribute routing. I assume that your Id is in the form of {date}/articleTitle
routes.MapRoute(
name: "ArticlesDefault",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Articles", action = "ViewArticle" },
constraints: new { id = “\\d+” });
Using attribute routing. Best approach will be to separate article date and article title into two distinct parameters. Then you can use the following code.
[Route("Articles/ViewArticle/{articleDate:datetime}/{articleTitle}")]
public ActionResult ViewArticle(string articleTitle, DateTime articleDate)
{
//your action code goes here
}
Related
I'm trying to achieve this goal of changing my apps routes to look like this:
hxxp://host/MyController/Widgets/3/AddWhatsit
The view for this route would help a user add a Whatsit to Widget 3.
Similarly, I would expect the route to create a new Widget to be:
hxxp://host/MyController/Widgets/Create
I've created separate routes to try and facilitate this. They are:
routes.MapRoute("DefaultAction",
"{controller}/{action}",
new {controller = "Home", action = "Index"});
routes.MapRoute("Default",
"{controller}/{id}/{action}",
new {controller = "Home", action = "Index", id = UrlParameter.Optional});
The problem I'm having is that when I browse to the Index page for Widgets (/MyController/Widgets, matching the "DefaultAction" route) Any ActionLinks that would introduce a new url parameter that's not part of that route gets turned into a querystring value. So, for example, the edit link for Widget 3 would render as:
Widget/Edit?id=3
instead of (what I would prefer):
Widget/3/Edit
I guess I understand that I'm messing things up by not putting my (optional) id param at the end of the route.
Should I suck it up and just leave id at the end of the route?
It is possible to achieve this. To get anchor link looking like /Home/1/Index, set routes like:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Custom",
url: "{controller}/{id}/{action}"
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
And then, in the View:
#Html.ActionLink("Here", "Index", "Home", new { id = 5 }, null)
And you get link rendered like this:
Here
Quirk is to constrain custom route. I removed defaults in this case, they do not make sense. And order of routes, of course.
I believe you need to change the order of your routes. Remember, that MVC looks down the route list and picks the First matching route. Your second route with the ID parameter is more specific and as such, should come first in your routing table.
Even though you have specified an ID parameter in your ActionLink, you have also specified a controller and an action. Therefore, the first route is being chosen by the RoutingEngine.
Lastly, remove the optional parameter for the ID attribute. Since you want that route to be chosen when you have an Id, then you do not want that to be an optional parameter, you want it to be required to match that route.
routes.MapRoute("Default","{controller}/{id}/{action}",
new {controller = "Home", action = "Index"});
routes.MapRoute("DefaultAction", "{controller}/{action}",
new {controller = "Home", action = "Index"});
I am using RegisterRoutes method in Global file to route user url to actual url.
routes.MapRoute("Blog",
"blog/dp/{id}",
new { controller ="Blog", action = "Details" });
As you might have guessed, Blog is the controller and Details is its action.
So the problem is that the following code does not generate my desire URL which has dp word in its url.
By the way, I don't want to change my Action Name.
#Html.ActionLink( "headline", "Details", "Blog", new { id="1200" }, null )
Thanks in advance ;)
You could use a RouteLink instead of using an ActionLink. In a RouteLink you can explicitly pass your route name:
#Html.RouteLink("headline", "Blog", new { controller = "Blog", action = "Details" })
More about RouteLink method can be found in the MSDN. Reordering routes can do the job but that's a rather fragile mechanism.
The ActionLink may be using a different route from what you are providing in the question. Do you have any routes declared before this one?
The routes are matched in the order that you provide them. So, for instance, if you had something like:
routes.MapRoute("Blog",
"blog/dp", // {id} is not provided in this one
new { controller ="Blog", action = "Details" });
declared before this route:
routes.MapRoute("Blog",
"blog/dp/{id}",
new { controller ="Blog", action = "Details" });
The first route would be matched first and you would see /blog/dp/?id=1200 instead of /blog/dp/1200.
I'm having problems when using this route:
routes.MapRoute("ProductIndex", "pr-{key}", new { controller = "Home", action = "Product" });
When the key contains 'pr-', the route doesn't work.
Example: http://.../pr-my-product-key-with-pr-key
Routes don't work the way you want them to work, but it's easily converted
change your route to:
routes.MapRoute(
"ProductIndex",
"pr/{key}",
new { controller = "Home", action = "Product" });
and use:
http://.../pr/my-product-key-with-pr-key
or, if you really want to use that "way" you need to override the Initialization method of your main controller are check the link with StartWith() and redirect to the proper Controller.
I have these two routes:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default2", // Route name
"{controller}/{action}/{OrderId}/{CustomerID}", // URL with parameters
new { controller = "NorthwindOrders", action = "Index", OrderId = UrlParameter.Optional, CustomerID = UrlParameter.Optional } // Parameter defaults
);
and want to create link that uses the second route.
How can I do this?
If you want to specifically use a route, you can use the Html helper Html.RouteLink :
<%= Html.RouteLink("my link", "Default2", new {OrderId=1, CustomerId=2}) %>
Also, you can put the second route first : the most generic route should be at the end, in order to be used only when no specific route was found.
Order is very important w/ MapRoutes. Try reversing the order of those two statements.
As well you should use definition of routes in different order.
the order should be more specific first to less
also in your action links i would add routing parameters
Actually not 100% what the OP asked for, but what I needed was an ActionResult that forcefully uses a specific route. RedirectToAction always used the wrong route. I found it in RedirectToRoute("RouteName", new { action="Index" }).
I need routes to match sometimes controllers, and sometimes - database values. Here's an example:
/controller/action?id=test - this is the default {controller}/{action} route
/name/type?flag=test - this is my custom {dbvalue}/{dbvalue} route
As you can see, the two routes are the same. But if {controller} or {action} is a specific value (only known at runtime because it depends on DB) - I need the route to match my other route (i.e. /specificcontroller/handleall(string name, string type) action).
Is it possible?
OK, the answer would be to implement IRouteConstraint to exclude DB values from the {controller} values accepted in the default route.
E.g.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new { controller = new ExcludeValuesConstraint("dbvalue1", "dbvalue2") }
);
Of course excluded values have to be dynamic.
The trick was not to add constraints to my route, but to exclude the values from the default route.
This is not tested yet but just an idea:
Global.asax:
routes.MapRoute("DbRoute", "{dbValue1}/{dbValue2}", new {controller = "RouteController", action = "Index"});
routes.MapRoute("Default", "{controller}/{action}/{id}", new {controller = "Home", action = "Index", id = UrlParameter.Optional});
then in method action Index() inside class RouteController, you check for the dbValue1 and dbValue2. If not match, you can use RedirectToRoute("Default", ...) method.
By this way, any request will match DbRoute first and RouteController will check for the db value, if not match simply forward the route to the Default and render the view based on controller/action.