Reputation: 2754
I need some custom routing for my website. I need the URLs show up like this
Please note that two bold URLs are different only in last part of URL and I can't use controller name and action name with this type of URL. How can I do this with rout tables in ASP.NET MVC? I this is impossible with rout tables, Is there another utility to do this?
Thanks
Upvotes: 0
Views: 262
Reputation: 11903
I know of several ways.
First of all, I assume there is some kind of difference between the two URL's. If "apple" is a valid product and category name as well, then of course there is no way on earth to distinguish them if the URL pattern is the same. And always make sure that your routes are defined in the right order, the routing engine will route a request to the first matching route, so put more specific routes first.
The easiest is if there is a syntactical difference between subcategoryname
and productname
. Then route constraints are the way to go. You can define different regular expressions for the two parameters and they will work perfectly, the routing engine will know where to route which request. (See here or here.)
If there is no syntactical difference, you can introduce one. For example:
www.domain.com/categoryname/s_subcategoryname
www.domain.com/categoryname/p_productname
It isn't too ugly and there are no conflicts.
Then, you can also implement your own IRouteConstraint. This way you can define any logic that you want to differentiate between the two routes. Collect a name of possible products in a list, and then you can match that to the product route. (See here.)
You can also define a custom route handler or HTTP handler, which does the same logic as the previous paragraph and does a Server.Transfer()
to actually execute different actions, but it's a lot messier, so I wouldn't suggest it.
Upvotes: 1
Reputation: 96
One way to achieve this is to create custom RouteConstraint by inheriting IRouteConstraint and store your urls in xml. You will need to know the page template type so you could store this information in an enum like this:
public enum TemplateType
{
Home,
Product,
Category
}
Here is an example xml that you can use to store your data:
<Sitemap>
<Item url="/home" TemplateType="Home" />
<Item url="/products/category" TemplateType="Category">
<Item url="/products/category/product" TemplateType="Product" />
</Item>
</Sitemap>
After that you will need method to extract Sitemap nodes and get specific node. You simply need to deserialize the xml and traverse it to find specific url.
Your custom RouteConstraing should be something like this:
public class CustomRouteConstraint : IRouteConstraint
{
#region IRouteConstraint Members
private TemplateType m_type;
public CustomRouteConstraint(TemplateType type)
:base()
{
m_type = type;
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
bool returnValue = false;
SitemapNode sitemapNode = GetSiteMapNode(httpContext.Request);
if (sitemapNode != null && sitemapNode.TemplateType == m_type)
{
return true;
}
return returnValue;
}
#endregion
private static SitemapNode GetSiteMapNode(HttpRequestBase request)
{
//get the aboslute url
string url = request.Url.AbsolutePath;
return SitemapManager.GetSiteMapNode(url);
}
}
After you have all of this in place in your Global.asax file in the RegisterRoutes method you need to do something like this:
routes.MapRoute(
"", // Route name
route, // URL with parameters
new { lang = "en", region = "us", controller = "Category", action = "Index" },
new { param1 = new CustomRouteConstraint(TemplateType.Category) });
Hope this helps.
Upvotes: 1
Reputation: 13600
No, this is not possible like this, because no url routing engine would know how to match such url to a corresponding route. You need to somehow differentiate these types of urls, so it's clear which one to use.
well, ok, there might be a way, but it's kinda hacky... You would just route to some generic action and there you would compare the last part to your records and decide, if the parameter is a productname or a subcategory name, and return a view based on that...
Upvotes: 0