2012-02-27 27 views
0

我正在使用NopCommerce 2.30構建網站。開箱即用,產品的URL看起來像這樣:覆蓋UrlHelper.RouteUrl

/p/16/build-your-own-computer/ 

我已經做了一些改動,以獲得的URL看起來像這樣:

/build-your-own-computer/ 

我做了一個變化的Route到請停止使用Id參數。然而,所有整個網站的鏈接仍然傳遞Id參數通過Url.RouteUrl方法:

@Url.RouteUrl("Product", new { productId = Model.Id, SeName = Model.SeName }) 

這將導致以下網址:

/build-your-own-computer/?productId=16 

我可以去通過,並刪除productId參數來自方法調用。但是,一些插件還添加了包含productId的鏈接,我無法更改。

有沒有辦法可以覆蓋Url.RouteUrl方法來檢查對產品Route的請求,然後刪除productId

+1

烏姆 - 如何將你的控制器/動作知道編號已經點擊,如果你不傳遞一個標識在URL中的用戶什麼樣的產品? – Tommy 2012-02-27 17:59:59

+0

而不是使用產品ID獲取產品,它使用產品名稱。 – 2012-02-27 18:26:14

回答

0

我已經成功使用這個稍微修改解決方案來解決我的問題:http://erraticdev.blogspot.com/2011/03/removing-route-values-from-linksurls-in.html

羅伯特的解決方案不包括命名空間,所以我做了幾以下調整:

public static class CustomRouteExtensions 
{ 

    public static Route MapRoute(this RouteCollection routes, string name, string url, string excludeRouteValueNames, object defaults) 
    { 
     return MapRoute(routes, name, url, excludeRouteValueNames, defaults, null, null); 
    } 

    public static Route MapRoute(this RouteCollection routes, string name, string url, string excludeRouteValueNames, object defaults, string[] namespaces) 
    { 
     return MapRoute(routes, name, url, excludeRouteValueNames, defaults, null, namespaces); 
    } 

    public static Route MapRoute(this RouteCollection routes, string name, string url, string excludeRouteValueNames, object defaults, object constraints) 
    { 
     return MapRoute(routes, name, url, excludeRouteValueNames, defaults, constraints, null); 
    } 

    public static Route MapRoute(this RouteCollection routes, string name, string url, string excludeRouteValueNames, object defaults, object constraints, string[] namespaces) 
    { 
     if (routes == null) 
      throw new ArgumentNullException("routes"); 

     if (url == null) 
      throw new ArgumentNullException("url"); 

     Route item = new CustomRoute(url, new MvcRouteHandler(), excludeRouteValueNames) 
     { 
      Defaults = new RouteValueDictionary(defaults), 
      Constraints = new RouteValueDictionary(constraints), 
      DataTokens = new RouteValueDictionary() 
     }; 

     if ((namespaces != null) && (namespaces.Length > 0)) 
      item.DataTokens["Namespaces"] = namespaces; 

     routes.Add(name, item); 

     return item; 
    } 

} 

我定製Route則是這樣的:

public class CustomRoute : Route 
{ 

    #region Properties 

    public ReadOnlyCollection<string> ExcludedRouteValuesNames { get; private set; } 

    #endregion 

    #region Constructor 

    public CustomRoute(string url, IRouteHandler routeHandler, string commaSeparatedRouteValueNames) 
     : this(url, routeHandler, (commaSeparatedRouteValueNames ?? string.Empty).Split(',')) 
    { 
    } 

    public CustomRoute(string url, IRouteHandler routeHandler, params string[] excludeRouteValuesNames) 
     : base(url, routeHandler) 
    { 
     ExcludedRouteValuesNames = new ReadOnlyCollection<string>(excludeRouteValuesNames.Select(val => val.Trim()).ToList()); 
    } 

    #endregion 

    #region Route overrides 

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 
    { 
     if (requestContext == null) 
      throw new ArgumentNullException("requestContext"); 

     // create new route data and include only non-excluded values 
     var excludedRouteData = new RouteData(this, this.RouteHandler); 

     // add route values 
     requestContext.RouteData.Values 
      .Where(pair => !this.ExcludedRouteValuesNames.Contains(pair.Key, StringComparer.OrdinalIgnoreCase)) 
      .ToList() 
      .ForEach(pair => excludedRouteData.Values.Add(pair.Key, pair.Value)); 

     // add data tokens 
     requestContext.RouteData.DataTokens 
      .ToList() 
      .ForEach(pair => excludedRouteData.DataTokens.Add(pair.Key, pair.Value)); 

     // intermediary request context 
     var currentContext = new RequestContext(new HttpContextWrapper(HttpContext.Current), excludedRouteData); 

     // create new URL route values and include only none-excluded values 
     var excludedRouteValues = new RouteValueDictionary(
      values 
       .Where(v => !this.ExcludedRouteValuesNames.Contains(v.Key, StringComparer.OrdinalIgnoreCase)) 
       .ToDictionary(pair => pair.Key, pair => pair.Value) 
     ); 

     var result = base.GetVirtualPath(currentContext, excludedRouteValues); 

     return result; 
    } 

    #endregion 

} 

我的新Route.MapRoute看起來是這樣的:

routes.MapRoute("Product", 
       "{SeName}", 
       "productIdd", 
       new { controller = "Catalog", action = "UrlType" }, 
       new[] { "Nop.Plugin.FreshEgg.Seo.Controllers" }); 
0

沒有必要重寫RouteUrl。它需要一組鍵/值對。只需修改路由,使其不再期待該ID並從@ Url.RouteUrl調用中移除該ID。您需要創建一個接受的URL一樣的路線如下:

/p/{productName}

你可以在你的Global.asax:

routes.MapRoute(
    "Products", 
    "/p/{productName}", 
    new { controller = "Products", action = "Details" } 
); 

現在,你會產生這樣的替代路線:

@Url.RouteUrl("Products", new { productName = Model.SeName }) 

現在在你的控制器,你必須額外的工作,找到從名稱而不是ID的產品。它可能會是這個樣子,而不是現在:

public ActionResult Details(string productName) 
{ 
    var product = ProductRepository.FindByName(productName); 

    return View(product); 
} 
+0

嗨,感謝您的評論。這就是我已經在做的事情,然而,所有'@ Url.RouteUrl'事件仍然在發送'productId'。由於'productId'不是'Route'的一部分,它將它作爲查詢字符串參數添加到鏈接的末尾。我需要停止添加查詢字符串參數而不從'@ Url.RouteUrl'中移除它。 – 2012-02-27 18:33:46

+0

@Scrooby有沒有你期望這個id被傳入的任何代碼?它可以傳遞給Url.RouteUrl的調用,但不傳遞給控制器​​嗎? – Dismissile 2012-02-27 18:41:40

+0

@Dismissle我在視圖中的其他地方使用Id,因此從控制器中刪除它不會是一個選項。 – 2012-02-28 10:58:47