13

我有一個ASP.NET MVC 3應用程序,用戶可以發佈沿線的建議「喇嘛喇嘛會更好,如果亞達內容十分重要」。 您的建議詳細信息頁面我如下定義了一個不錯SEO友好路線:失敗的ASP.NET MVC路由。這是一個錯誤還是角落案例?

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's Routing Debugger並確認路線實際上會運行到suggestion/84/this-site/would-be-better-if-would-be-better-if-,所以第二個「would-be-better-if」實際上被接受了;之後添加任何實際上會造成網址無法匹配任何路線(感謝奧馬爾 - 參見評論 - 求助)


請記住,我真的不想改變路線定義,因爲我認爲這是一樣好,我可以管理這種情況下,搜索引擎優化,明智的。

所以,有文字等於航線的固定部分是怎麼來防止路由匹配的聯繫? 爲什麼是路由斷裂了嗎?

我實際上對更感興趣,爲什麼,因爲我相信理解爲什麼會導致解決方案或至少正確理解一個相當有趣的問題。

+2

這非常有趣。不知道它爲什麼會發生,但是如果您想要臨時修復,請用'/ {if}'替換' - {if}'。我猜ASP.NET MVC對待'/'不同於其他字符。 – Omar 2011-03-11 23:15:00

+1

一些測試表明,路線「建議/ 84 /本網站/將會更好 - 如果將會更好 - 如果 - 」有效;只有在最後一個'-'後面有任何東西之後,它纔會中斷。 – Omar 2011-03-11 23:20:44

+0

@Omar - 我真的*不想改變路線,儘管你提出的解決方法是完全可以接受的。關於你的第二條評論,謝謝,我完全錯過了那個......如果你問我,這更讓人好奇。 – 2011-03-11 23:26:29

回答

5

我不知道爲什麼它的行爲這樣,但你可以使用這樣的事情:

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-") })); 
+0

áš - 這可能工作(還沒有嘗試過),但我其實很感興趣*爲什麼*這是路線中斷。 – 2011-03-12 20:24:04

+0

我會傾向於同意它打破的原因是它是一個錯誤。你有沒有在MVC團隊中的任何人跑過這個? – 2011-03-14 15:17:04

+0

@Matt - 我其實沒有,但我想我會馬上去做。謝謝你的提示。 – 2011-03-14 20:49:37