ASP.NET 路由實現頁面靜態化(附在線Demo和Source)


頁面靜態化最大的好處是利於SEO,即使是偽靜態,搜索引擎也會覺得這是一個較為友好的Url。Url的友好也取決於其命名,為一篇描述古代文學的頁面起名用ancient-literature.html當然比隨便起的名字例如aa.html之流要友好。頁面靜態化並不代表你一定要用后綴名為.html或.htm的鏈接來顯示你的頁面,你完全可以不用任何后綴名(就像MVC一樣),只要Url結構良好。

實現靜態化的三個目標:

1. 實現頁面靜態化,頁面中的鏈接都用.html來表示,但每個.html實際都映射了一個.aspx頁面。

例如:當用戶請求index.html頁面時,實際請求的是Default.aspx頁面,index.html的物理路徑在網站中並不存在。

2. 實現請求.aspx頁面時自動跳轉到對應的靜態映射頁面。

例如:當用戶請求Default.aspx頁面,自動跳重定向到index.html頁面

3. 自定義404頁面的實現,當請求的路徑既不在映射表中,也不在網站的虛擬路徑中時,它將自動跳轉到我預先設定好的404頁面。

實現以上要點,需要用到ASP.NET Url Routing、HttpHandler和HttpModule技術。

這是一個小系列的文章,這一篇文章將詳細解說並實現第1點。

一、項目創建

1. 創建一個ASP.NET Web Application項目

SNAGHTMLf9ef62

image

2. 創建web.config文件

ASP.NET Membership在這里使用不到,所以生成的web.config配置沒有用處,刪掉它並重新創建一個新的web.config文件

<?xml version="1.0"?>
<configuration>

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

</configuration>

3. 將網站添加到IIS6或IIS7中

SNAGHTML1048e8d

默認的ASP.NET Web Application已經為我們提供了不少頁面,我就在下面的例子中將它們靜態化吧。

二、頁面靜態化實現

1. 添加Routing引用

由於這里需要用到ASP.NET的路由映射(從.NET 3.5開始誕生),所以需要在項目中添加System.Web.Routing引用。

SNAGHTMLfc9503

SNAGHTML1007756

2. 添加WebHandler和WebModule文件夾

這兩個文件夾分別用於存放IHttpHandler和IHttpModule。

3. 將所有.aspx后綴的超鏈接更改為.html

Site.Master文件:

<asp:Menu ID="NavigationMenu" runat="server" CssClass="menu" EnableViewState="false" IncludeStyleBlock="false" Orientation="Horizontal">
    <Items>
        <asp:MenuItem NavigateUrl="~/Index.html" Text="Home"/>
        <asp:MenuItem NavigateUrl="~/About.html" Text="About"/>
    </Items>
</asp:Menu>

Account文件夾ChangePassword.aspx文件:

<asp:ChangePassword ID="ChangeUserPassword" runat="server" CancelDestinationPageUrl="~/" EnableViewState="false" RenderOuterTable="false" 
         SuccessPageUrl="ChangePasswordSuccess.html">

當然現在這三個靜態鏈接都訪問不到,因為它們的物理地址不存在。

下面我們要做的就是:

1) 請求Index.html時實際請求的是Default.aspx

2) 請求About.html時實際請求的是About.aspx

3) 請求Account/Login.html時實際請求的是Account/Login.aspx

4. 添加自定義的IRouteHandler實現

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; }
        
        public CustomRouteHandler(string virtualPath)
        {
            this.VirtualPath = virtualPath;
        }

        /// <summary>
        /// 返回實際請求頁
        /// </summary>
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            var page = BuildManager.CreateInstanceFromVirtualPath(VirtualPath, typeof(Page)) as IHttpHandler;
            return page;
        }
    }
}

5. 在Global.asax文件中注冊路由

先來個簡單的實現:

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

namespace Routing_Static_Page_Demo
{
    public class Global : System.Web.HttpApplication
    {

        void Application_Start(object sender, EventArgs e)
        {
            RegisterRoutes();
        }

        /// <summary>
        /// 注冊路由
        /// </summary>
        private void RegisterRoutes()
        {
            
            //將Index.html請求映射為Default.aspx
            RouteTable.Routes.Add("Default",
                                  new Route("Index.html",
                                            new CustomRouteHandler("~/Default.aspx")));

            // 將About.html請求映射為About.aspx
            RouteTable.Routes.Add("About",
                                  new Route("About.html",
                                            new CustomRouteHandler("~/About.aspx")));

            // 將Account/Login.html請求映射為/Account/Login.aspx
            RouteTable.Routes.Add("Login",
                                  new Route("Account/Login.html",
                                            new CustomRouteHandler("~/Account/Login.aspx")));
        }
    }
}

