简体   繁体   中英

ASP.NET MVC - Custom Routing

I need some custom routing for my website. I need the URLs show up like this

  • www.domain.com/categoryname/subcategoryname
  • www.domain.com/categoryname
  • www.domain.com/categoryname/productname
  • www.domain.com/categoryname/subcategoryname/productname

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

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.

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.

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...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM