I've got two (so far) different types of routes in my ASP.NET MVC app, one is: {controller}/{action}/{id} and the other {controller}/{action}/{title}
Currently I need to define the routes like this:
routes.MapRoute (
"Default_Title_Slug", // Route name
"product/details/{title}", // URL with parameters
new { controller = "product", action = "details", title = "" } // Parameter defaults
);
routes.MapRoute (
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "site", action = "index", id = "" } // Parameter defaults
);
Notice that the first one I've had to tie down to the product controller, this seems to be the only way I can get it work...otherwise the other routes end up looking like this:
/controller/action?id=number
Now I need to add another MapRoute call targeting another controller with the {title} segment...I don't want to create a new route for each specific entry I come up with in the future...is there a generic route I can create to map the /controller/action/title that'll play nicely with the /controller/action/id route?
Thanks,
Kieron
You can do that with a route-constraint, such as regex - a very similar example is here. Something like:
routes.MapRoute (
"Default",
"{controller}/{action}/{id}",
new { controller = "site", action = "index", id = "" },
new { id = #"\d+" }
);
routes.MapRoute (
"Default_Title_Slug",
"{controller}/{action}/{title}",
new { controller = "product", action = "details", title = "" }
);
Related
I want users to be able to access the "/Linecard" page of my ASP.Net MVC site using "/Linecard" or "/Manufacturers" as the URL... so same controller, 2 different possible URLs.
I tried adding the following:
routes.MapRoute(
name: "Manufacturers",
url: "Manufacturers/{action}/{id}",
defaults: new { controller = "Linecard", action = "Index", id = UrlParameter.Optional }
);
Adding this after the "Default" route doesn't work at all and I get a 404 error when I go to "/Manufacturers". Putting it BEFORE "Default" works, but then only "/Manufacturers" shows up in the URL when I click menu links since it is the first match. I would like "/Linecard" to always show as the URL.
Any pointers? Is there a certain constraint I can use to accomplish this? Thanks!
I had the same problem when we moved to extension-less URLs. We needed to continue to support one route with extensions. I got around it by having my default route apply to everything except the old URL, then after that mapping one specifically for the exception
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
// if controller specified does not match 'manufacturers' (case insensitive)
new { controller = "^((?i)(?!manufacturers).)*$" },
new string[] { "Namespace.Of.Controllers" }
);
routes.MapRoute(
"Manufacturers", // Route name
"Manufacturers/{action}/{id}", // URL with parameters
new { controller = "Linecard", action = "Index", id = UrlParameter.Optional },
new string[] { "Namespace.Of.Controllers" }
);
You could also set an order when mapping your routes with the defaults at the end like so
routes.MapRoute(
name: "Manufacturers",
url: "Manufacturers/{action}/{id}",
defaults: new { controller = "Linecard", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
I am wanting to create a website that dynamically maps routes in the following fashion:
http://domain/MyCategory1
http://domain/
http://domain/MyCategory1/MySubCategory
So far I've added in a new route to Global.asax
routes.MapRoute(
"IFAMainCategory", // Route name
"{IFACategoryName}", // URL with parameters
new { controller = "Home", action = "GetSubCategories", IFACategoryName=1} // Parameter defaults
);
But this then messes up the default route that comes as standard.
Is there any way I can control this?
You need to change your routes:
routes.MapRoute("MyCustomRoute", "MyCategory1/{action}/{id}",
new { controller = "MyCategory1", action = "MySubCategory", id = UrlParameter.Optional });
// Then the default route
Basically, since you've just made one giant route catcher, all routes match to that one. You need to go specific if you want to map a specific route to a controller.
You need to include MyCategory1 in the route name
routes.MapRoute( "IFAMainCategory",
// Route name "MyCategory1/{IFACategoryName}",
// URL with parameters new { controller = "Home", action = "GetSubCategories", IFACategoryName=1} // Parameter defaults );
Check out this other post for example, and check out Route Debugger
.NET MVC custom routing
Unfortunately I don't think you're going to achieve what you want directly.
You need some way to separate the routes, like placing your "categories" in a folder:
routes.MapRoute(
"IFAMainCategory", // Route name
"categories/{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "GetSubCategories", IFACategoryName=1 }
);
The other option is you could register a route for every parent category before the default route on App Start:
routes.MapRoute(
"IFAMainCategory 1", // Route name
"MyCategory1/{subcategory}", // URL with parameters
new { controller = "Home", action = "GetSubCategories", IFACategoryName=1, subcategory = UrlParameter.Optional }
);
routes.MapRoute(
"IFAMainCategory 2", // Route name
"MyCategory2/{subcategory}", // URL with parameters
new { controller = "Home", action = "GetSubCategories", IFACategoryName=2, subcategory = UrlParameter.Optional }
);
I'm interested to know how people handle the following situation.
Assume we have a DataField and each DataField can have unlimited number of DataValues
We have 2 controllers to handle the manipulation of these objects
DataFieldController
DataValueContoller
Now if we ever need to add a new DataValue we need to know the ID of the CustomDataField. The following URL would be used,
/CustomDataValue/Add/1
1 = DataField ID
However, because the ASp.Net MVC engine binds the parameter name to the model (IE in the case below. My DatValeu Object would have its ID replaced, when I am actually trying to pass through the FieldID)
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Site", action = "Home", id = UrlParameter.Optional } // Parameter defaults
);
How can we handle this? Doing the following obviously will not work.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Site", action = "Home", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{fieldid}", // URL with parameters
new { controller = "Site", action = "Home", fieldid = UrlParameter.Optional } // Parameter defaults
);
I assume this is a common problem, I just cant find the obvious solution at the moment. It would be ok if the Signature was differant but both are /String/String/Int
==========================
How can these routes work then?
/DataValue/Add/{DataFieldID}
/DataValue/Edit/{ID}
/DataValue/List/{DataFieldID}
Must I add 3 routes?
Use constraints in routes like this:
routes.MapRoute(
"Default", // Route name
"CustomDataValue/{action}/{fieldid}", // URL with parameters
new { controller = "Site", action = "Home", fieldid = UrlParameter.Optional } // Parameter defaults
);
It makes sure only URLs starting with "CustomDataValue" calls this route. It's declared as a constant, different from the default route. Make sure these specified routes are declared before the default route. Since there are no restrictions, all URLs are matched to it.
Update
I guess you have to call DataValueController methods with URLs like http://domain.com/CustomDataValue/Add/23. If that's the case use the following route:
routes.MapRoute(
"CustomData", // Route name
"CustomDataValue/{action}/{fieldid}", // URL with parameters
new { controller = "DataValue", action = "List", fieldid = UrlParameter.Optional } // Parameter defaults
);
This will work if you have action methods in DataValueController named List/Add/Edit.
I have two pages in my simple MVC App with two defined routes:
routes.MapRoute(
"Results", // Route name
"Results/{id}", // URL with parameters
new { controller = "Results", action = "Index",
id = "" } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Main", action = "Index",
id = UrlParameter.Optional } // Parameter defaults
);
I needed to have the results page load with just a product ID such as this: [MyDomain....]/Results/12345. But also the main page does a POST (using JQuery) to the Results Controller for updates using this route: [MyDomain....]/Main/Update along with a data bag. This works fine when I only have the "Default" route. But when I added the other "Results" route, all the POST calls to update are failing. Any ideas what I'm doing wrong???
Thanks a lot.
I didn't try this out, but should accomplish what you need. Not sure if there may be a "better" way to accomplish it.
routes.MapRoute(
"Results", // Route name
"Results/{id}", // URL with parameters
new { controller = "Results", action = "Index", id = "" } // Parameter defaults
new { id = #"\d+" } // regex for id param - id must be a number
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Main", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
How can I rewrite a url like: /SomePage to /Pages/ShowPage/SomePage?
I tried:
routes.MapRoute("myroute", "{id}", new { controller = "Pages", action = "ShowPage" });
But It's not working. What am I doing wrong?
If you are trying to say "navigating to /SomePage shall call PagesController.ShowPage("SomePage")", then you probably want this:
// Find a method with signature PagesController.ShowPage( string param )
// and call it as PagesController.ShowPage("SomePage")
route.MapRoute(
"MyRoute",
"SomePage",
new { controller = "Pages", action = "ShowPage", param = "SomePage" } );
This will only redirect the exact URL /SomePage. If you are trying to say "navigating to /{something} shall run the PagesController.ShowPage( something ) method", then that is a more difficult problem.
If this second case is indeed what you want, then you'll have to define it after most of your other routes. The routing entry you would want would be:
// This will call the method PagesController.ShowPage( string param )
route.MapRoute(
"MyRoute",
"{param}",
new { controller = "Pages", action = "ShowPage" } );
I think this should be:
routes.MapRoute("myroute", "{controller}/{action}/{id}", new { controller = "Pages", action = "ShowPage", id = "SomePage" });
It was wrong because I think in your application, there is this default map route :
routes.MapRoute(
"root", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
it will looks for the controller with the name equal to the id that you passed in, if you remove this default map route, your map route would work.
You should try this route debugger tool, it helps out a lot:
Debugger Tool
You need to ensure that your route maps to your objects. In your case, you need to have a controller called PagesController with a method called ShowPage, with a single parameter called pagename (if you use a route like the following).
routes.MapRoute("route", "{controller}/{action}/{pagename}", new { controller = "Pages", action = "ShowPage", pagename = "" } );
Also, do not forget that you can use regex when specifying the route - this may help you ensure the correct route is used by the routing engine.
routes.Add(new Route("{controller}/{action}/{params}",
new RouteValueDictionary { { "controller", "user" }, { "action", "login" }, { "params", "" } },
new RouteValueDictionary { { "controller", #"^(?!Resources)\w*$" }, { "action", "[a-zA-Z]+" } },
new MvcRouteHandler()));
You can write your own static routing. Above the default route add your own.
routes.MapRoute("MyRoute", // Route name
"Pages/ShowPage/SomePage/{id}", // URL with parameters
new { controller = "Pages", action = "ShowPage", id = "" } // Parameter defaults
);
Now, if SomePage is a variable, you'll want something like this:
routes.MapRoute("MyRoute", // Route name
"Pages/ShowPage/{somePage}/{id}", // URL with parameters
new { controller = "Pages", action = "ShowPage", id = "", somePage = "" } // Parameter defaults
);
You can leave out the {id} if you want, just leave it out of your action parameters.
routes.MapRoute("MyRoute", // Route name
"Pages/ShowPage/{somePage}", // URL with parameters
new { controller = "Pages", action = "ShowPage", somePage = "" } // Parameter defaults
);