网站重构与旧链接处理

拥有一个网站意味着需要投入时间和精力在互联网上推广,确保搜索引擎索引所有页面,并通过博客或讨论板获得曝光。然后,当有了新的想法,真的需要重新组织网站——改变一些文件夹名称,移动一些页面等。那么,那些曾经引以为豪的第三方链接会发生什么?想要失去它们吗?

在.NET Framework 3.5 SP1的到来,有了一个优雅的解决这个问题的方法——ASP.NET路由。最初,它是ASP.NET MVC Preview 2的一部分,现在它已经成为框架的一部分。

这个想法是向网站添加特殊的“路由”,其单一目标是处理对不再存在于网站上的页面的请求。在其最简单的形式中,处理可以在一个ASPX页面中完成,该页面负责正确处理请求。

下面是一个示例:

附加的项目包含了所需要的所有部分:

  • WebFormRouteHandler
  • 由Chris Cavanagh创建,代表一个IRouteHandler实现
  • Global.asax文件注册路由
  • web.config文件注册WebFormRouteHandler
  • Default.aspx页面负责实际的请求处理

让看看Global.asax:

void Application_Start(object sender, EventArgs e) { // 运行在应用程序启动时 RegisterMyRoutes(System.Web.Routing.RouteTable.Routes); } private void RegisterMyRoutes(System.Web.Routing.RouteCollection routes) { // 引用IRouteHandler实现 // (示例由Chris Cavanagh创建) // 参见 http://chriscavanagh.wordpress.com/2008/03/11/aspnet-routing-goodbye-url-rewriting/ var startPageRouteHandler = new WebFormRouteHandler("~/default.aspx"); // 排除.axd以处理Web服务和AJAX,而不需要检查所有路由 // 参见 http://msdn.microsoft.com/en-us/library/ // system.web.routing.stoproutinghandler.aspx routes.Add(new System.Web.Routing.Route("{resource}.axd/{*pathInfo}", new System.Web.Routing.StopRoutingHandler())); routes.Add(new System.Web.Routing.Route("{service}.asmx/{*path}", new System.Web.Routing.StopRoutingHandler())); // 映射: // 提取文件夹名称和页面名称作为HttpContext.Items中的项 routes.Add(new System.Web.Routing.Route("{folderName}/", startPageRouteHandler)); routes.Add(new System.Web.Routing.Route("{folderName}/{pageName}", startPageRouteHandler)); }

在这里,定义了一个单一的路由处理器——default.aspx,以及路由规则。

规则#1:

routes.Add(new System.Web.Routing.Route("{folderName}/", startPageRouteHandler));

表明所有结构为"http://mysite.com/something"的URL请求将由default.aspx页面处理,如果网站上没有实际的"something"。例如,如果网站上有RealPage.aspx页面,那么对http://mysite.com/RealPage.aspx的请求将由该页面处理。

但是,如果客户端请求RealPage2.aspx,那么该请求将由default.aspx页面根据规则#1处理。请注意,客户端不会被重定向到default.aspx,它将只是Web服务器在响应请求时运行default.aspx中的代码。对于客户端来说,响应将来自RealPage2.aspx。

可以添加尽可能多的路由,例如规则#2:

routes.Add(new System.Web.Routing.Route("{folderName}/{pageName}", startPageRouteHandler));

表明所有结构为"http://mysite.com/somefolder/somethingelse"的URL请求将由default.aspx页面处理,如果网站上没有实际的"somefolder/somethingelse"。

default.aspx的代码背后展示了如何提取请求的这些部分。如所见,它们将被放置在HttpContext.Items集合中。

lblFolder.Text = Context.Items["folderName"] as string; lblPage.Text = Context.Items["pageName"] as string;

在现实生活中的应用:

这里有一个实际使用这种技术的网站——Digitsy Global Store。除了处理过时的URL,ASP.NET路由还被用来处理网站上的多种语言,实时切换CultureInfo:

protected void Page_PreInit(object sender, EventArgs e) { CultureInfo lang = new CultureInfo(getCurrentLanguage()); Thread.CurrentThread.CurrentCulture = lang; Thread.CurrentThread.CurrentUICulture = lang; } private static string getCurrentLanguage() { string lang = HttpContext.Current.Items["language"] as string; switch (lang) { case "france": return "fr-FR"; case "canada": return "en-CA"; case "germany": return "de-DE"; case "japan": return "ja-JP"; case "uk": return "en-GB"; case "russia": return "ru-RU"; default: return "en-US"; } }

如所见,默认语言是英语,美国:"en-US"。在内部链接中,网站使用结构http://{sitename}/{language}/…其他东西…

所以,如果尝试http://digitsy.com/us/,将得到美国版本,尝试http://digitsy.com/japan/将带去日本版本,如果尝试http://digitsy.com/whatever/——不会得到404错误,将再次得到美国版本。

ASP.NET路由使网站的重构变得非常容易。文件夹结构"{language}/{index}/category/{categoryID}"最近被替换为"{language}/{index}/shopping/{categoryID}"。网站上不应该再有"category"文件夹。但由于两个路由都指向同一个处理页面,两个文件夹"category"和"shopping"都返回有效响应。

尝试http://digitsy.com/us/Electronics/shopping/541966将使用规则:

routes.Add(new System.Web.Routing.Route("{language}/{index}/shopping/{categoryID}", categoryRouteHandler));

而尝试http://digitsy.com/us/Electronics/category/541966将使用:

routes.Add(new System.Web.Routing.Route("{language}/{index}/category/{categoryID}", categoryRouteHandler));

两者都将解析到同一个路由处理页面。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485