Asp.net-Mvc

ASP.NET MVC 路由失敗。這是錯誤還是極端情況?

  • September 19, 2011

我有一個 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-") }));

引用自:https://stackoverflow.com/questions/5279040