利用 ASP.NET3.5(ASP.NET4.0) 的路由功能建立搜尋引擎友好的 URL

孟子E章發表於2010-01-18

注意:本文所講述的並非MVC框架。

ASP.NET 3.5 SP1中提供了一種路由技術。ASP.NET 路由是一種能夠使我們在ASP.NET應用程式中利用一種可描述的、對搜尋引擎和使用者很友好的URL訪問資源的技術。這種URL不必物理地對映到真正的資源。比如:
http://dotnet.aspx.cc/Article.aspx?articleId=8d01fd5e-b2c1-40f5-8cea-bc2197fb9bd8
這個 URL 實際上是對映到網站根目錄下的一個Article.aspx檔案。使用ASP.NET路由技術,可以使用類似下面的URL進行訪問:
http://dotnet.aspx.cc/article/8d01fd5e-b2c1-40f5-8cea-bc2197fb9bd8/read.aspx

實現這種URL,有兩種技術可以做到:URL重寫和 URL路由:
1,URL 重寫通過在將請求傳送到網頁之前實際更改 URL 來處理傳入請求。例如,一個使用 URL 重寫的應用程式可能會將 URL 從 /article/8d01fd5e-b2c1-40f5-8cea-bc2197fb9bd8/read.aspx 更改為 /Article.aspx?articleId=8d01fd5e-b2c1-40f5-8cea-bc2197fb9bd8。此外,URL 重寫通常沒有相應的 API 來建立基於模式的 URL。在 URL 重寫中,如果更改了 URL 模式,則必須手動更新包含原始 URL 的所有超連結。
2,由於 ASP.NET 路由可以從 URL 提取值,所以處理傳入請求時不更改 URL。如果必須建立一個 URL,則將引數值傳遞到為您生成 URL 的方法中。若要更改 URL 模式,請在某位置更改該模式,您在應用程式中建立的基於該模式的所有連結將自動使用新模式。

若要啟用路由,必須更改應用程式的配置檔案來註冊路由程式集,並新增 UrlRoutingModule 類作為模組。還必須為路由建立一個自定義路由處理程式。該處理程式實現IRouteHandler 介面並建立 Web 窗體(.aspx 檔案)的一個例項,該例項將為請求的實際終結點。

下面我們就以完整的例子來簡單說明如何在網站釋出系統中使用這項技術。

1,首先建立表 Article 用來儲存文章資料內容,從 SQL Server 2000 建立指令碼功能建立出SQL語句:

SQL 程式碼
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --&gtCREATE TABLE [Article] (
    
[ArticleId] [int] IDENTITY (1, 1) NOT NULL ,
    
[Title] [nvarchar] (255) COLLATE Chinese_PRC_CI_AS NOT NULL ,
    
[CreateDate] [datetime] NOT NULL CONSTRAINT [DF_Article_CreateDate] DEFAULT (getdate()),
    
[Content] [ntext] COLLATE Chinese_PRC_CI_AS NOT NULL ,
    
CONSTRAINT [PK_Article] PRIMARY KEY  CLUSTERED
    (
        
[ArticleId]
    )  
ON [PRIMARY]
)
ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO


2,在VS2008SP1或者VS2010中,新建一個ASP.NET網站,新增對System.Web.Routing的引用;
 

3,建立自定義路由處理程式,在網站工程中新增新項“類”,命名為ArticleRouteHandler.cs,類的網站內容如下:

C# 程式碼
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --&gtusing System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

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

///
///ArticleRouteHandler 的摘要說明
///
public class ArticleRouteHandler : IRouteHandler
{
  
public ArticleRouteHandler()
  {
    
//
    
//TODO: 在此處新增建構函式邏輯
    
//
  }

  
public IHttpHandler GetHttpHandler(RequestContext requestContext)
  {
    
string ArticleGuid = requestContext.RouteData.Values["ArticleGuid"] as string;
    HttpContext context
= HttpContext.Current;
    context.Items.Add(
"ArticleGuid", ArticleGuid);
    
string action = (requestContext.RouteData.Values["Action"] as string).ToLower();
    
if (action.Equals("read"))
      
return BuildManager.CreateInstanceFromVirtualPath("~/ArticleShow.aspx", typeof(Page)) as Page;
    
else if (action.Equals("new"))
      
return BuildManager.CreateInstanceFromVirtualPath("~/ArticleAdd.aspx", typeof(Page)) as Page;
    
else if (action.Equals("edit"))
      
return BuildManager.CreateInstanceFromVirtualPath("~/ArticleEdit.aspx", typeof(Page)) as Page;
    
else if (action.Equals("comment"))
      
return BuildManager.CreateInstanceFromVirtualPath("~/ArticleComment.aspx", typeof(Page)) as Page;
    
else if (action.Equals("print"))
      
return BuildManager.CreateInstanceFromVirtualPath("~/ArticlePrint.aspx", typeof(Page)) as Page;
    
else
      
return BuildManager.CreateInstanceFromVirtualPath("~/ArticleList.aspx", typeof(Page)) as Page;
  }
}

