2015-04-23 34 views
0

這可以完成使用ASP.NET 4.0 Web窗體創建的我的網站上列出了約1700篇文章。這些文章的URL格式爲:可以使用ASP.NET URL重寫

http://www.mymymyarticles.com/Article.aspx?ID=400 

我已經探索了ASP.NET友好URL以及IIS URL重寫。這些擴展名很好,但一旦創建了規則,他們一般會處理所有網址。

是否有可能手動爲我的網站上存在的每個網址生成自己的網址字符串?對於如:

我想永久重定向http://www.mymymyarticles.com/Article.aspx?ID=400http://www.mymymyarticles.com/this-is-a-very-long-url

http://www.mymymyarticles.com/Article.aspx?ID=500可以重定向到http://www.mymymyarticles.com/article/short-url

http://www.mymymyarticles.com/Article.aspx?ID=523可以重定向到http://www.mymymyarticles.com/very-short-url

所以,你可以看到有在沒有統一我想手動生成的網址。基本上我想完全控制網址。我怎麼去解決這個問題。 它會影響性能嗎?

任何例子的讚賞。

+0

據我所見,你想有效地將​​一個整數'ID'變成一個url slug?猜測,這個slu is是文章的標題?如果是這樣,我認爲你只需要兩條路線,一條接受'.../Article.aspx?ID = {int}',查找與id相關的文章的標題併發送一個301/302響應回到重定向到'.../article/{slug}' –

+0

我該如何解決它?文章/ {slug}部分是我想控制的東西 – Hitz

+0

我對此有動態解決方案,但您的URL應該看起來像'http://www.mymymyarticles.com/artid/102/this-is-a-very- long-url',爲此你必須在你的web.config文件中寫入URL重寫規則。 – Keval

回答

0

你有一個ID映射到新頁面的URL的一種方式?如果是這種情況,您可以通過ASP.NET路由實現此目的。我會做的是先從定義路線:

var route = routes.MapRoute(
    "LegacyDocument", 
    "Articles.aspx{*pathInfo}", 
    null, 
    constraints: new { pathInfo = new LegacyDocumentRouteConstraint() } 
); 
route.RouteHandler = new RedirectRouteHandler(); 

這條路線僅僅採集任何請求/articles.aspx,但它有一個約束,一個自定義的路由處理。

約束的目的是保證我們至少有ID查詢字符串屬性,它是一個數字:

public class LegacyDocumentRouteConstraint : IRouteConstraint 
{ 
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) 
    { 
     if (routeDirection == RouteDirection.UrlGeneration) 
     { 
      // Don't both doing anything while we generate links. 
      return false; 
     } 

     string id = httpContext.Request.QueryString["id"]; 
     if (string.IsNullOrWhiteSpace(id)) 
     { 
      // No query string argument was provided. 
      return false; 
     } 

     int documentId; 
     if (!int.TryParse(id, out documentId)) 
     { 
      // The Id is not a number. 
      return false; 
     } 

     // Set the output document Id in the route values. 
     values["documentId"] = documentId; 
     return true; 
    } 
} 

如果ID沒有被提供,或者是不是一個數字,我們可以」與現有文檔匹配,所以路由將被跳過。但是,當滿足約束條件,我們存儲在路線的變量值values["documentId"] = documentId所以我們可以遲一些再在路由處理程序使用(而不必再次查詢字符串解析它):

public class RedirectRouteHandler : IRouteHandler 
{ 
    public IHttpHandler GetHttpHandler(RequestContext context) 
    { 
     int documentId = (int)context.RouteData.Values["documentId"]; 

     return new RedirectLegacyDocumentHttpHandler(documentId); 
    } 

    private class RedirectLegacyDocumentHttpHandler : IHttpHandler 
    { 
     private int _documentId; 

     public RedirectHttpHandler(int documentId) 
     { 
      _documentId = documentId; 
     } 

     public bool IsReusable { get { return false; } } 

     public void ProcessRequest(HttpContext context) 
     { 
      var response = context.Response; 

      string url = ResolveNewDocumentUrl(); 
      if (url == null) 
      { 
       // Issue a 410 to say the document is no longer available? 
       response.StatusCode = 410; 
      } 
      else 
      { 
       // Issue a 301 to the new location. 
       response.RedirectPermanent(url); 
      } 
     } 

     public string ResolveNewDocumentUrl() 
     { 
      // Resolve to a new url using _documentId 
     } 
    } 
} 

路由處理器執行從ASP.NET路由映射回到ASP.NET運行時的IHttpHandler邏輯的邏輯。在普通的MVC中,這將映射到調用控制器的標準MvcHandler,但在我們的情況下,我們只需要發出重定向。

在路由處理程序中,我們從路由值中獲取文檔ID,並創建一個執行實際重定向的新HTTP處理程序。你需要在解決實際的新網址(ResolveNewDocumentUrl)的位置上鑽取,但通常它會解析url,如果url返回爲null,我們將發出一個HTTP 410 Gone的響應以對客戶說(更重要的是抓取工具)該項目已不在那裏,否則它將發出一個HTTP 301 Permanent Redirect以及適當的位置標題到新的url。

+0

優秀的迴應。我會試試看。謝謝馬修! – Hitz

0

我曾與下面的架構

<URLMapper> 
    <Code>1</Code> 
    <OLDURL>%Oldurl.aspx%</OLDURL> 
    <NEWURL>default.aspx</NEWURL> 
    <PermanentRedirect>true</PermanentRedirect> 
    <Order>1</Order> 
    <Status>true</Status> 
    </URLMapper> 

中的Application_Start事件時加載的這一個應用程序變量(在數據表的形式)在服務器上創建一個XML文件,克服這一點。

而且在開始請求 -

void Application_BeginRequest(object sender, EventArgs e) 
     {    
      if (Application["URLMapper"] == null) return; 
      DataTable dtURLs = Application["URLMapper"] as DataTable; 

      if (dtURLs.Rows.Count == 0) return; 

      string OrigUrl = HttpContext.Current.Request.Url.ToString().ToLower().Replace("'", "`"); 

      DataRow[] drFound = dtURLs.Select("Status = true and '" + OrigUrl.Trim() + "' like oldurl", "Order",DataViewRowState.CurrentRows); 
      if (drFound.Length == 0) return; 
      string OldURL = drFound[0]["OldURL"].ToString().Replace("%",""); 

      Response.RedirectPermanent(OrigUrl.Replace(OldURL, drFound[0]["NewURL"].ToString().Trim()), true); 

      return; 
     } 
+0

謝謝阿卜杜勒。大概你映射了多少個URL。一個XML文件解析通常很慢,1700個url會殺死它。 – Hitz

+0

大約400. Bcoz xml很慢,我不得不在應用程序啓動時只加載一次,以儘量減少文件IO。沒有遇到任何性能問題。 –