ASP.NET 页面双向静态化

在上一篇博文ASP.NET 路由实现页面静态化中我已经详细介绍并实现了.html页面到.aspx页面的映射,当然这属于伪静态,而且是单向的。

现在我们来实现第2点,当用户请求Default.aspx页面时,自动重定向到Index.html页面。甚至当用户请求某些.aspx页面时,自动跳转到与之对应的.html页面。

按照这个逻辑,必然会造成循环请求,不断地产生子请求,请求流程如下图:

image

而我们预期的结果应该如下图,实际只请求两次。

image

用301重定向可以解决该循环请求产生的问题。

1. 修改CustomRouteHandler类,添加RequestPath属性

using System.Web;
using System.Web.Compilation;
using System.Web.Routing;
using System.Web.UI;

namespace Routing_Static_Page_Demo.WebHandler
{
    public class CustomRouteHandler : IRouteHandler
    {
        /// <summary>
        /// 虚拟路径
        /// </summary>
        public string VirtualPath { get; private set; }

        /// <summary>
        /// 请求路径
        /// </summary>
        public string RequestPath
        {
            get { return VirtualPath.Substring(1); }
        }
        
        public CustomRouteHandler(string virtualPath)
        {
            this.VirtualPath = virtualPath;
        }

        /// <summary>
        /// 返回实际请求页
        /// </summary>
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            foreach (var urlParm in requestContext.RouteData.Values)
            {
                requestContext.HttpContext.Items[urlParm.Key] = urlParm.Value;
            }
            var page = BuildManager.CreateInstanceFromVirtualPath(VirtualPath, typeof(Page)) as IHttpHandler;

            return page;
        }
    }
}

RequestPath属性是从VirtualPath过来的,如果VirtualPath为~/default.aspx,那么对应的RequestPath则是/default.aspx

2. 在WebModule下创建CustomHttpModule.cs类

using System;
using System.Globalization;
using System.Web;
using System.Web.Routing;
using Routing_Static_Page_Demo.WebHandler;

namespace Routing_Static_Page_Demo.WebModule
{
    public class CustomHttpModule : IHttpModule
    {

        private HttpApplication app;

        public void Init(HttpApplication context)
        {
            app = context;
            app.AuthorizeRequest += App_AuthorizeRequest;
        }

        public void App_AuthorizeRequest(object sender, EventArgs e)
        {
            HttpRequest req = app.Request;
            string path = req.Path;

            // 如果是.aspx页面
            if (path.EndsWith(".aspx", true, CultureInfo.CurrentCulture))
            {

                // routeUrl则用于存放对应的.html
                string routeUrl = string.Empty;

                // 遍历RouteTable,找到.aspx页面对应的.html
                foreach (Route route in RouteTable.Routes)
                {
                    // 获取CustomRouteHandler
                    var handler = (CustomRouteHandler) route.RouteHandler;
                    // 获取CustomRouteHandler的RequestPath
                    string requestPath = handler.RequestPath;

                    if (requestPath.ToLower() == path.ToLower())
                    {
                        routeUrl = route.Url;
                        break;
                    }
                }

                // 将.aspx页面永久重定向到对应的.html页面
                app.Response.StatusCode = 301;
                app.Response.AddHeader("Location", "/" + routeUrl);
                app.Response.End();
            }
        }

        public void Dispose()
        {

        }
    }
}

如果你不太熟悉HttpApplication的事件,可以参照:MSDN HttpApplication事件
如果你不太熟悉HttpApplication的用法,可以参照:MSDN HttpApplication类

3. 修改web.config文件,添加HttpModule配置

黄色标记的地方是添加的,其它配置不变。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />

    <httpModules>
      <

add name="CustomHttpModule" type="Routing_Static_Page_Demo.WebModule.CustomHttpModule, Routing_Static_Page_Demo"

/>
    </httpModules>
  </system.web>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="UrlRoutingModule"/>
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, 
                                          System.Web, 
                                          Version=4.0.0.0, 
                                          Culture=neutral, 
                                          PublicKeyToken=b03f5f7f11d50a3a" />

      <

add name="CustomHttpModule" type="Routing_Static_Page_Demo.WebModule.CustomHttpModule"

/>
    </modules>
    <handlers>
      <add name="UrlRoutingHandler" 
                                  preCondition="integratedMode" 
                                  verb="*" path="UrlRouting.axd"
                                  type="System.Web.HttpForbiddenHandler, System.Web,
                                        Version=2.0.0.0, Culture=neutral,
                                        PublicKeyToken=b03f5f7f11d50a3a"/>
      
      
      
    </handlers>
  </system.webServer>

</configuration>

在VS自带的WebDev服务器中运行这个项目:在浏览器栏输入http://localhost:xxxx/Default.aspx,会自动跳转到http://localhost:xxxx/Index.html,运行默认路径http://loclhost:xxxx/也会自动跳转到http://localhost:xxxx/Index.html

4. 在IIS中运行项目

WebDev运行虽然通过了,IIS可不见得通过,毕竟WebDev的权限太高了。

果然,运行之后,出现下面的错误画面:

SNAGHTML9af826

还是web.config的配置问题。在<webserver>节点下添加下面一行配置:

<validation validateIntegratedModeConfiguration="false"/>

这一行配置并不会真正影响web应用程序的安全性,它只是用于关闭有些配置将不会被使用的警告。

That’s end, have fun.

posted @ 2012-04-01 12:40  keepfool  阅读(2817)  评论(6编辑  收藏  举报