快速入门系列--MVC--02路由
现在补上URL路由的学习,至于蒋老师自建的MVC小引擎和相关案例就放在论文提交后再实践咯。通过ASP.NET的路由系统,可以完成请求URL与物理文件的分离,其优点是:灵活性、可读性、SEO优化。接下来通过一个最简单的路由例子进入这部分的学习,这是一个蒋老师提供的WebForm路由的例子,回想起刚做ASP.NET时,每次看到.aspx页面的前台代码时的茫然和无措,茫茫多的标签,属性,数据源的绑定吓死小兄弟俺了,也花过不少时间去理解记忆,效果不也不大。现在回头看看感觉好了很多,看到IsPostback老亲切了,觉得在理解的基础上拖拉控件也是很幸福的事情,嘿嘿。
1 void Application_Start(object sender, EventArgs e) 2 { 3 //路由配置 4 var defaults = new RouteValueDictionary { { "name", "*" }, { "id", "*" } }; 5 RouteTable.Routes.MapPageRoute("default", "employees/{name}/{id}", "~/Default.aspx", true, defaults); 6 } 7 8 //前台代码 9 <form id="form1" runat="server"> 10 <div> 11 <asp:GridView ID="GridViewEmployees" runat="server" AutoGenerateColumns="False" Width="100%"> 12 <Columns> 13 <asp:HyperLinkField DataNavigateUrlFields="Name,Id" DataNavigateUrlFormatString="~/employees/{0}/{1}" DataTextField="Name" HeaderText="姓名" /> 14 <asp:BoundField DataField="Gender" HeaderText="性别" /> 15 <asp:BoundField DataField="Birthday" DataFormatString="{0:dd/MM/yyyy}" HeaderText="出生日期" /> 16 <asp:BoundField DataField="Department" HeaderText="部门" /> 17 </Columns> 18 </asp:GridView> 19 <asp:DetailsView ID="DetailsViewEmployee" runat="server" Height="50px" Width="100%" AutoGenerateRows="False"> 20 <Fields> 21 <asp:BoundField DataField="Id" HeaderText="ID" /> 22 <asp:BoundField DataField="Name" HeaderText="姓名" /> 23 <asp:BoundField DataField="Gender" HeaderText="性别" /> 24 <asp:BoundField DataField="Birthday" DataFormatString="{0:dd/MM/yyyy}" HeaderText="出生日期" /> 25 <asp:BoundField DataField="Department" HeaderText="部门" /> 26 </Fields> 27 </asp:DetailsView> 28 </div> 29 </form> 30 31 //后台代码 32 public partial class Default : System.Web.UI.Page 33 { 34 private EmployeeRepository _repository; 35 public EmployeeRepository Repository 36 { 37 get 38 { 39 return null == _repository ? _repository = new EmployeeRepository() : _repository; 40 } 41 } 42 43 protected void Page_Load(object sender, EventArgs e) 44 { 45 if (this.IsPostBack) 46 { 47 return; 48 } 49 string employeeId = this.RouteData.Values["id"] as string; 50 if (employeeId == "*" || string.IsNullOrEmpty(employeeId)) 51 { 52 this.GridViewEmployees.DataSource = this.Repository.GetEmployees(); 53 this.GridViewEmployees.DataBind(); 54 this.DetailsViewEmployee.Visible = false; 55 } 56 else 57 { 58 this.DetailsViewEmployee.DataSource = this.Repository.GetEmployees(employeeId); 59 this.DetailsViewEmployee.DataBind(); 60 this.GridViewEmployees.Visible = false; 61 } 62 } 63 }
接下来通过一个表格简要介绍下路由系统的相关类型:
类型 | 简介 |
RouteBase | 提供GetRouteData方法获得RouteData,该对象中属性RouteHandler用于提供HttpHandler对象,Values提供解析Url后的数据,DataTokens提供自己在路由类型中添加的数据;GetVirtualPath方法根据提供的变量和URL模板生成虚拟路径,是GetRouteData方法的逆过程,用于响应阶段。 |
Route | Url属性表示Url模板,如world/{country}/{city}匹配world/China/Shanghai,通配符为{*pathInfo}。Defaults属性提供模板变量默认值,Constraints提供约束条件 |
RouteTable | 静态属性Routes维护全局路由表,属性RouteExistingFiles用于控制是否需要对存在的物理文件实施路由,默认为False;属性AppendTrailingSlash和LowercaseUrls用于GetVirtualPath方法是否转变url为小写或在末尾添加"/" |
之后展示一个关于注册路由相对完整的例子,代码如下所示:
1 var defaults = new RouteValueDictionary { { "cityCode", "021" }, { "distinctCode", 1 } }; 2 var constraints = new RouteValueDictionary { { "cityCode", @"0\d{2,3}" }, { "distinctCode", @"[1-7]{1}" } }; 3 var dataTokens = new RouteValueDictionary { { "defaultCity", "Shanghai" }, { "defaultDistinct", "Pudong" } }; 4 RouteTable.Routes.MapPageRoute("default", "{cityCode}/{distinctCode}", "~/default.aspx", false, defaults, constraints, dataTokens);
再则是介绍一些路由模块在ASP.NET MVC中的扩展,包括是UrlParameter.Optional代表缺省的URL参数,通过Area来划分系统的模块,以及HtmlHelper与UrlHelper相关的内容,相对比较简单就不一一介绍了,只是补充一个Area注册的例子加强记忆,代码如下:
1 public class WeatherAreaRegistration : AreaRegistration 2 { 3 public override string AreaName 4 { 5 get { return "Weather"; } 6 } 7 public override void RegisterArea(AreaRegistrationContext context) 8 { 9 object defaults = new 10 { 11 areacode = "010", 12 days = 2, 13 defaultCity = "BeiJing", 14 defaultDays = 2 15 }; 16 object constraints = new { areacode = @"0\d{2,3}", days = @"[1-3]{1}" }; 17 context.MapRoute("weatherDefault", "weather/{areacode}/{days}", defaults, constraints); 18 } 19 }
最后来说说整个路由系统是如何实现的,正如蒋老师所说,是通过HttpHandler的动态映射来实现的。UrlRoutingModule实现了IHttpModule,通过注册HttpApplication的PostResolveRequestCache事件对请求进行拦截,并利用路由表与请求URL进行模式匹配得到相应的路由数据,并获得关联的HttpHandler用于处理请求。注意PageRouteHandler和MvcRouteHanlder分别针对WebForm和MVC,部分相关代码如下所示:
1 public class UrlRoutingModule:IHttpModule 2 { 3 public RouteCollection RouteCollection { get; set; } 4 public void Init(HttpApplication context) 5 { 6 context.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache); 7 } 8 9 private void OnApplicationPostResolveRequestCache(object sender, EventArgs e) { 10 HttpContext context = ((HttpApplication)sender).Context; 11 HttpContextBase contextWrapper = new HttpContextWrapper(context); 12 RouteData routeData = this.RouteCollection.GetRouteData(contextWrapper); 13 RequestContext requestContext = new RequestContext(contextWrapper, routeData); 14 IHttpHandler handler = routeData.RouteHandler.GetHttpHandler(requestContext); 15 context.RemapHandler(handler); 16 } 17 //omit 18 }
Tip: ASP.NET的处理过程始终是Request->HttpModule->HttpHandler->Response,
对了,现在关于Owin的相关内容很火,感觉其就是J2EE标准规范的.NET版本,提供规范与接口,大家一起来做好它的感觉。简单来说就是现在只有IIS支持ASP.NET管道,而JAVA却有Tomcat,Weblogic等很多优质的Web服务器支持Servlet,今后我们也可以在很多开源高效的Web服务器上搭建.NET应用了,因为它们一定会简化现有的ASP.NET管道,让XXXing,XXXed离我们远一点吧。真心的说,以前面试的时候感觉好难背,哈哈。
如果需要在mvc代码中进行分离,下图标红处的设置最为关键。
系列目录如下,谢谢您的阅读。
注:本文主要供自己学习,不妥之处望见谅。
参考资料:
[1]蒋金楠. ASP.NET MVC4框架揭秘[M]. 上海:电子工业出版社, 2012. 35-85
出 处:http://www.cnblogs.com/xiong2ge/
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。