在VS中直接運行站點(VS自帶的WebDev服務器),點擊這些鏈接都能夠正常訪問。

三.  在IIS 7下設置站點

下面的設置很重要,因為上面在VS自帶的web服務器中雖然跑通了,但IIS 7下是運行不通過的(IIS 6下的設置很簡單,本文的在線Demo是運行在IIS 6下的)

1. 初次在IIS 7下運行該網站,會出現下面的錯誤。

SNAGHTML2cedf45

這是因為IIS對該Web站點目錄沒有讀寫權限。

在IIS下:右鍵站點 >  Edit Permissions > Security > Edit > Add > 輸入IIS_IUSRS > Check Names > OK。

選擇完畢后,為IIS_IUSRS用戶添加Full Control權限。

image

image

SNAGHTML2f152df[4]

2. 添加完該設置后,再運行一次網站,可能會出現下面的錯誤。

SNAGHTML2f65a2f

按照上面的步驟添加IUSR用戶,為IUSR用戶分配Read權限即可。

SNAGHTML2f8d75a

再次運行網站,能夠正常訪問頁面了。

SNAGHTML2fd7e14

3.  配置web.config

網站雖然能運行,但是點擊Home或About鏈接時會出現404錯誤。

SNAGHTML2ff02fc

i. 首先確保在安裝IIS時你已經勾選了HTTP Reirection

如果沒有安裝這個功能,按照如下設置再配置一遍IIS

Control Panel --> Progams --> Turn off windows features --> World wide web Services --> Common HTTP Features –> HTTP Redirection

ii. 修改web.config文件,在webserver中注冊RoutingHandler和RoutingModule

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

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </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" />
    </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>

注意: 如果你采用的是ASP.NET 3.5 Routing或使用IIS 6,web.config配置會不一樣。

iii. 確保web站點的應用程序池選擇的是集成模式,因為ASP.NET 4.0 Routing並不支持經典模式

SNAGHTML32bdeab

OK,似乎所有的該配置的地方都配置了,那么再去點擊Index.html或About.html鏈接試試吧。

SNAGHTML32d4edb

如果現在去訪問Login.html頁面,還是會得到一個401.3的錯誤,更改Account目錄下的web.config文件:

<?xml version="1.0"?>
<configuration>

  <location path="Register.aspx">
    <system.web>
      <authorization>
        <allow users="*"/>
      </authorization>
    </system.web>
  </location>

  <system.web>
    <!--<authorization>
      <deny users="?"/>
    </authorization>-->
  </system.web>

</configuration>

如果你不需要這個web.config文件,直接刪掉也可以。

四. 更改RegisterRoutes方法

上面提供的注冊路由的方式屬於硬編碼,需要為每一個.aspx頁面指定映射路由。Account目錄下還有一些.aspx文件,如果增加別的目錄也存放.aspx頁面,為了讓每個頁面都靜態化,RegisterRoutes方法將會是產生很多重復代碼。

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

namespace Routing_Static_Page_Demo
{
    public class Global : System.Web.HttpApplication
    {

        void Application_Start(object sender, EventArgs e)
        {
            RegisterRoutes();
        }

        /// <summary>
        /// 注冊路由
        /// </summary>
        private void RegisterRoutes()
        {
            
            //將Index.html請求映射為Default.aspx
            RouteTable.Routes.Add("Default",
                                  new Route("Index.html",
                                            new CustomRouteHandler("~/Default.aspx")));

            // 將About.html請求映射為About.aspx
            RouteTable.Routes.Add("About",
                                  new Route("About.html",
                                            new CustomRouteHandler("~/About.aspx")));

            // 遍歷頁面存放目錄,為每個.aspx頁面添加路由映射
            foreach (string mapPth in _pageMapPath)
            {
                string path = Server.MapPath(mapPth);
                var directoryInfo = new DirectoryInfo(path);
                foreach (FileInfo f in directoryInfo.GetFiles())
                {
                    string fileName = f.Name;
                    if (fileName.EndsWith(".aspx"))
                    {
                        string routeName = fileName.Substring(0, fileName.Length - 5);
                        string url = string.Concat(mapPth.Substring(2), routeName, ".html");
                        RouteTable.Routes.Add(routeName,
                                              new Route(url,
                                                        new CustomRouteHandler(string.Concat(mapPth, fileName))));
                    }
                }
            }
            
        }

        // 頁面存放目錄
        private readonly string[] _pageMapPath = {@"~/Account/"};
    }
}

以上代碼就能實現為每個.aspx頁面注冊路由實現靜態化。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM