【问题标题】:ASP.NET MVC - Custom RoutingASP.NET MVC - 自定义路由
【发布时间】:2014-02-12 09:48:03
【问题描述】:

我的网站需要一些自定义路由。 我需要这样的 URL 显示

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

请注意,两个粗体 URL 仅在 URL 的最后一部分和 我不能在这种类型的 URL 中使用控制器名称和操作名称。 如何使用 ASP.NET MVC 中的路由表执行此操作? 我用路由表是不可能的,还有其他实用程序可以做到这一点吗?

谢谢

【问题讨论】:

    标签: c# asp.net-mvc


    【解决方案1】:

    我知道几种方法。

    首先,我假设这两个 URL 之间存在某种差异。如果“apple”也是有效的产品和类别名称,那么如果 URL 模式相同,那么在地球上当然无法区分它们。并始终确保您的路由以正确的顺序定义,路由引擎会将请求路由到第一个匹配的路由,因此首先放置更具体的路由。

    最简单的方法是subcategorynameproductname 之间的语法差异。然后路线限制是要走的路。您可以为这两个参数定义不同的正则表达式,它们将完美地工作,路由引擎将知道将哪个请求路由到哪里。 (见herehere。)

    如果没有语法上的区别,你可以引入一个。例如:

    www.domain.com/categoryname/s_subcategoryname
    www.domain.com/categoryname/p_productname
    

    不会太丑,也没有冲突。

    然后,您还可以实现自己的 IRouteConstraint。通过这种方式,您可以定义任何想要区分两条路线的逻辑。在列表中收集可能产品的名称,然后您可以将其与产品路线相匹配。 (见here。)

    您还可以定义自定义路由处理程序或 HTTP 处理程序,其执行与上一段相同的逻辑并执行 Server.Transfer() 以实际执行不同的操作,但它更混乱,所以我不建议这样做。

    【讨论】:

      【解决方案2】:

      实现此目的的一种方法是通过继承 IRouteConstraint 创建自定义 RouteConstraint 并将您的 url 存储在 xml 中。您将需要知道页面模板类型,以便您可以将此信息存储在这样的枚举中:

      public enum TemplateType
      {
          Home, 
          Product,
          Category
      }
      

      这是一个可用于存储数据的示例 xml:

      <Sitemap>
        <Item url="/home" TemplateType="Home" />
        <Item url="/products/category" TemplateType="Category">
          <Item url="/products/category/product"  TemplateType="Product" />
        </Item>
       </Sitemap>
      

      之后,您将需要提取站点地图节点并获取特定节点的方法。您只需要反序列化xml并遍历它以找到特定的url。

      您的自定义 RouteConstraing 应该是这样的:

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

      在您的 Global.asax 文件中的 RegisterRoutes 方法中完成所有这些后,您需要执行以下操作:

      routes.MapRoute(
          "", // Route name
          route, // URL with parameters
          new { lang = "en", region = "us", controller = "Category", action = "Index" },
          new { param1 = new CustomRouteConstraint(TemplateType.Category) });
      

      希望这会有所帮助。

      【讨论】:

      • 您能否提供一个示例,说明它如何与 {route: url 参数} 一起使用。
      【解决方案3】:

      不,这是不可能的,因为没有 url 路由引擎会知道如何将这样的 url 匹配到相应的路由。您需要以某种方式区分这些类型的 url,因此使用哪一种很清楚。

      好吧,好吧,可能有一种方法,但它有点 hacky...您只需路由到一些通用操作,然后您会将最后一部分与您的记录进行比较并决定参数是产品名称还是子类别名称,并基于该名称返回一个视图...

      【讨论】:

        猜你喜欢
        • 2011-04-02
        • 2020-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-22
        • 2014-02-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多