我正在使用NopCommerce 2.30构建网站。开箱即用,产品网址如下所示:
/p/16/build-your-own-computer/
我做了一些更改,以使网址如下所示:
/build-your-own-computer/
我已对Route
进行了更改,以阻止其使用Id
参数。但是,网站上的所有链接仍然通过Url.RouteUrl
方法传递Id参数:
@Url.RouteUrl("Product", new { productId = Model.Id, SeName = Model.SeName })
这会产生以下网址:
/build-your-own-computer/?productId=16
我可以直接从方法调用中删除productId
参数。但是,某些插件还会添加包含productId
的链接,我无法更改。
有没有办法可以覆盖Url.RouteUrl
方法来检查对产品Route
的请求,然后删除productId
?
答案 0 :(得分: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);
}
答案 1 :(得分: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" });