2014-05-02 59 views
2

我正在創建URL別名功能;的能力,資源映射A到B別名自定義ASP MVC路由中的URL

我安裝這個資源與映射到一個自定義的路由解析傳入URL字符串並查找URL部分我們的數據庫裏面的一個包羅萬象的URL的項目。基本上,整個URL字符串是動態的,並映射到類別層次結構(例如/輪胎/汽車/輪胎/麪包車,/暫停/福特/焦點)。這一切工作正常,只存在路由到一個控制器。

目前我正在整合我的網址別名代碼到這條路線,因爲我們目前只允許這些動態路由的別名。它會查找傳入的數據庫URL以查看是否存在別名,然後抓取它映射到的原始URL並將該字符串傳遞給我們的URL解析器。這感覺很骯髒,關心和所有的分離。

我認爲一個更好的方法是映射兩個單獨的路線。一,URLAliasRoute,另CustomWebsiteRoute。路線是否可能影響其他路線將看到的網址?

所以,想象一下,我有以下途徑映射:

UrlAliasRoute aliasRoute = new UrlAliasRoute("{*url}"); 
routes.Add(aliasRoute); 
CustomWebsiteRoute customRoute = new CustomWebsiteRoute("{*url}"); 
routes.Add(customRoute); 
routes.MapRoute("Contact Us", "contact", new { controller = "Contact" }); 
routes.MapRoute("About Us", "about", new { controller = "About" }); 
//etc 

和URL 汽車/輪胎化名爲汽車輪胎

所以當/小車 - 傳入的請求輪胎進來後,我的UrlAliasRoute會在數據庫中查看它,看看是否有「汽車/輪胎」的映射,然後將RouteData URL從「car-tires」更改爲「car/tires」。所有其他路線然後使用汽車/輪胎作爲匹配路線約束的URL?

這也將有允許開發人員已經編寫...潛在的危險,但東西,我會小心的任何預定義的路線走樣的利益。

似乎是一個很好的解決方案,但我一直在努力尋找如何更改URL,其他線路將GetRouteData後收到()被調用。

回答

2

我一般使用下面的方法。首先內Routeconfig靠近頂部註冊新Routebase(稱爲LegacyURLRoute):

routes.Add(new LegacyUrlRoute()); 

甲削減的這個版本如下:

public class LegacyUrlRoute : RouteBase 
{ 
    public override RouteData GetRouteData(HttpContextBase httpContext) 
    { 
     var request = httpContext.Request; 
     var response = httpContext.Response; 
     var legacyUrl = request.Url.ToString().ToLower(); 
     var legacyPath = request.Path.ToString().ToLower(); 

     Tuple<bool, bool, string> result = DervieNewURL(legacyPath); 
     bool urlMatch = result.Item1; 
     bool urlMatchGone = result.Item2; 
     var newUrl = result.Item3; 

     if (urlMatch) 
     {//For 301 Moved Permanently 
      response.Clear(); 
      response.StatusCode = (int)System.Net.HttpStatusCode.MovedPermanently; 
      response.RedirectLocation = "http://www.example.com" + newUrl; 
      response.End(); 
     } 
     else if (urlMatchGone) 
     {// 410 Gone 
      response.Clear(); 
      response.StatusCode = (int)System.Net.HttpStatusCode.Gone; 
      response.End(); 
     } 
     return null; 
    } 
    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 
    { 
     return null; 
    } 
} 

上述DervieNewURL然後可以包括在DB中查找,但最近在一個項目中,我將它作爲HTMLHelper使用,它還允許我傳入直接來自數據庫列的URL,然後可以根據需要對其進行解析和更新。 DervieNewURL的

簡單的例子可能是如下,但你會在一個表中查找明顯,而不是硬編碼如下位。

public static Tuple<bool, bool, string> DervieNewURL(string url) 
{ 
    /* 
     return type from this function is as follows: 
     Tuple<bool1, bool2, string1, string2> 
     bool1 = indicates if we have a replacement url mapped 
     bool2 = indicates if we have a url marked as gone (410) 
     string1 = indicates replacement url 
     */ 
    Tuple<bool, bool, string> result = new Tuple<bool, bool, string>(false, false, null); 
    if (!String.IsNullOrWhiteSpace(url)) 
    { 
     string newUrl = null; 
     bool urlMatch = false; 
     bool urlMatchGone = false; 

     switch (url.ToLower()) 
     { 
      case "/badfoldergone/default.aspx": { urlMatchGone = true; } break; 
      case "/oldfoldertoredirect/default.aspx": { urlMatch = true; newUrl = "/somecontroller/someaction"; } break; 
      default: { } break; 
     } 
     result = new Tuple<bool, bool, string>(urlMatch, urlMatchGone, newUrl); 

    } 
    return result; 
} 

如果你需要通配符匹配,那麼我想你可以修改上述內容或將其構建到數據庫調用匹配條件中。

通過在早期使用此路由,您可以將傳統url重定向到其他路由,然後在請求級聯到路由表中時觸發其他路由。最終你會以類似於您的默認路由結束:

routes.MapRoute(
    name: "Default", 
    url: "{controller}/{action}/{id}", 
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
); 

如果開發商都硬編碼鏈接,然後你只需要使用將由這些網址的觸發路線。通過採用上述方法,可以儘早捕獲並添加到您的數據庫列表中,並根據需要添加適當的301 Move或410。

+0

非常感謝您的詳細解答!不幸的是,我已經將所有的URL別名信息都放到了我的CustomWebsiteRoute中,因爲我有一些奇怪的需求,在這裏可以輕鬆完成。你的回答仍然有幫助,再次感謝。 –