asp.net mvc route with action after id and slug - asp.net-mvc

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 }
);

Related

Custom route breaks Default routing Asp.Net

I have custom routing for controller added right over the default one:
Custom:
routes.MapRoute(
name: "FaqSubCategory",
url: "{culture}/{controller}/{action}/{TapCode}",
defaults: new { controller = "FAQ", action = "GetChosenFaqSubCategory", TapCode = UrlParameter.Optional },
constraints: new { culture = new CultureConstraint() }
);
Custom v2:
routes.MapRoute(
name: "FaqSubCategory",
url: "{culture}/{controller}/{action}/{TapCode}",
defaults: new { controller = "FAQ", action = "GetChosenFaqSubCategory", TapCode = UrlParameter.Optional },
constraints: new { culture = new CultureConstraint(), FAQ = new TranslateControllersConstraint("4189") }
);
Default:
routes.MapRoute(
name: "DefaultWithCulture",
url: "{culture}/{controller}/{action}/{ID}",
defaults: new { controller = "Home", action = "Index", ID = UrlParameter.Optional },
constraints: new { culture = new CultureConstraint() }
);
Basically because of that custom route, home page is receiving "/home/index" and some of the other pages are receiving "/index" at the end of the URL
When I write the custom routing like the second variant, then everything is working perfectly except the FAQ controller.
When an MVC application first starts it creates the route table.The default route table contains a single route named Default. So default route should have Default name, instead of DefaultWithCulture an your default route should have default culture
routes.MapRoute(
name: "Default",
url: "{culture}/{controller}/{action}/{ID}",
defaults: new { culture="en", controller = "Home", action = "Index", ID = UrlParameter.Optional },
.....

MVC Routing Issue when trying www.example.com/id

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.

mvc routes not working

I have two routes in RouteConfig
routes.MapRoute(
name: "Default",
url: "{culture}/{controller}/{action}/{id}",
defaults: new { controller = "Desktop", action = "Index", wizard = "", culture = "he-IL", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Wizard",
url: "{wizard}/{culture}/{controller}/{action}/{id}",
defaults: new { controller = "Desktop", action = "Index", wizard = "AllManufucturer", culture = "he-IL", id = UrlParameter.Optional }
);
I'm trying to navigate to
http://localhost:5754/he-IL/Account/Login which is working
http://localhst:5754/wizard234/he-IL/InfoRequest/Details which is not working
I tried to change the routes order and link 1 is not working and link 2 is working, I want the site will run two different routes template
Please what am I missing?
Tank you in advanced

ASP.NET MVC Routes Config and Internationalization with long URLs

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.

Asp MVC 4 MapRoute specific url

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.

Resources