ASP.NET MVC 路由失敗。這是錯誤還是極端情況?
我有一個 ASP.NET MVC 3 應用程序,使用者可以在其中發布“bla bla would be better if yada yada yada”的建議。對於建議詳細資訊頁面,我定義了一個很好的SEO 友好路線,如下所示:
routes.MapRoute(null, "suggestion/{id}/{it}/would-be-better-if-{if}", new { controller = "suggestion", action = "details" });如您所見,我希望修復“如果會更好”部分。
這條路線非常適合任何舊的建議並生成類似
suggestion/5/this-site/would-be-better-if-it-had-a-iphone-application的連結,點擊連結實際上會請求相應的詳細資訊頁面。具有諷刺意味的是,我的一個朋友恰好是一名測試人員,他無意中發布了一條實際上打破路線的建議:“如果’如果’總是在中間對齊會更好,這個網站會更好”。
為此建議生成的連結是
/suggestion/84/this-site/would-be-better-if-would-be-better-if-was-always-alligned-in-the-middle。我已經嘗試過Phil Haack 的 Routing Debugger並確認該路由實際上會一直工作到
suggestion/84/this-site/would-be-better-if-would-be-better-if-,所以第二個“如果會更好”實際上被接受了;在此之後添加任何內容實際上會導致 url 不匹配任何路由*(感謝 Omar -see comments- for help)*。請記住,我真的不想更改路線定義,因為我認為在這種情況下,我可以做到最好,SEO 明智。
那麼,為什麼文本等於路由的固定部分會阻止連結匹配路由呢?為什麼路線中斷?
我實際上對為什麼更感興趣,因為我相信理解為什麼會導致解決方案,或者至少是對一個相當有趣的問題的正確理解。
這看起來像是ASP.NET 路由的欺騙:標記之間的文字子段,以及使用來自文字子段的字元的路由值,這是一個更簡單的錯誤版本。我建議關閉這個以支持那個。
我回答了那個問題。
我不確定它為什麼會這樣,但你可以使用這樣的東西:
public interface IRouteRule { object ProcessIncoming(object value); object ProcessOutgoing(object value); } public class StartsWithRouteRule : IRouteRule { public StartsWithRouteRule(string value) { Value = value; } public string Value { get; protected set; } public object ProcessIncoming(object value) { var result = value as string; if (result == null) return null; if (!result.StartsWith(Value)) return null; return result.Substring(Value.Length); } public object ProcessOutgoing(object value) { var result = value as string; if (result == null) return null; return Value + result; } } public class ComplexRoute : Route { public ComplexRoute(string url, object defaults, object rules) : this(url, new RouteValueDictionary(defaults), rules) { } public ComplexRoute(string url, RouteValueDictionary defaults, object rules) : base(url, defaults, new MvcRouteHandler()) { Rules = new Dictionary<string, IRouteRule>(); foreach (var pair in new RouteValueDictionary(rules)) Rules.Add(pair.Key, (IRouteRule)pair.Value); } public Dictionary<string, IRouteRule> Rules { get; protected set; } public override RouteData GetRouteData(HttpContextBase httpContext) { var result = base.GetRouteData(httpContext); if (result == null) return null; foreach (var pair in Rules) { var currentValue = result.Values[pair.Key]; if (currentValue == null) return null; var value = pair.Value.ProcessIncoming(currentValue); if (value == null) return null; result.Values[pair.Key] = value; } return result; } public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { values = new RouteValueDictionary(values); foreach (var pair in Rules) { var currentValue = values[pair.Key]; if (currentValue == null) return null; var value = pair.Value.ProcessOutgoing(currentValue); if (value == null) return null; values[pair.Key] = value; } return base.GetVirtualPath(requestContext, values); } }用法:
routes.Add(new ComplexRoute( "suggestion/{id}/{it}/{if}", new { controller = "suggestion", action = "details" }, new { @if = new StartsWithRouteRule("would-be-better-if-") }));