注意:

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

這3行程式碼是新加的。 

在這裡,我們將URL地址中的佔位符引數放到 HttpContext.Current 物件中,以便在真正的處理頁面中進行獲取,然後執行相應的操作。關鍵的程式碼是這幾句:

string ArticleGuid = requestContext.RouteData.Values["ArticleGuid"] as string;
HttpContext context = HttpContext.Current;
context.Items.Add("ArticleGuid", ArticleGuid);

4,在Global裡註冊路由,其程式碼為:

C# 程式碼
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --&gt@ Application Language="C#" %>
@ Import Namespace="System.Web.Routing" %>

<script. RunAt="server">

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

  
public static void RegisterRoutes(RouteCollection routes)
  {
    routes.Add(
"ArticleRoute", new Route
    (
      
"Article/{ArticleGuid}/{Action}.aspx",
            
new ArticleRouteHandler()
    )
    );
  }
    
script>

這裡,作為例子,只定義了一條URL規則,Article/{ArticleGuid}/{Action}.aspx。 

5,按照自定義路由處理程式中定義的實際處理程式,分別新增ArticleShow.aspx、ArticleAdd.aspx、ArticleEdit.aspx、ArticleComment.aspx、ArticlePrint.aspx和ArticleList.aspx等真正的處理程式。作為例子,這裡列出ArticleShow.aspx、ArticleAdd.aspx和ArticleList.aspx的原始碼分別如下:

ArticleAdd.aspx

ASPX 程式碼
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --&gt@ Page Language="C#" ValidateRequest="false" %>

@ Import Namespace="System.Data" %>
@ Import Namespace="System.Data.SqlClient" %>
DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script. runat="server">

  protected
void Button1_Click(object sender, EventArgs e)
  {
    String ConnectionString
= "Data Source=(local);Initial Catalog=ArticleDev;User ID=sa;Password=sa";
    SqlConnection cn
= new SqlConnection(ConnectionString);
    cn.Open();
    String sql
= "Insert Into Article(Title,Content) Values(@Title,@Content)";
    SqlCommand cmd
= new SqlCommand(sql, cn);
    cmd.Parameters.AddWithValue(
"@Title", TextBox1.Text);
    cmd.Parameters.AddWithValue(
"@Content", TextBox2.Text);
    
int ret = cmd.ExecuteNonQuery();
    
if (ret == 1)
    {
      Label1.Text
= "新增成功。";
    }
    
else
    {
      Label1.Text
= "新增失敗。";
    }
    cn.Dispose();

  }
script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  
<title>title>
head>
<body>
  
<form. id="form1" runat="server">
  
<div>文章標題:<asp:TextBox ID="TextBox1" runat="server" Width="767px">asp:TextBox>div>
  
<div>文章內容:<br />
    
<asp:TextBox ID="TextBox2" runat="server" Width="845px" Height="319px" TextMode="MultiLine">
    
asp:TextBox>div>
  
<asp:Button ID="Button1" runat="server" Text="新增文章" OnClick="Button1_Click" />
  
<asp:Label ID="Label1" runat="server" Text="">asp:Label>
  
form>
body>
html>

ArticleShow.aspx

ASPX 程式碼
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --&gt@ Page Language="C#" %>
@ Import Namespace="System.Data" %>
@ Import Namespace="System.Data.SqlClient" %>

DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script. runat="server">

  protected
void Page_Load(object sender, EventArgs e)
  {
    
int ArticleGuid = 0;
    HttpContext context
= HttpContext.Current;
    
if (context.Items["ArticleGuid"] != null)
    {
      Int32.TryParse(context.Items[
"ArticleGuid"].ToString(), out ArticleGuid);
    }
    
if (ArticleGuid < 1)
    {
      ArticleTitle.InnerHtml
= "載入文章錯誤";
      ArticleContent.InnerHtml
= "指定的 標識 無效!";
      ArticleContent.Style[
"color"] = "#f00";
    }
    
else
    {
      String ConnectionString
= "Data Source=(local);Initial Catalog=ArticleDev;User ID=sa;Password=sa";
      SqlConnection cn
= new SqlConnection(ConnectionString);
      cn.Open();
      String sql
= "Select * From Article Where ArticleId = @ArticleId";
      SqlCommand cmd
= new SqlCommand(sql, cn);
      cmd.Parameters.AddWithValue(
"@ArticleId", ArticleGuid);
      SqlDataReader dr
= cmd.ExecuteReader();
      
if (dr.Read())
      {
        ArticleTitle.InnerHtml
= dr["Title"].ToString();
        ArticleContent.InnerHtml
= dr["Content"].ToString();
      }
      
else
      {
        ArticleTitle.InnerHtml
= "載入文章錯誤";
        ArticleContent.InnerHtml
= "指定的文章不存在!";
        ArticleContent.Style[
"color"] = "#f00";
      }
      cn.Dispose();
    }    
  }
