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.
Related
Let say I have a website www.example.com
the default routing looks like
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
Ok that works fine but let's say I want my site when I go to www.example.com/id to go to www.example.com/login/index/id
How would I configure/add routing for this, without breaking my other pages where I am actually trying to go to www.example.com/controller?
EDIT: Unfortunately id is a string so I do not have any concrete constraints that I can think of that would work. Think of maybe instead of the id I should have said companyname or sitename so the URL would look like www.example.com/companyname .
The only solution that I have come up with so far is adding a maproute for each one of my controllers like this
routes.MapRoute(
name: "Home",
url: "Home/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Settings",
url: "Settings/{action}/{id}",
defaults: new { controller = "Settings", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "companyname",
url: "{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
This will work but I have many controllers and if I add one in the future and forget to adjust the routes it will fail. Also, this is unlikely but if a companyname happens to the be same as one of my controller names it would also fail.
In controller you may redirect to another Controller/action:
public ActionResult yourAction()
{
return RedirectToAction("nameAction","nameController");
}
Did you tried adding this mapping first:
routes.MapRoute( name: "Custom", url: "{id}", defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional } );
That should work but keep in mind that routes are evaluated secuentially, so you will have to organize mappings in order to reach out all pages in your site.
For example, routes like www.example.com/Product could be redirected to /Login by mistake.
EDIT: You can add constraints, so if id is an int value, you can try with the following:
routes.MapRoute("Custom", "{id}",
new { controller = "Login", action = "Index" },
new { id = #"\d+" }
EDIT 2: Having ids as string values, the only solution I see is to manually add each controller as you said, or to add something like this:
routes.MapRoute(
name: "Default",
url: "app/{controller}/{action}/{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
This way you don't need to update each route in the future.
Please try below routing
routes.MapRoute(name: "companylogin", url: "companylogin/{id}", defaults: new
{
controller = "Login",
action = "Index",
id = UrlParameter.Optional
});
routes.MapRoute(name: "default", url: "{controller}/{action}/{id}", defaults: new
{
controller = "Login",
action = "Index",
id = UrlParameter.Optional
});
Remove other controller specific routing. Now you can navigate to login using
url : - www.example.com/companylogin/{id} and all other url redirect default route.
I am working with internationalization and long routes.
My URLs look like domain/en-us/users/edit/240.
Here is my RouteConfig :
routes.MapRoute(
name: "DefaultWithCulture",
url: "{culture}/{controller}/{action}/{id}",
defaults: new { culture = CultureHelper.GetDefaultCulture(), controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { culture = "([a-zA-Z]{2}-[a-zA-Z]{2})|[a-zA-Z]{2}" }
);
routes.MapRoute(name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
And here is some Actions in my Controller Users :
public ActionResult Edit(int id);
public ActionResult EditPassword(int id);
public ActionResult EditRights(int id);
I want my Actions EditPassword and EditRights to be accessible via domain/en-us/users/edit/password/240 and domain/en-us/users/edit/rights/240.
I did find a solution, using Route Attributes but with the culture (en-us, es-mx, fr-ca) in my url, it broke it all.
The DefaultWithCulture route you have configured will match 3 or 4 route segments. Your URL (en-us/users/edit/password/240) has 5 route segments, so it will not match.
It will match if you pass it the action method name as you have it configured: en-us/users/editpassword/240.
If you want your URLs to look like your example with 5 segments, you will need to do some additional work. First of all, you need to account for the fact that your action names and URLs don't match. One way to do that is to use the ActionName attribute.
[ActionName("password")]
public ActionResult EditPassword(int id);
[ActionName("rights")]
public ActionResult EditRights(int id);
Then you need some new routes and constraints to match the 4 or 5 segment URLs. The main issue to deal with is that some of your segments overlap. So, you need a constraint so you can tell when the 4th segment is an id or if it is an action method.
Basically, to do this break the 1 route with an optional id parameter into 2 routes with required parameters (since when you add a constraint to id it makes it required).
Then add another route for both the localized and non-localized version that handles the extra edit segment in your URL.
// Route to handle culture with 4 segments, ending in numeric id
routes.MapRoute(
name: "DefaultWithCulture",
url: "{culture}/{controller}/{action}/{id}",
defaults: new { culture = CultureHelper.GetDefaultCulture(), controller = "Home", action = "Index" },
constraints: new { culture = "([a-zA-Z]{2}-[a-zA-Z]{2})|[a-zA-Z]{2}", id = #"\d+" }
);
// Route to handle culture with 3 segments, to make id optional
routes.MapRoute(
name: "DefaultWithCulture3Segments",
url: "{culture}/{controller}/{action}",
defaults: new { culture = CultureHelper.GetDefaultCulture(), controller = "Home", action = "Index" },
constraints: new { culture = "([a-zA-Z]{2}-[a-zA-Z]{2})|[a-zA-Z]{2}" }
);
// Route to handle culture with 4 or 5 segments
routes.MapRoute(
name: "DefaultWithCulture5Segments",
url: "{culture}/{controller}/edit/{action}/{id}",
defaults: new { culture = CultureHelper.GetDefaultCulture(), controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { culture = "([a-zA-Z]{2}-[a-zA-Z]{2})|[a-zA-Z]{2}" }
);
// Route to handle default with 3 segments, ending in numeric id
routes.MapRoute(name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index" },
constraints: new { id = #"\d+" }
);
// Route to handle default with 2 segments, to make id optional
routes.MapRoute(name: "Default2Segments",
url: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
// Route to handle default with 3 or 4 segments
routes.MapRoute(name: "Default4Segments",
url: "{controller}/edit/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
If you want the extra segment you added to read something other than edit, you will need additional routes because MVC doesn't understand this URL scheme natively.
I have web site root structure controllers for work with culture part in url,
like mysite.com/en/controller/action/id
but for one specific controller I don't want to use culture prefix.
mysite.com/controller/action/id
How I can do it ?
I have write it MyRoute but it dos't work
routes.MapRoute(
name: "MyNewRoute",
url: "MyNewRoute/",
defaults: new { controller = "MyNewRoute", action = "Data", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "MemberTransfer",
url: "en/Member/Transfer",
defaults: new { culture = "en", controller = "Member", action = "Transfer", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "ExecuteTransfer",
url: "en/Member/ExecuteTransfer",
defaults: new { culture = "en", controller = "Member", action = "ExecuteTransfer", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "",
defaults: new { culture = "en", controller = "Home", action = "Maintenance", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "HomePage",
url: "{culture}/{*pathInfo}",
defaults: new { culture = "en", controller = "Home", action = "Maintenance", id = UrlParameter.Optional }
);
Your "Default" route is overriding the last one. Try to swap the last two routes.
Btw, you can use handy route debugger from Phil Haack. It's really easy to set up and use (you just need to comment/uncomment one single line in your Global.asax.cs). It's absolutely must have tool for every Asp.Net MVC developer.
Swap your last two routes. Routes are evaluated top down, going with the first match, so you want to go from most specific to most generic in the order that you add them.
I'm making asp.net mvc application and I have next issue. For example I need produce url like this www.something.com/abc where abc is product ID and www.something.com/def where def is company ID.
Can someone show me some part of code with route link like this?
#Html.RouteLink("Sample link 1", "routeName 1",
new {controller = "Home", action = "action name 1", parameter="abc" })
#Html.RouteLink("Sample link 2", "routeName 2",
new {controller = "Home", action = "action name 2", parameter="def" })
Just to clarify more my question, for example:
this is routing system
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "aaaaa",
url: "{id}",
defaults: new { controller = "Home2", action = "Index2" }
);
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "bbbb",
url: "{id}",
defaults: new { controller = "Home3", action = "Index2" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
And these are routelinks
#Html.RouteLink("bbbb", "aaaaa",new { id = 555 })
#Html.RouteLink("bbbb", "bbbb", new { id = 6666666, controller="Home3"})
And both of them are redirecting me to same action controller home2 and action Index2.
But I specified which route to use "aaaaa" for first and "bbbb" for secound
And I also specified different controller in second one.
You cannot have 2 identically looking urls:
http://example.com/555
http://example.com/6666666
be routed to 2 different controller actions. The routing engine has absolutely no way of disambiguating between them. When a request of this form comes in, the routing engine evaluates your routes in the order they are defined and it matches this one:
routes.MapRoute(
name: "aaaaa",
url: "{id}",
defaults: new { controller = "Home2", action = "Index2" }
);
That's the reason why Home2 controller is executed. You should distinguish between the notion of generating an url (with the Html.RouteLink helper) where you have the possibility of specifying the route name and evaluating a route.
If you want to be able to disambiguate between those 2 urls you will need to use constraints. For example:
routes.MapRoute(
name: "aaaaa",
url: "{id}",
defaults: new { controller = "Home2", action = "Index2" },
constraints: new { id = #"\d{1,3}" }
);
routes.MapRoute(
name: "bbbb",
url: "{id}",
defaults: new { controller = "Home3", action = "Index2" },
constraints: new { id = #"\d{4,10}" }
);
In this example the first route accepts ids with 1 to 3 digits whereas the second route accepts ids with 4 to 10 digits.
I'm adding a new route into my mvc web application and it's not working as desired. I was hoping someone could help me figure out where in the list it should go and maybe which defaults and/or constraints should be defined for it (in RouteConfig.cs).
The desired route would look like so:
/controller/id/slug/action e.g. mydomain.com/products/10/product-name/reviews
I've tried to define this route like so and have tried it as the 1st, 2nd and 3rd routes listed:
routes.MapRoute(
name: "AlternateRoute",
url: "{controller}/{id}/{slug}/{action}",
defaults: null,
constraints: new { id = #"\d+", slug = #"[\w\-\d+]*" }
);
What's happening is after I add the above route, and browse to a page like /products/10/product-name - url's that were previously something like /products/create look like /products/10/product-name/create (but only on that page).
The only other routes I have are these 3 (defined in my routeConfig file):
/controller/id/slug
routes.MapRoute(
name: "DefaultSlugRoute",
url: "{controller}/{id}/{slug}",
defaults: new { action = "Details", slug = "" },
constraints: new { id = #"\d+", slug = #"[\w\-\d+]*" }
);
/controller/action/year/month
routes.MapRoute(
name: "MonthlyArchiveRoute",
url: "{controller}/{action}/{year}/{month}",
defaults: new { controller = "Blog", action = "Archives", year = UrlParameter.Optional, month = UrlParameter.Optional },
constraints: new { year = #"\d{4}", month = #"\d{2}" }
);
/controller/action/id (the standard one included w/ a new mvc project)
routes.MapRoute(
name: "DefaultRoute",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);