MVC Routing: Defining multiple / separated items as a single route - c#

Consider the following MVC route entry:
routes.MapRoute("Content", "content/{route}", new { controller = "Content", action = "ContentPage", route="" });
Works ok for:
www.domain.com/content/test
www.domain.com/content/blah
Also works for url parameters
www.domain.com/content/test?hello=1
Does not work for:
www.domain.com/content/foo/bar
www.domain.com/one/two/three/four
How can I get my route to accept /foo/bar or /one/two/three/four as
{route}?
How can I do the above and maintain teh ability to read url
parameters by the controller?

Try this,
routes.MapRoute("Content", "content/{route1}/{route2}", new { controller = "Content", action = "ContentPage", route1 = UrlParameter.Optional, route2 = UrlParameter.Optional });
Note: Add the maximum number of optional parameters as required.

Related

Url generation not giving desired results according to route config

I am using ASP.NET MVC 4.
I have a controller called Server, and 2 action methods called Search and Component. I have the following route configuration:
routes.MapRoute("Component",
"{controller}/{serverId}/{action}",
new { controller = "Server", action = "Component" },
new { serverId = #"\d+" });
I am looking for a url similar to:
/Server/12345/Component
My Search action method:
return RedirectToAction("Component", new { serverId = 12345 });
My Component action method:
public ActionResult Component(int serverId)
{
return View();
}
The url that is generated is:
/Server/12345/
It is wrong, it is leaving out "Component". Why is this?
new { controller = "Server", action = "Component" },
Becase you are setting the default action to "Component", I think the link generation is smart enough to leave it off.
You defined Component as Default-Action, so why should it been appended?
If you want it in your route, then remove it from default and add it to your RedirectToAction call.

mvc3 unusual routing

I have two routes except for default:
routes.MapRoute("ShopDefault",
"Shop/{id}/{action}",
new { controller = "Shop" });
routes.MapRoute("Shop",
"Shop/{id}/List/{categoryID}",
new { controller = "Shop", action = "List"});
The first route works perfectly, links like .../Shop/3/Index, .../Shop3/Messages are correctly processed.
But for the second route - links like .../Shop/3/List/5 are not found. Anyone know why?
Your more explicit route should be first, the routing engine is attempting to match Shop/Id/Action in ShopDefault and then probably failing and giving you a 404 before it gets to your more explicit route of Shop.
You should put the routes in the opposite order:
routes.MapRoute(
"Shop",
"Shop/{id}/List/{categoryID}",
new { controller = "Shop", action = "List"},
new { id= #"\d+" }
routes.MapRoute(
"ShopDefault",
"Shop/{id}/{action}",
new { controller = "Shop" });

Generating URLs from ASP.NET MVC routes

If I have some routes set up as follows:
context.MapRoute("Route1", "Public/DataCapture/Name", new { controller = "Profile", action = "Name" } );
context.MapRoute("Route2", "Public/DataCapture/Age", new { controller = "Profile", action = "Age" } );
context.MapRoute("Route2", "Public/DataCapture/Amount", new { controller = "Income", action = "Amount" } );
How can I generate URLs that use the route path and not the actual controller/action path?
E.g.
Url.Action("Name", "Profile")
Should generate "Public/DataCapture/Name" rather than "Public/Profile/Name"
Try using Url.RouteUrl.
In the past, when I have had problems getting that to return the correct route, it was usually an indication that either my routes were not defined in the correct order, or I was doing something that kept the routing system from matching the route I intended.

ASP.NET MVC multiple url's pointing to the same action

How do i map multiple url's to the same action in asp.net mvc
I have:
string url1 = "Help/Me";
string url2 = "Help/Me/Now";
string url3 = "Help/Polemus";
string url1 = "Help/Polemus/Tomorow";
In my global.asax.cs file i want to map all those url to the following action:
public class PageController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View();
}
}
Now in MVC 5 this can be achieved by using Route Attribute.
[Route("Help/Me")]
[Route("Help/Me/Now")]
[Route("Help/Polemus")]
[Route("Help/Polemus/Tomorow")]
public ActionResult Index()
{
return View();
}
Add the following line to your routing table:
routes.MapRoute("RouteName", "Help/{Thing}/{OtherThing}", new { controller = "Page" });
EDIT:
foreach(string url in urls)
routes.MapRoute("RouteName-" + url, url, new { controller = "Page", action = "Index" });
In my case I was looking to simply combine two 'hardcoded' routes into one and stumbled upon this post. I wanted to clean out my RouteConfig.cs a little - because it had so many similar routes.
I ended up using some simple 'or' logic in a regular expression and basically changed:
routes.MapRoute(
"UniqueHomePage",
"Default",
new { controller = "Redirector", action = "RedirectToRoot" }
);
routes.MapRoute(
"UniqueHomePage2",
"Home",
new { controller = "Redirector", action = "RedirectToRoot" }
);
Into a single route:
routes.MapRoute(
"UniqueHomePageGeneric",
"{url}",
new { controller = "Redirector", action = "RedirectToRoot" },
new { url = "Home|Default" }
);
Note for the SEO-savy or -interested: The reason for pointing multiple URL's to one and the same action, is to then redirect them to one and the same page again. In this case the homepage. So the idea is to prevent duplicate content issues. When you use this method for pointing for NON redirecting actions, but actions that show their own views, then you might be CAUSING duplicate content issues :P.
You can just add the routes into your route table as you need them, same as any other route. Just give them unique names, hard coded URL and point them to the same controller / action. It will work fine.
If you use pattern matching instead of hard coded URLs just make sure you get all your routes in the right order so the correct one is selected from the list. So /Help/Me should appear before /Help/{Page} if the hard coded route goes to a different page to the pattern matched one. If you put /help/{page} in the route tabel 1st this will match to /help/me and your hard coded named action for that route would never fire.
On a side note, if this is a public facing site and SEO is important please be careful if you have multiple URLs returning the same data, it will be flagged as duplicate. If this is the case, then use the Canonical tag, this gives all the page rank from all the URLS that go to that single page to the one you name and removes the duplicate content issue for you.

ASP.NET MVC 2 Routing with additional consistent parameters (not just controller & action)

Currently, I have URLs that look like this:
http://www.example.com/user/create
http://www.example.com/user/edit/1
But now, I have to support multiple organizations and their users. I need to have something like this:
http://www.example.com/org-name/user/create
http://www.example.com/org-name/user/edit/1
I was having trouble getting the routes to work just perfectly, so I had to add a token to the beginning of the organization name so that routing wouldn't confuse it with a controller/action pair. Not a huge deal but my URLs look like this now:
http://www.example.com/o/org-name/user/create
http://www.example.com/o/org-name/user/edit/1
That's fine. I can live with that.
Here's where I'm running into trouble:
When I generate URLs once I have an organization selected, it's not persisting the organization name. So when I'm here:
http://www.example.com/o/org-name
...and I use Url.Action("User", "Create") to generate a URL, it outputs:
/user/create
...rather than what I want:
/o/org-name/user/create
This is what my routes look like (in order):
routes.MapRouteLowercase(
"DefaultOrganization",
"{token}/{organization}/{controller}/{action}/{id}",
new { id = UrlParameter.Optional },
new { token = "o" }
);
routes.MapRouteLowercase(
"OrganizationDashboard",
"{token}/{organization}/{controller}",
new { controller = "Organization", action = "Dashboard" },
new { token = "o" }
);
routes.MapRouteLowercase(
"DefaultSansOrganization",
"{controller}/{action}/{id}",
new { controller = "Core", action="Dashboard", id = UrlParameter.Optional }
);
It's similar to this question ASP.NET MVC Custom Routing Long Custom Route not Clicking in my Head.
I have a feeling this is going to end up being obvious but it's Friday and it's not happening right now.
EDIT:
Womp's suggested worked but would this be the best way to automate this?
public static string ActionPrepend(this UrlHelper helper, string actionName, string controllerName)
{
string currentUrl = helper.RequestContext.RouteData.Values["url"] as string;
string actionUrl = string.Empty;
if (currentUrl != null)
{
Uri url = new Uri(currentUrl);
if (url.Segments.Length > 2 && url.Segments[1] == "o/")
actionUrl = string.Format("{0}{1}{2}{3}", url.Segments[0], url.Segments[1], url.Segments[2],
helper.Action(actionName, controllerName));
}
if(string.IsNullOrEmpty(actionUrl))
actionUrl = helper.Action(actionName, controllerName);
return actionUrl;
}
EDIT:
Fixed my routes to work rather than hacking it together. The final solution didn't need the stupid {token} in the URL. Maybe this'll help someone else:
routes.MapRouteLowercase(
"Organization",
"{organization}/{controller}/{action}/{id}",
new { controller = "Organization", action = "Dashboard", id = UrlParameter.Optional },
new { organization = #"^(?!User|Account|Report).*$" }
);
routes.MapRouteLowercase(
"Default",
"{controller}/{action}/{id}",
new { controller = "Core", action = "Dashboard", id = UrlParameter.Optional }
);
Url.Action uses route values to generate the actual URL's by querying the virtual path provider and attempting to match the most specific route. In the form that you are using, you are supplying values for the controller and the action, which is as deep as most simple websites go, hence the convenient form of the method. When Url.Action queries the routing system, it only has a "controller" and an "action" segment to match.
If you give the method the rest of the routing information it needs, it will properly match the route that you desire, and will return the correct URL. Try this:
Url.Action("User", "Create", new { token = "o", organization = "organization" })

Categories