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 代码
CREATETABLE[Article](
[ArticleId][int]IDENTITY(1,1)NOTNULL,
[Title][nvarchar](255) COLLATE Chinese_PRC_CI_ASNOTNULL,
[CreateDate][datetime]NOTNULLCONSTRAINT[DF_Article_CreateDate]DEFAULT(getdate()),
[Content][ntext]COLLATE Chinese_PRC_CI_ASNOTNULL,
CONSTRAINT[PK_Article]PRIMARYKEY CLUSTERED
(
[ArticleId]
) ON[PRIMARY]
)ON[PRIMARY]TEXTIMAGE_ON[PRIMARY]
GO
2,在VS2008SP1或者VS2010中,新建一个ASP.NET网站,添加对System.Web.Routing的引用;
3,创建自定义路由处理程序,在网站工程中添加新项“类”,命名为ArticleRouteHandler.cs,类的网站内容如下:
C# 代码
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.UI;
usingSystem.Web.Routing;
usingSystem.Web.Compilation;
///<summary>
///ArticleRouteHandler 的摘要说明
///</summary>
publicclassArticleRouteHandler : IRouteHandler
{
publicArticleRouteHandler()
{
//
//TODO: 在此处添加构造函数逻辑
//
}
publicIHttpHandler GetHttpHandler(RequestContext requestContext)
{
stringArticleGuid=requestContext.RouteData.Values["ArticleGuid"]asstring;
HttpContext context=HttpContext.Current;
context.Items.Add("ArticleGuid", ArticleGuid);
stringaction=(requestContext.RouteData.Values["Action"]asstring).ToLower();
if(action.Equals("read"))
returnBuildManager.CreateInstanceFromVirtualPath("~/ArticleShow.aspx",typeof(Page))asPage;
elseif(action.Equals("new"))
returnBuildManager.CreateInstanceFromVirtualPath("~/ArticleAdd.aspx",typeof(Page))asPage;
elseif(action.Equals("edit"))
returnBuildManager.CreateInstanceFromVirtualPath("~/ArticleEdit.aspx",typeof(Page))asPage;
elseif(action.Equals("comment"))
returnBuildManager.CreateInstanceFromVirtualPath("~/ArticleComment.aspx",typeof(Page))asPage;
elseif(action.Equals("print"))
returnBuildManager.CreateInstanceFromVirtualPath("~/ArticlePrint.aspx",typeof(Page))asPage;
else
returnBuildManager.CreateInstanceFromVirtualPath("~/ArticleList.aspx",typeof(Page))asPage;
}
}
注意:
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# 代码
<%@ Application Language="C#"%>
<%@ Import Namespace="System.Web.Routing"%>
<script. RunAt="server">
voidApplication_Start(objectsender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
publicstaticvoidRegisterRoutes(RouteCollection routes)
{
routes.Add("ArticleRoute",newRoute
(
"Article/{ArticleGuid}/{Action}.aspx",
newArticleRouteHandler()
)
);
}
</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 代码
<%@ 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">
protectedvoidButton1_Click(object sender, EventArgs e)
{
String ConnectionString="Data Source=(local);Initial Catalog=ArticleDev;User ID=sa;Password=sa";
SqlConnection cn=newSqlConnection(ConnectionString);
cn.Open();
String sql="Insert Into Article(Title,Content) Values(@Title,@Content)";
SqlCommand cmd=newSqlCommand(sql, cn);
cmd.Parameters.AddWithValue("@Title", TextBox1.Text);
cmd.Parameters.AddWithValue("@Content", TextBox2.Text);
intret=cmd.ExecuteNonQuery();
if(ret==1)
{
Label1.Text="添加成功。";
}
else
{
Label1.Text="添加失败。";
}
cn.Dispose();
}
</script>
<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
<title></title>
</head>
<body>
<form.id="form1"runat="server">
<div>文章标题:<asp:TextBoxID="TextBox1"runat="server"Width="767px"></asp:TextBox></div>
<div>文章内容:<br/>
<asp:TextBoxID="TextBox2"runat="server"Width="845px"Height="319px"TextMode="MultiLine">
</asp:TextBox></div>
<asp:ButtonID="Button1"runat="server"Text="添加文章"OnClick="Button1_Click"/>
<asp:LabelID="Label1"runat="server"Text=""></asp:Label>
</form>
</body>
</html>
ArticleShow.aspx
ASPX 代码
<%@ 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">
protectedvoidPage_Load(object sender, EventArgs e)
{
intArticleGuid=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=newSqlConnection(ConnectionString);
cn.Open();
String sql="Select * From Article Where ArticleId = @ArticleId";
SqlCommand cmd=newSqlCommand(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>
<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
<title></title>
</head>
<body>
<form.id="form1"runat="server">
<h2id="ArticleTitle"runat="server"style="text-align:center">
</h2>
<hr/>
<divid="ArticleContent"runat="server">
</div>
</form>
</body>
</html>
这段代码中,我们从自定义路由处理程序中添加的 HttpContext 对象中取出参数 context.Items["ArticleGuid"],然后进行处理。
ArticleList.aspx
ASPX 代码
<%@ 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">
protectedvoidPage_Load(object sender, EventArgs e)
{
String ConnectionString="Data Source=(local);Initial Catalog=ArticleDev;User ID=sa;Password=sa";
SqlConnection cn=newSqlConnection(ConnectionString);
cn.Open();
String sql="Select * From Article Order By ArticleId DESC";
SqlCommand cmd=newSqlCommand(sql, cn);
SqlDataReader dr=cmd.ExecuteReader();
GridView1.DataSource=dr;
GridView1.DataBind();
cn.Dispose();
}
</script>
<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
<title></title>
</head>
<body>
<form.id="form1"runat="server">
<asp:GridViewID="GridView1"runat="server"AutoGenerateColumns="false">
<Columns>
<asp:HyperLinkFieldDataNavigateUrlFields="ArticleId"DataTextField="Title"
DataNavigateUrlFormatString="~/Article/{0}/read.aspx"HeaderText="标题"/>
<asp:BoundFieldDataField="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 代码
<assemblies>
<addassembly="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</assemblies>
如果应用程序在 IIS 6.0 或 IIS 7.0 经典模型下运行,则将 UrlRoutingModule 类添加到 httpModules 元素
XML/XHTML 代码
<httpModules>
<addname="UrlRoutingModule"
type="System.Web.Routing.UrlRoutingModule,
System.Web.Routing,
Version=3.5.0.0,
Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
</httpModules>
下面就可以使用下面的地址进行访问了。当然,这里只是一个例子,更多的功能处理有待于我们在实践中加以处理。
查看所有0条评论>>