2015-04-23 78 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。没有遇到任何性能问题。 –