script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  
<title>title>
head>
<body>
  
<form. id="form1" runat="server">
  
<h2 id="ArticleTitle" runat="server" style="text-align:center">
  
h2>
  
<hr />
  
<div id="ArticleContent" runat="server">
  
div>
  
form>
body>
html>

這段程式碼中,我們從自定義路由處理程式中新增的 HttpContext 物件中取出引數 context.Items["ArticleGuid"],然後進行處理。

ArticleList.aspx

ASPX 程式碼
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --&gt@ Page Language="C#" %>
@ Import Namespace="System.Data" %>
@ Import Namespace="System.Data.SqlClient" %>

DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script. runat="server">

  protected
void Page_Load(object sender, EventArgs e)
  {
    String ConnectionString
= "Data Source=(local);Initial Catalog=ArticleDev;User ID=sa;Password=sa";
    SqlConnection cn
= new SqlConnection(ConnectionString);
    cn.Open();
    String sql
= "Select * From Article Order By ArticleId DESC";
    SqlCommand cmd
= new SqlCommand(sql, cn);
    SqlDataReader dr
= cmd.ExecuteReader();
    GridView1.DataSource
= dr;
    GridView1.DataBind();
    cn.Dispose();
  }
script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    
<title>title>
head>
<body>
    
<form. id="form1" runat="server">
    
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false">
    
<Columns>
    
<asp:HyperLinkField DataNavigateUrlFields="ArticleId" DataTextField="Title"
      DataNavigateUrlFormatString
="~/Article/{0}/read.aspx" HeaderText="標題" />
    
<asp:BoundField DataField="CreateDate" HtmlEncode="false" HeaderText="釋出日期"
     DataFormatString
="{0:yyyy-MM-dd HH:mm:ss}" />
    
Columns>    
    
asp:GridView>
    
form>
body>
html>

6,如果IIS裡設定的ASP.NET版本是 ASP.NET 4.0,無需配置以下的配置,如果是ASP.NET 2.0,則需要在web.config裡配置路由。在應用程式的 Web.config 檔案中,將 ASP.NET 路由程式集新增到 assemblies 元素

XML/XHTML 程式碼
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --&gt<assemblies>
  
<add assembly="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
assemblies>

如果應用程式在 IIS 6.0 或 IIS 7.0 經典模型下執行,則將 UrlRoutingModule 類新增到 httpModules 元素

XML/XHTML 程式碼
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --&gt<httpModules>
  
<add name="UrlRoutingModule"
   type
="System.Web.Routing.UrlRoutingModule,
         System.Web.Routing,
         Version=3.5.0.0,
         Culture=neutral,
         PublicKeyToken=31BF3856AD364E35"
/>
httpModules>

 下面就可以使用下面的地址進行訪問了。當然,這裡只是一個例子,更多的功能處理有待於我們在實踐中加以處理。
http://dotnet.aspx.cc/article/8d01fd5e-b2c1-40f5-8cea-bc2197fb9bd8/comment.aspx
http://dotnet.aspx.cc/article/8d01fd5e-b2c1-40f5-8cea-bc2197fb9bd8/new.aspx
http://dotnet.aspx.cc/article/8d01fd5e-b2c1-40f5-8cea-bc2197fb9bd8/edit.aspx
http://dotnet.aspx.cc/article/8d01fd5e-b2c1-40f5-8cea-bc2197fb9bd8/read.aspx
http://dotnet.aspx.cc/article/8d01fd5e-b2c1-40f5-8cea-bc2197fb9bd8/print.aspx

以上例子只是簡單地進行了說明,實際應用中,還有更多的東西需要考慮,更多的資訊可以參考如下的連結:
ASP.NET 路由(http://msdn.microsoft.com/zh-cn/library/cc668201.aspx)

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15723462/viewspace-625302/,如需轉載,請註明出處,否則將追究法律責任。

相關文章