url映射是asp.net 2.0的一个新的特性,它可以让开发人员把一个页映射到另一个url上。如果一个url请求过来,程序会自动把它重新映射到服务端。例如,如果你在程序中配置了把~/Beverages.aspx映射到了~/ProductsByCategory.aspx?CategoryID=1&CategoryName=Beverages,那么当用户在浏览器中输入了http://YourSite.com/Beverages.aspx,服务器会接收后会自动的转到http://YourSite.com/ProductsByCategory.aspx?CategoryID=1&CategoryName=Beverages去处理。而这个用户在浏览器的地址栏中看到的仍然是http://YourSite.com/Beverages.aspx。他们不会知道这个请求被重新映射了。
url映射经常是为了提供友好的url而被使用,这种友好的url更易读,更容易理解。例如Beverages.aspx要比ProductsByCategory.aspx?CategoryID=1&CategoryName=Beverages更容易懂。当你修改站点结构的时候,url映射也是非常有用的。想象一下,所有的产品信息都需要用http://YourSite.com/Products/...来访问,如果你想修改这个结构,通过http://YourSite.com/Catalog/...来代替它的话,如果一位你的老用户通过收藏夹来访问的话,就会得到一个404的错误,而如果使用url映射,则两个url写法都能够访问到产品信息。
本文我们将研究如何设置asp.net 2.0 web应用程序提供的url映射功能,也来看一看url映射是如何工作的。我们也将论述一下asp.net 1.x中的url映射实现的技术,以及扩展asp.net 2.0中的url映射。接下来你将看到更多。
定义url映射
在asp.net 2.0中使用url映射是非常简单的,我们可以直接在web.config中设置。通过一些简单的配置,我们就可以在一些场景中建立url映射的功能,但是它不适用一些复杂的场景,如需要动态定义映射或者需要更强适应性的时候。本文稍后会提供一个简单的例子。
为了指定一个映射,我们可以在web.config里增加一个<urlMappings>元素,并设置它的enabled属性为true,然后再每一个<add>元素中做映射。在<add>元素中,分别指明url(引入的url)和mappedUrl(要映射到的url)属性。
在本文结尾处将提供示例下载,它是一个asp.net 2.0的web应用程序,使用了Northwind数据库来显示产品信息。ProductsByCategory.aspx页需要两个参数,分别是CategoryID和CategoryName。然后这个页用一个Label控件来显示CategoryName,用一个GridView控件,和一个SqlDataSource控件来显示CategoryID所指向的产品的列表。所以,用户使用地址~/ProductsByCategory.aspx?CategoryID=1&CategoryName=Beverages来访问这个页面。
我们可以使用asp.net 2.0的url映射功能,来给用户提供一个友好的url,像~/Beverages.aspx这样的。我们在<urlMappings>元素中写8个映射,来为Northwind数据库中的每一个产品类建立一个友好的url。写完这些映射后,如果用想看饮料类的产品就可以通过地址~/ProductsByCategory.aspx?CategoryID=1&CategoryName=Beverages或~/Beverages.aspx来访问了。
<configuration>
<system.web>
<urlMappings enabled="true">
<add
url="~/Beverages.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=1&CategoryName=Beverages" />
<add
url="~/Condiments.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=2&CategoryName=Condiments" />
<add
url="~/Confections.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=3&CategoryName=Confections" />
<add
url="~/Dairy.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=4&CategoryName=Dairy+Products" />
<add
url="~/Grains.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=5&CategoryName=Grains+and+Cereals" />
<add
url="~/Meat.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=6&CategoryName=Meat+and+Poultry" />
<add
url="~/Produce.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=7&CategoryName=Produce" />
<add
url="~/Seafood.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=8&CategoryName=Seafood" />
</urlMappings>
</system.web>
</configuration>
<system.web>
<urlMappings enabled="true">
<add
url="~/Beverages.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=1&CategoryName=Beverages" />
<add
url="~/Condiments.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=2&CategoryName=Condiments" />
<add
url="~/Confections.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=3&CategoryName=Confections" />
<add
url="~/Dairy.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=4&CategoryName=Dairy+Products" />
<add
url="~/Grains.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=5&CategoryName=Grains+and+Cereals" />
<add
url="~/Meat.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=6&CategoryName=Meat+and+Poultry" />
<add
url="~/Produce.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=7&CategoryName=Produce" />
<add
url="~/Seafood.aspx"
mappedUrl="~/ProductsByCategory.aspx?CategoryID=8&CategoryName=Seafood" />
</urlMappings>
</system.web>
</configuration>
注意:因为web.config是xml格式的,所以所有xml的特征都将被保留。例如,如果你想输入符号&,就要写成&。
当这个页是通过友好url(Beverages.aspx)被访问的时候,则将用到映射文件中的参数。通过下面的截图我们可以注意到,用户在浏览器的地址栏输入了Beverages.aspx,但这个请求发到服务端后,会自动映射到~/ProductsByCategory.aspx?CategoryID=1&CategoryName=Beverages,而用户在地址栏中看到的却仍然是Beverages.aspx。但是透过服务端代码,参数CategoryID和CategoryName将用来在呈现类别名和类别下产品列表时被使用。
asp.net 2.0是如何映射url的
当一个请求到达了web服务器,asp.net runtime会决定请求哪个url,然后调用页的相应的类呈现出结果。每个页都有它自己的生命周期,包括控件的初始化和处理,通过一些阶段,如PreInit,Init,Load等之后将处理结果在标记中呈现,再把这些标记传给浏览器中显示。
在这些步骤发生之前,首先会检查请求的url,并且查看所请求的url是否在url映射文件按中出现。如果有,则使用HttpContext类的RewritePath方法,该方法将通过web.config中指定的规则更细当前请求的url。这些信息更新后,系统将把用户最初输入的url用映射后的url代替。但是用户在浏览器的地址栏看到的仍然是最初输入的url。
其工作流图示如下:
asp.net 2.0中的url映射的缺点。
asp.net 2.0中的url映射主要有两个缺点。首先,所有url映射必须静态的在web.config中定义。这使得一些数据驱动的web站点如果要使用url映射就要手工往配置文件里输入所有相关信息,只是不现实的。本文结束后有个例子,你会发现如果你从数据库中删除了某一类别或新增了某一类别,你就必须手动修改web.config文件,在<urlMappings>节点处删除或增加一个<add>元素。
另一个缺点是无法使用正则表达式。在有大量的url需要映射的时候,有一种情况是通过定义一种映射模式来实现所有url的映射,这种特别的需求在一些站点的重构中是非常有用的。如果在重写规则中可以用正则表达式,那么一句非常简单的映射就可以完成所有老文件夹映射到新文件夹上的功能。(假设一个web站点要把“Old”文件夹重新命名为“New”)
<add url="~/Old/(.*)" mappedUrl="~/New/$1" />
在asp.net 2.0不能在url映射的实现过程中提供正则表达式功能的这段期间,Chris Pietschmann提供了一段HTTP Module代码来做这件事,在他的Blog中有详细说明“asp.net 2.0:给url映射提供正则表达式功能”这段HTTP Module也可以动态的写映射规则。
另一方面,还有一个小缺点,就是当用户通过url映射访问页面后,如果<form>提交了,将会转到真实页。就是说,如果用户通过友好url Beverages.aspx 来访问ProductsByCategory.aspx?CategoryID=1&CategoryName=Beverages页面的话,如果页面回发数据了,那么浏览器将会去请求ProductsByCategory.aspx?CategoryID=1&CategoryName=Beverages而不是Beverages.aspx。功能还能正常的实现,但是地址栏上的地址变化了,这会把通过记下url地址访问页面的用户弄糊涂。
asp.net 1.x中的url映射
asp.net 1.x中没有提供类似asp.net 2.0中的<urlMappings>元素,但是通过自定义的HTTP Handler或Module也可以实现映射的功能。详细的实现过程请看我的另一篇文章“asp.net中的url重写”。这篇文章是为了asp.net 1.x写的,但其中的想法也适用于asp.net 2.0。Chris Pietschmann为asp.net 2.0写的给url映射提供正则表达式功能的HTTP Module也使用了相同的想法。
“asp.net中的url重写”这篇文章使用了form提交后重新映射为友好url的技术。
结论
本文中,我们一起看了一下asp.net 2.0中url映射的特性,它提供了一个非常简单的方法来实现url映射。这个技术通常为了创建友好url和处理站点重构时使用。不幸的是,我们需要手动创建url映射项,如果需要动态创建url映射的话,我们可以通过自定义HTTP Module来实现。