由于工作的原因,断断续续终于看完了《ASP.NET Web API 2 框架揭秘》第二章关于WebApi的路由系统的知识。
路由系统是请求消息进入Asp.net WebApi的第一道屏障,其根本目的利用注册的路由表对请求的URI进行解析以确定目标HttpController和Action的名称,以及与某个Action方法某个参数进行绑定的路由变量。
Asp.net webApi中的路由系统和Asp.net中的路由系统很相似,也有Route,只是WebApi的路由系统又独立于Asp.net的路由系统,实现类也在不同的命名空间下。所以在讲Asp.net WebApi路由之前先来谈谈Asp.net路由系统。
一、Asp.net 路由
Asp.net MVC的路由完全由 Asp.net路由系统来完成 ,但是后者并非专门为前者设计 ,其实它最初是为了帮助 WebForm应用实现 “请求地址与物理文件的分离” 而设计的。
1.1 请求Url与物理文件的分离:类似于www.xxx.com/default.aspx这类没有把url与物理地址分开的做法的局限性体现在一下几个方面,1.灵活性(物理文件路径发生变化,链接无效);2.可读性;3.SEO优化。
解决上面问题,URL路由系统,通过托管代码实现URL与物理文件的分离。
下面示例展示了通过URL路由实现请求地址与web页面的映射。示例地址:员工列表与员工信息示例
1 namespace WebApp 2 { 3 public class Global : System.Web.HttpApplication 4 { 5 protected void Application_Start(object sender, EventArgs e) 6 { 7 var defaults = new RouteValueDictionary { { "name", "*" }, { "id", "*" } }; 8 RouteTable.Routes.MapPageRoute("", "employees/{name}/{id}","~/default.aspx", true, defaults); 9 } 10 } 11 } 12
在示例中有我们将实现映射的路由注册代码定义在 Global.asax文件中,调用system.Web.Routing.RouteCollection对象的MapPageRoute方法将Default.aspx页面 (~/Default.aspx)与一个路由模板(employees/{name}/{id})进行了映射.
MapPageRoute的最后一个参数RouteValueDictionary用于指定在路由模版中路由变量(“name”和“id”)的默认值。对于针对URL为 “/employees” 的请求,我们注册的 Route会将其格式化成 “/employees/*/*".
1.2 ASP.Net 路由系统(重要类分析):
1.RouteBase
命名空间: System.Web.Routing
属性:RouteExistingFiles
方法:GetRouteData、GetVirtualPath、RouteBase
1 // 摘要: 2 // 用作表示 ASP.NET 路由的所有类的基类。 3 [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")] 4 public abstract class RouteBase 5 { 6 // 摘要: 7 // 初始化该类供继承的类实例使用。 此构造函数只能由继承的类调用。 8 protected RouteBase(); 9 10 // 摘要: 11 // 获取或设置一个值,该值指示 ASP.NET 路由操作是否应处理与现有文件匹配的 URL。 12 // 13 // 返回结果: 14 // 如果 ASP.NET 路由操作处理所有请求(甚至包括与现有文件匹配的请求),则为 true;否则为 false。 默认值为 false。 15 public bool RouteExistingFiles { get; set; } 16 17 // 摘要: 18 // 当在派生类中重写时,会返回有关请求的路由信息。 19 // 20 // 参数: 21 // httpContext: 22 // 一个对象,封装有关 HTTP 请求的信息。 23 // 24 // 返回结果: 25 // 一个对象,包含路由定义的值(如果该路由与当前请求匹配)或 null(如果该路由与请求不匹配)。 26 public abstract RouteData GetRouteData(HttpContextBase httpContext); 27 // 28 // 摘要: 29 // 当在派生类中重写时,会检查路由是否与指定值匹配,如果匹配,则生成一个 URL,然后检索有关该路由的信息。 30 // 31 // 参数: 32 // requestContext: 33 // 一个对象,封装有关所请求的路由的信息。 34 // 35 // values: 36 // 一个包含路由参数的对象。 37 // 38 // 返回结果: 39 // 一个对象(包含生成的 URL 和有关路由的信息)或 null(如果路由与 values 不匹配)。 40 public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values); 41 }
2.RouteData
命名空间: System.Web.Routing
属性:Route、DataTokens(说明:直接附加到Route上的自定义变量)、RouteHandler 、Values(说明:Route通过对请求的Url的解析得到的)
方法:两个构造函数RouteData、GetRequiredString
1 // 摘要: 2 // 封装有关路由的信息。 3 [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")] 4 public class RouteData 5 { 6 // 摘要: 7 // 初始化 System.Web.Routing.RouteData 类的新实例。 8 public RouteData(); 9 // 10 // 摘要: 11 // 使用指定路由和路由处理程序初始化 System.Web.Routing.RouteData 类的新实例。 12 // 13 // 参数: 14 // route: 15 // 一个定义路由的对象。 16 // 17 // routeHandler: 18 // 一个处理请求的对象。 19 public RouteData(RouteBase route, IRouteHandler routeHandler); 20 21 // 摘要: 22 // 获取在 ASP.NET 路由确定路由是否匹配请求时,传递到路由处理程序但未使用的自定义值的集合。 23 // 24 // 返回结果: 25 // 一个包含自定义值的对象。 26 public RouteValueDictionary DataTokens { get; } 27 // 28 // 摘要: 29 // 获取或设置表示路由的对象。 30 // 31 // 返回结果: 32 // 一个表示路由定义的对象。 33 public RouteBase Route { get; set; } 34 // 35 // 摘要: 36 // 获取或设置处理所请求路由的对象。 37 // 38 // 返回结果: 39 // 一个处理路由请求的对象。 40 public IRouteHandler RouteHandler { get; set; } 41 // 42 // 摘要: 43 // 获取路由的 URL 参数值和默认值的集合。 44 // 45 // 返回结果: 46 // 一个对象,其中包含根据 URL 和默认值分析得出的值。 47 public RouteValueDictionary Values { get; } 48 49 // 摘要: 50 // 使用指定标识符检索值。 51 // 52 // 参数: 53 // valueName: 54 // 要检索的值的键。 55 // 56 // 返回结果: 57 // 其键与 valueName 匹配的 System.Web.Routing.RouteData.Values 属性中的元素。 58 // 59 // 异常: 60 // System.InvalidOperationException: 61 // valueName 的值不存在。 62 public string GetRequiredString(string valueName); 63 }
3.VirtualPathData
命名空间: System.Web.Routing
属性:VirtualPath、Route、DataTokens
方法:构造函数VirtualPathData
1 // 摘要: 2 // 表示有关路由和虚拟路径的信息,该路由和虚拟路径是在使用 ASP.NET 路由框架生成 URL 时产生的。 3 [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")] 4 public class VirtualPathData 5 { 6 // 摘要: 7 // 初始化 System.Web.Routing.VirtualPathData 类的新实例。 8 // 9 // 参数: 10 // route: 11 // 用于生成 URL 的对象。 12 // 13 // virtualPath: 14 // 生成的 URL。 15 public VirtualPathData(RouteBase route, string virtualPath); 16 17 // 摘要: 18 // 获取路由定义的自定义值集合。 19 // 20 // 返回结果: 21 // 路由的自定义值集合。 22 public RouteValueDictionary DataTokens { get; } 23 // 24 // 摘要: 25 // 获取或设置用于创建 URL 的路由。 26 // 27 // 返回结果: 28 // 一个对象,该对象表示与用于生成 URL 的参数匹配的路由。 29 public RouteBase Route { get; set; } 30 // 31 // 摘要: 32 // 获取或设置依据路由定义创建的 URL。 33 // 34 // 返回结果: 35 // 依据路由生成的 URL。 36 public string VirtualPath { get; set; } 37 }
4.Route
命名空间: System.Web.Routing
属性:Url、RouteHandler 、Defaults 、DataTokens 、Constraints
方法:4个构造函数、ProcessConstraint、GetVirtualPath、GetRouteData
1 // 摘要: 2 // 提供用于定义路由及获取路由相关信息的属性和方法。 3 [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")] 4 public class Route : RouteBase 5 { 6 // 摘要: 7 // 使用指定的 URL 模式和处理程序类初始化 System.Web.Routing.Route 类的新实例。 8 // 9 // 参数: 10 // url: 11 // 路由的 URL 模式。 12 // 13 // routeHandler: 14 // 处理路由请求的对象。 15 public Route(string url, IRouteHandler routeHandler); 16 // 17 // 摘要: 18 // 使用指定的 URL 模式、默认参数值和处理程序类初始化 System.Web.Routing.Route 类的新实例。 19 // 20 // 参数: 21 // url: 22 // 路由的 URL 模式。 23 // 24 // defaults: 25 // 用于 URL 中缺失的任何参数的值。 26 // 27 // routeHandler: 28 // 处理路由请求的对象。 29 public Route(string url, RouteValueDictionary defaults, IRouteHandler routeHandler); 30 // 31 // 摘要: 32 // 使用指定的 URL 模式、默认参数值、约束和处理程序类初始化 System.Web.Routing.Route 类的新实例。 33 // 34 // 参数: 35 // url: 36 // 路由的 URL 模式。 37 // 38 // defaults: 39 // 要在 URL 不包含所有参数时使用的值。 40 // 41 // constraints: 42 // 一个用于指定 URL 参数的有效值的正则表达式。 43 // 44 // routeHandler: 45 // 处理路由请求的对象。 46 public Route(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler); 47 // 48 // 摘要: 49 // 使用指定的 URL 模式、默认参数值、约束、自定义值和处理程序类初始化 System.Web.Routing.Route 类的新实例。 50 // 51 // 参数: 52 // url: 53 // 路由的 URL 模式。 54 // 55 // defaults: 56 // 要在 URL 不包含所有参数时使用的值。 57 // 58 // constraints: 59 // 一个用于指定 URL 参数的有效值的正则表达式。 60 // 61 // dataTokens: 62 // 传递到路由处理程序但未用于确定该路由是否匹配特定 URL 模式的自定义值。 这些值会传递到路由处理程序,以便用于处理请求。 63 // 64 // routeHandler: 65 // 处理路由请求的对象。 66 public Route(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler); 67 68 // 摘要: 69 // 获取或设置为 URL 参数指定有效值的表达式的词典。 70 // 71 // 返回结果: 72 // 一个包含参数名称和表达式的对象。 73 public RouteValueDictionary Constraints { get; set; } 74 // 75 // 摘要: 76 // 获取或设置传递到路由处理程序但未用于确定该路由是否匹配 URL 模式的自定义值。 77 // 78 // 返回结果: 79 // 一个包含自定义值的对象。 80 public RouteValueDictionary DataTokens { get; set; } 81 // 82 // 摘要: 83 // 获取或设置要在 URL 不包含所有参数时使用的值。 84 // 85 // 返回结果: 86 // 一个包含参数名称和默认值的对象。 87 public RouteValueDictionary Defaults { get; set; } 88 // 89 // 摘要: 90 // 获取或设置处理路由请求的对象。 91 // 92 // 返回结果: 93 // 处理请求的对象。 94 public IRouteHandler RouteHandler { get; set; } 95 // 96 // 摘要: 97 // 获取或设置路由的 URL 模式。 98 // 99 // 返回结果: 100 // 用于匹配路由和 URL 的模式。 101 // 102 // 异常: 103 // System.ArgumentException: 104 // 以下任一值: 以 ~ 或 / 开头的值。 包含 ? 字符的值。 “全部捕捉”参数不在末尾。 105 // 106 // System.Exception: 107 // 没有使用分隔符或文字常量分隔 URL 分段。 108 public string Url { get; set; } 109 110 // 摘要: 111 // 返回有关所请求路由的信息。 112 // 113 // 参数: 114 // httpContext: 115 // 一个对象,封装有关 HTTP 请求的信息。 116 // 117 // 返回结果: 118 // 一个对象,其中包含路由定义中的值。 119 public override RouteData GetRouteData(HttpContextBase httpContext); 120 // 121 // 摘要: 122 // 返回与路由关联的 URL 的相关信息。 123 // 124 // 参数: 125 // requestContext: 126 // 一个对象,封装有关所请求的路由的信息。 127 // 128 // values: 129 // 一个包含路由参数的对象。 130 // 131 // 返回结果: 132 // 一个包含与路由关联的 URL 的相关信息的对象。 133 public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values); 134 // 135 // 摘要: 136 // 确定参数值是否与该参数的约束匹配。 137 // 138 // 参数: 139 // httpContext: 140 // 一个对象,封装有关 HTTP 请求的信息。 141 // 142 // constraint: 143 // 用于测试 parameterName 的正则表达式或对象。 144 // 145 // parameterName: 146 // 要测试的参数的名称。 147 // 148 // values: 149 // 要测试的值。 150 // 151 // routeDirection: 152 // 一个指定 URL 路由是否处理传入请求或构造 URL 的值。 153 // 154 // 返回结果: 155 // 如果参数值与约束匹配,则为 true;否则为 false。 156 // 157 // 异常: 158 // System.InvalidOperationException: 159 // constraint 不是包含正则表达式的字符串。 160 protected virtual bool ProcessConstraint(HttpContextBase httpContext, object constraint, string parameterName, RouteValueDictionary values, RouteDirection routeDirection); 161 }
5.RouteTable
命名空间: System.Web.Routing
属性:Routes
方法:1个构造函数
1 // 摘要: 2 // 存储应用程序的 URL 路由。 3 [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")] 4 public class RouteTable 5 { 6 // 摘要: 7 // 初始化 System.Web.Routing.RouteTable 类的新实例。 8 public RouteTable(); 9 10 // 摘要: 11 // 获取从 System.Web.Routing.RouteBase 类派生的对象的集合。 12 // 13 // 返回结果: 14 // 包含集合中的所有路由的对象。 15 public static RouteCollection Routes { get; } 16 }
1.3 注册路由映射:我们可以通过 RouteTable的静态属性 Routes得到一个基于整个应用的全局路由表。这是一个类型为RouteCollection的集合对象 ,可以通过调用它的 MapPageRoute进行路由映射 ,即注册路由模板与某个物理文件的匹配关系。路由注册的核心就是在全局路由表中添加一个Route对象,该对象的绝大部分属性都可以通过MapPageRoute方法的相关参数来指定。
接下来我们通过实例演示的方式来说明路由注册的— 些细节问题 。^_^
-------------------------------------------------------------------------------------------------------------------------------------------------------
在路由注册中指定约束和默认值(constaints和defaults),示例:天气预报 的例子 S202 和 S203(S203中加入了对httpmethod的约束)
针对现有物理文件的路由(RouteTable.Routes.RouteExistingFiles),示例:天气预报 的例子 S204 和 S205(S204中RouteExistingFiles默认false,S205RouteExistingFiles为true)
RouteCollection和 Route的 RouteExistingFiles属性对路由的影响,示例:S206
注册需要被忽略的路由地址,示例:S207 和 S208 (S208中加了一段代码“RouteTable.Routes.Ignore("css/{filename}.css/{*pathInfo}");”为了让路由系统忽略对css文件的请求)
1.4 根据路出规则生成 URL:
Asp.NET的 路由系统主要有两个方面的应用,—个就是通过注册路由模板与物理文件路径的映射实现请求地址和物理地址的分离;另一个则是通过注册的路由规则生成一个相应的 URL,后者可以通过调用 RouteCollection对象的 GetVirtrualPath方法来实现。
下面是一个示例:天气预报 S209
1 namespace WebApp 2 { 3 public partial class Weather : System.Web.UI.Page 4 { 5 protected void Page_Load(object sender, EventArgs e) 6 { 7 RouteData routeData = new RouteData(); 8 routeData.Values.Add("areaCode", "0512"); 9 routeData.Values.Add("days", "1"); 10 RequestContext requestContext = new RequestContext(); 11 requestContext.HttpContext = new HttpContextWrapper(HttpContext.Current); 12 requestContext.RouteData = routeData; 13 14 RouteValueDictionary values = new RouteValueDictionary(); 15 values.Add("areaCode", "028"); 16 values.Add("days", "3"); 17 18 Response.Write(RouteTable.Routes.GetVirtualPath(null, null).VirtualPath+ "<br/>"); 19 Response.Write(RouteTable.Routes.GetVirtualPath(requestContext,null).VirtualPath + "<br/>"); 20 Response.Write(RouteTable.Routes.GetVirtualPath(requestContext,values).VirtualPath + "<br/>"); 21 } 22 } 23 }
从上面 的代码片段可以看到 ,第—次调用GetVirtrualPath方法传输的requestContext和values参数均为Null。第二次则指定了一个手工创建的RequestContext对象,其 RouteData的Values属性具有两个变量 (areaCode=0512,days=1),而values参数依然为 Null。第三次我们同时为参数requestContext和values指定了具体的对象,而后者包 含两个参数(areaCode=028,days=3)。
该实例最后现实的效果,如下图所示:
1.5 HttpHandler的动态映射:
一般情况下一个请求最终是通过一个具体的 HttpHandler进行处理的。表示—个Web页面的Page对象就是一个 HttpHandler,它 被用于最终处理基于某个.aspx文件的请求。我们可以通过
HttpHandler的动态映射来实现请求地址与物理文件路径之间的分离。
Asp.Net的URL路由系统通过一个注册的HttpModule对象实现对请求进行的拦截,然后动态映射一个用于处理当前请求的 HttpHandler对象。HttpHandler对请求进行处理并予以响应 。
作为请求拦截器的HttpModule类型为System.Web.Routing.UrlRoutingModule.
对于通过调用RouteCollection的MapPageRoute方法注册的Route来说,它的RouteHandler属性返回一个类型为System.Web.Routing.PageRouteHandler的对象。
PageRouteHandler的GetHttpHandler方法最终返回的就是针对映射页面文件路径的Page对象。
二、Asp.net Web API 路由
WebAPI的独立性在与它有一套自己的消息处理管道。作为消息处理管道的一部分,Asp.Net Web API 具有自己的路由系统,其路由采用与Asp.Net路由系统类似的设计。在下面的讲解中我们会发现定义在Asp.Net路由系统中的核心类型,在Asp.Net Web API的路由系统中均可以找到对应的类型。
请求与响应:
Asp.Net: 有HttpContext HttpRequest和HttpResponse 命名空间:System.Web
Asp.Net Web API: 无HttpContext HttpRequestMessage和HttpResponseMessage 命名空间:System.Net.Http
Asp.Net Web API的核心框架是一个独立抽象的消息处理管道.所以命名空间和所在的程序集也不同于Asp.Net.
1.HttpRequestMessage
命名空间: System.Net.Http
属性:Content、Headers、Method(默认为Get)、Properties、RequestUri、Version(默认值:System.Net.HttpVersion.Version11,表示为HTTP1.1)
方法:3个构造函数、Dispose、Dispose(带参虚方法)、ToString
请求报文的报头集合和主体内容分别通过HttpRequestMessage的Headers和Content来表示。利用字典类型的只读属性Properties,我们可以将任意对象作为属性附加到一个HttpRequestMessage对象上。
1 // 摘要: 2 // 表示 HTTP 请求消息。 3 public class HttpRequestMessage : IDisposable 4 { 5 // 摘要: 6 // 初始化 System.Net.Http.HttpRequestMessage 类的新实例。 7 public HttpRequestMessage(); 8 // 9 // 摘要: 10 // 初始化 HTTP 方法和请求 System.Uri 的 System.Net.Http.HttpRequestMessage 类的新实例。 11 // 12 // 参数: 13 // method: 14 // HTTP 方法。 15 // 16 // requestUri: 17 // 表示请求 System.Uri 的字符串。 18 public HttpRequestMessage(HttpMethod method, string requestUri); 19 // 20 // 摘要: 21 // 初始化 HTTP 方法和请求 System.Uri 的 System.Net.Http.HttpRequestMessage 类的新实例。 22 // 23 // 参数: 24 // method: 25 // HTTP 方法。 26 // 27 // requestUri: 28 // 要请求的 System.Uri。 29 public HttpRequestMessage(HttpMethod method, Uri requestUri); 30 31 // 摘要: 32 // 获取或设置 HTTP 消息的内容。 33 // 34 // 返回结果: 35 // 返回 System.Net.Http.HttpContent。 消息的内容 36 public HttpContent Content { get; set; } 37 // 38 // 摘要: 39 // 获取 HTTP 请求标头的集合。 40 // 41 // 返回结果: 42 // 返回 System.Net.Http.Headers.HttpRequestHeaders。 HTTP 请求标头的集合。 43 public HttpRequestHeaders Headers { get; } 44 // 45 // 摘要: 46 // 获取或设置 HTTP 请求信息使用的 HTTP 方法。 47 // 48 // 返回结果: 49 // 返回 System.Net.Http.HttpMethod。 被请求消息使用的HTTP 方法。 GET 是默认方法。 50 public HttpMethod Method { get; set; } 51 // 52 // 摘要: 53 // 获取 HTTP 请求的属性集。 54 // 55 // 返回结果: 56 // 返回 System.Collections.Generic.IDictionary<TKey,TValue>。 57 public IDictionary<string, object> Properties { get; } 58 // 59 // 摘要: 60 // 获取或设置 HTTP 请求的 System.Uri。 61 // 62 // 返回结果: 63 // 返回 System.Uri。 用于 HTTP 请求的 System.Uri。 64 public Uri RequestUri { get; set; } 65 // 66 // 摘要: 67 // 获取或设置 HTTP 消息版本。 68 // 69 // 返回结果: 70 // 返回 System.Version。 HTTP 消息版本。 默认值为 1.1。 71 public Version Version { get; set; } 72 73 // 摘要: 74 // 释放由 System.Net.Http.HttpRequestMessage 使用的非托管资源和托管资源。 75 public void Dispose(); 76 // 77 // 摘要: 78 // 释放由 System.Net.Http.HttpRequestMessage 使用的非托管资源,并可根据需要释放托管资源。 79 // 80 // 参数: 81 // disposing: 82 // 如果为 true,则释放托管资源和非托管资源;如果为 false,则仅释放非托管资源。 83 protected virtual void Dispose(bool disposing); 84 // 85 // 摘要: 86 // 返回表示当前对象的字符串。 87 // 88 // 返回结果: 89 // 返回 System.String。 当前对象的字符串表示形式。 90 public override string ToString(); 91 }
2.HttpResponseMessage
命名空间: System.Net.Http
属性:Content、Headers、Version、IsSuccessStatusCode(该值指示 HTTP 响应是否成功【200-299】)、ReasonPhrase(获取或设置服务器与状态代码通常一起发送的原因短语)、RequestMessage(获取或设置导致此响应消息的请求消息)、StatusCode(HTTP 响应的状态代码)
方法:2个构造函数、Dispose、Dispose(带参虚方法)、ToString、EnsureSuccessStatusCode
1 // 摘要: 2 // 表示 HTTP 响应消息。 3 public class HttpResponseMessage : IDisposable 4 { 5 // 摘要: 6 // 初始化 System.Net.Http.HttpResponseMessage 类的新实例。 7 public HttpResponseMessage(); 8 // 9 // 摘要: 10 // 初始化指定的 System.Net.Http.HttpResponseMessage.StatusCode 的 System.Net.Http.HttpResponseMessage 11 // 类的新实例。 12 // 13 // 参数: 14 // statusCode: 15 // HTTP 响应的状态代码。 16 public HttpResponseMessage(HttpStatusCode statusCode); 17 18 // 摘要: 19 // 获取或设置 HTTP 响应消息的内容。 20 // 21 // 返回结果: 22 // 返回 System.Net.Http.HttpContent。 HTTP 响应消息的内容。 23 public HttpContent Content { get; set; } 24 // 25 // 摘要: 26 // 获取 HTTP 响应标头的集合。 27 // 28 // 返回结果: 29 // 返回 System.Net.Http.Headers.HttpResponseHeaders。 HTTP 响应标头的集合。 30 public HttpResponseHeaders Headers { get; } 31 // 32 // 摘要: 33 // 获取一个值,该值指示 HTTP 响应是否成功。 34 // 35 // 返回结果: 36 // 返回 System.Boolean。 指示 HTTP 响应是否成功的值。 如果 System.Net.Http.HttpResponseMessage.StatusCode 37 // 在 200-299 范围中,则为 true;否则为 false。 38 public bool IsSuccessStatusCode { get; } 39 // 40 // 摘要: 41 // 获取或设置服务器与状态代码通常一起发送的原因短语。 42 // 43 // 返回结果: 44 // 返回 System.String。 服务器发送的原因词组。 45 public string ReasonPhrase { get; set; } 46 // 47 // 摘要: 48 // 获取或设置导致此响应消息的请求消息。 49 // 50 // 返回结果: 51 // 返回 System.Net.Http.HttpRequestMessage。 导致此响应信息的请求消息。 52 public HttpRequestMessage RequestMessage { get; set; } 53 // 54 // 摘要: 55 // 获取或设置 HTTP 响应的状态代码。 56 // 57 // 返回结果: 58 // 返回 System.Net.HttpStatusCode。 HTTP 响应的状态代码。 59 public HttpStatusCode StatusCode { get; set; } 60 // 61 // 摘要: 62 // 获取或设置 HTTP 消息版本。 63 // 64 // 返回结果: 65 // 返回 System.Version。 HTTP 消息版本。 默认值为 1.1。 66 public Version Version { get; set; } 67 68 // 摘要: 69 // 释放由 System.Net.Http.HttpResponseMessage 使用的非托管资源。 70 public void Dispose(); 71 // 72 // 摘要: 73 // 释放由 System.Net.Http.HttpResponseMessage 使用的非托管资源,并可根据需要释放托管资源。 74 // 75 // 参数: 76 // disposing: 77 // 如果为 true,则释放托管资源和非托管资源;如果为 false,则仅释放非托管资源。 78 protected virtual void Dispose(bool disposing); 79 // 80 // 摘要: 81 // 如果 HTTP 响应的 System.Net.Http.HttpResponseMessage.IsSuccessStatusCode 属性为 false, 82 // 将引发异常。 83 // 84 // 返回结果: 85 // 返回 System.Net.Http.HttpResponseMessage。 如果调用成功则 HTTP 响应消息。 86 public HttpResponseMessage EnsureSuccessStatusCode(); 87 // 88 // 摘要: 89 // 返回表示当前对象的字符串。 90 // 91 // 返回结果: 92 // 返回 System.String。 当前对象的字符串表示形式。 93 public override string ToString(); 94 }
3.HttpContent
HttpRequestMessage和HttpResponseMessage都有一个类型为HttpContent的属性Content,表示请求报文和响应报头的主体内容 。我们可以调用其ReadAsByteArrayAsync/ReadAsstreamAsync/ReadAsstringAsync方法读取具体的主体内容,也可以调用CopyToAsync方法拷贝当前内容并将其写入指定的
Stream对象中。
命名空间: System.Net.Http
属性:Headers(类型为HttpContentHeaders)
方法:1个构造函数、CopyToAsync(重载2)、CreateContentReadStreamAsync、Dispose、LoadIntoBufferAsync(重载2)、ReadAsByteArrayAsync、ReadAsStreamAsync、ReadAsStringAsync、SerializeToStreamAsync、TryComputeLength
1 // 摘要: 2 // 表示 HTTP 实体正文和内容标头的基类。 3 public abstract class HttpContent : IDisposable 4 { 5 // 摘要: 6 // 初始化 System.Net.Http.HttpContent 类的新实例。 7 protected HttpContent(); 8 9 // 摘要: 10 // 根据 RFC 2616 中的定义,获取内容标头。 11 // 12 // 返回结果: 13 // 返回 System.Net.Http.Headers.HttpContentHeaders。 如 RFC 2616 中定义的内容标头。 14 public HttpContentHeaders Headers { get; } 15 16 // 摘要: 17 // 以异步操作将 HTTP 内容写入流。 18 // 19 // 参数: 20 // stream: 21 // 目标流。 22 // 23 // 返回结果: 24 // 返回 System.Threading.Tasks.Task。 表示异步操作的任务对象。 25 public Task CopyToAsync(Stream stream); 26 // 27 // 摘要: 28 // 以异步操作将 HTTP 内容写入流。 29 // 30 // 参数: 31 // stream: 32 // 目标流。 33 // 34 // context: 35 // 有关传输的信息(例如,通道绑定)。 此参数可以为 null。 36 // 37 // 返回结果: 38 // 返回 System.Threading.Tasks.Task。 表示异步操作的任务对象。 39 public Task CopyToAsync(Stream stream, TransportContext context); 40 // 41 // 摘要: 42 // 以异步操作将 HTTP 内容写入内存流。 43 // 44 // 返回结果: 45 // 返回 System.Threading.Tasks.Task<TResult>。 表示异步操作的任务对象。 46 protected virtual Task<Stream> CreateContentReadStreamAsync(); 47 // 48 // 摘要: 49 // 释放由 System.Net.Http.HttpContent 使用的非托管资源和托管资源。 50 public void Dispose(); 51 // 52 // 摘要: 53 // 释放由 System.Net.Http.HttpContent 使用的非托管资源,并可根据需要释放托管资源。 54 // 55 // 参数: 56 // disposing: 57 // 如果为 true,则释放托管资源和非托管资源;如果为 false,则仅释放非托管资源。 58 protected virtual void Dispose(bool disposing); 59 // 60 // 摘要: 61 // 以异步操作将 HTTP 内容序列化到内存缓冲区。 62 // 63 // 返回结果: 64 // 返回 System.Threading.Tasks.Task。 表示异步操作的任务对象。 65 public Task LoadIntoBufferAsync(); 66 // 67 // 摘要: 68 // 以异步操作将 HTTP 内容序列化到内存缓冲区。 69 // 70 // 参数: 71 // maxBufferSize: 72 // 要使用的缓冲区的最大大小(以字节为单位)。 73 // 74 // 返回结果: 75 // 返回 System.Threading.Tasks.Task。表示异步操作的任务对象。 76 public Task LoadIntoBufferAsync(long maxBufferSize); 77 // 78 // 摘要: 79 // 以异步操作将 HTTP 内容写入字节数组。 80 // 81 // 返回结果: 82 // 返回 System.Threading.Tasks.Task<TResult>。 表示异步操作的任务对象。 83 public Task<byte[]> ReadAsByteArrayAsync(); 84 // 85 // 摘要: 86 // 以异步操作将 HTTP 内容写入流。 87 // 88 // 返回结果: 89 // 返回 System.Threading.Tasks.Task<TResult>。 表示异步操作的任务对象。 90 public Task<Stream> ReadAsStreamAsync(); 91 // 92 // 摘要: 93 // 以异步操作将 HTTP 内容写入流。 94 // 95 // 返回结果: 96 // 返回 System.Threading.Tasks.Task<TResult>。 表示异步操作的任务对象。 97 public Task<string> ReadAsStringAsync(); 98 // 99 // 摘要: 100 // 以异步操作将 HTTP 内容序列化到流。 101 // 102 // 参数: 103 // stream: 104 // 目标流。 105 // 106 // context: 107 // 有关传输的信息(例如,通道绑定)。 此参数可以为 null。 108 // 109 // 返回结果: 110 // 返回 System.Threading.Tasks.Task。 表示异步操作的任务对象。 111 protected abstract Task SerializeToStreamAsync(Stream stream, TransportContext context); 112 // 113 // 摘要: 114 // 确定 HTTP 内容是否具备有效的字节长度。 115 // 116 // 参数: 117 // length: 118 // 以字节为单位的 HHTP 对象的长度。 119 // 120 // 返回结果: 121 // 返回 System.Boolean。 如果 length 为有效长度,则为 true;否则,为 false。 122 protected internal abstract bool TryComputeLength(out long length); 123 }
1 // 摘要: 2 // 表示在 RFC 2616 中定义的“内容标题”的集合。 3 public sealed class HttpContentHeaders : HttpHeaders 4 { 5 // 摘要: 6 // 获取 HTTP 响应的 Allow 内容标题的值。 7 // 8 // 返回结果: 9 // 返回 System.Collections.Generic.ICollection<T>。 请求 HTTP 的 Allow 标题的值。 10 public ICollection<string> Allow { get; } 11 // 12 // 摘要: 13 // 获取 HTTP 响应上的 Content-Disposition 内容标头值。 14 // 15 // 返回结果: 16 // 返回 System.Net.Http.Headers.ContentDispositionHeaderValue。HTTP 响应上的 Content-Disposition 17 // 内容标头值。 18 public ContentDispositionHeaderValue ContentDisposition { get; set; } 19 // 20 // 摘要: 21 // 获取 HTTP 响应的 Content-Encoding 内容标题的值。 22 // 23 // 返回结果: 24 // 返回 System.Collections.Generic.ICollection<T>。 请求 HTTP 的 Content-Encoding 25 // 内容标题的值。 26 public ICollection<string> ContentEncoding { get; } 27 // 28 // 摘要: 29 // 获取 HTTP 响应的 Content-Language 内容标题的值。 30 // 31 // 返回结果: 32 // 返回 System.Collections.Generic.ICollection<T>。 请求 HTTP 的 Content-Language 33 // 内容标题的值。 34 public ICollection<string> ContentLanguage { get; } 35 // 36 // 摘要: 37 // 获取或设置 HTTP 响应上的 Content-Length 内容标头值。 38 // 39 // 返回结果: 40 // 返回 System.Int64。 请求 HTTP 的 Content-Length 内容标题的值。 41 public long? ContentLength { get; set; } 42 // 43 // 摘要: 44 // 获取或设置 HTTP 响应上的 Content-Location 内容标头值。 45 // 46 // 返回结果: 47 // 返回 System.Uri。 请求 HTTP 的 Content-Location 内容标题的值。 48 public Uri ContentLocation { get; set; } 49 // 50 // 摘要: 51 // 获取或设置 HTTP 响应上的 Content-MD5 内容标头值。 52 // 53 // 返回结果: 54 // 返回 System.Byte。 请求 HTTP 的 Content-MD5 内容标题的值。 55 public byte[] ContentMD5 { get; set; } 56 // 57 // 摘要: 58 // 获取或设置 HTTP 响应上的 Content-Range 内容标头值。 59 // 60 // 返回结果: 61 // 返回 System.Net.Http.Headers.ContentRangeHeaderValue。 请求 HTTP 的 Content-Range 62 // 内容标题的值。 63 public ContentRangeHeaderValue ContentRange { get; set; } 64 // 65 // 摘要: 66 // 获取或设置 HTTP 响应上的 Content-Type 内容标头值。 67 // 68 // 返回结果: 69 // 返回 System.Net.Http.Headers.MediaTypeHeaderValue。 请求 HTTP 的 Content-Type 内容标题的值。 70 public MediaTypeHeaderValue ContentType { get; set; } 71 // 72 // 摘要: 73 // 获取或设置 HTTP 响应上的 Expires 内容标头值。 74 // 75 // 返回结果: 76 // 返回 System.DateTimeOffset。 请求 HTTP 的 Expires 内容标题的值。 77 public DateTimeOffset? Expires { get; set; } 78 // 79 // 摘要: 80 // 获取或设置 HTTP 响应上的 Last-Modified 内容标头值。 81 // 82 // 返回结果: 83 // 返回 System.DateTimeOffset。 请求 HTTP 的 Last-Modified 内容标题的值。 84 public DateTimeOffset? LastModified { get; set; } 85 }
HttpContent的只读属性 Headers返回一个 System.Net.Http.Headers.HttpContentHeaders对象,我们可以利用它获取请求/响应报文中与主体内容相关的报头 。
下面的列表给出了定义在HttpContentHeaders中的属性各自对应着怎样的报头 。
为了支持不同的主体内容的表示形式或者写入方式,在 “System.Net.Http” 命名空间下定义了如下一系列具体的HttpContent类型,当我们在创建具有主体内容的HttpRequestMessage 或者HttpResponseMessage对象时,可以根据具体的场景选择相应的 HttpContent类型。
● ByteArrayContent:采用字节数组表示请求/响应的主体内容。
● MultipartContent:针对媒体类型 “multipart/*” 的主体内容 ,即一个完整的内容被分割成多个片段以实现独立传输 (比如针对大文件的多线程下载),每 个片段的内容保存在一个 MultipartContent对象中。
● ObjectContent:直接将一个数据对象作为请求/响应的主体,具体的内容是该对象序列化后的结果。
● PushStreamContent/StreamContent:这两种类型提供—种以StreamContent的方式写入请求/响应主体内容的方式,前者采用 “推 ” 模式,后者则采用 “拉 ” 模式 。
● HttpMessageContent:这是对—个HttpRequestMessage或者HttpResponseMessage对象的封装,它会将 HttpRequestMessage/HttpResponseMessage表示的整个报文内容 (包含起始行 、报头集合和主体内容 )作为主体 。 具有这样主体内容 的请求/响应报文采用的媒体类型 (Content-Type报头 )为 “application/http;msgtype=request”或者 “application/http;msgtype=response”。
ASP.NET Web API 路由系统:
Asp.NET路由系统的核心是由注册Route对象所组成的路由表 。Asp.NET Web API路由系统的路由表由一系列注册的HttpRoute对象组成 ,因为相应的类型实现了接口IHttpRoute。(Asp.NET Web API路由系统中主要的类定义在System.Web.Http.Routing中)。
1.HttpRouteData
调用某个HttpRoute对象的GetRouteData方法的时候,返回HttpRouteData。HttpRouteData实现了接口IHttpRouteData。
1 // 摘要: 2 // Provides information about a route. 3 public interface IHttpRouteData 4 { 5 // 摘要: 6 // Gets the object that represents the route. 7 // 8 // 返回结果: 9 // The object that represents the route. 10 IHttpRoute Route { get; } 11 // 12 // 摘要: 13 // Gets a collection of URL parameter values and default values for the route. 14 // 15 // 返回结果: 16 // The values that are parsed from the URL and from default values. 17 IDictionary<string, object> Values { get; } 18 }
1 // 摘要: 2 // Encapsulates information regarding the HTTP route. 3 public class HttpRouteData : IHttpRouteData 4 { 5 // 摘要: 6 // Initializes a new instance of the System.Web.Http.Routing.HttpRouteData class. 7 // 8 // 参数: 9 // route: 10 // An object that defines the route. 11 public HttpRouteData(IHttpRoute route); 12 // 13 // 摘要: 14 // Initializes a new instance of the System.Web.Http.Routing.HttpRouteData class. 15 // 16 // 参数: 17 // route: 18 // An object that defines the route. 19 // 20 // values: 21 // The value. 22 public HttpRouteData(IHttpRoute route, HttpRouteValueDictionary values); 23 24 // 摘要: 25 // Gets the object that represents the route. 26 // 27 // 返回结果: 28 // the object that represents the route. 29 public IHttpRoute Route { get; } 30 // 31 // 摘要: 32 // Gets a collection of URL parameter values and default values for the route. 33 // 34 // 返回结果: 35 // An object that contains values that are parsed from the URL and from default 36 // values. 37 public IDictionary<string, object> Values { get; } 38 }
2.HttpVirtualPathData
调用HttpRoute对象GetVirtualPath属性生成URL(同Asp.net中的Route对象的GetVirtualPath方法)
1 // 摘要: 2 // Defines the properties for HTTP route. 3 public interface IHttpVirtualPathData 4 { 5 // 摘要: 6 // Gets the HTTP route. 7 // 8 // 返回结果: 9 // The HTTP route. 10 IHttpRoute Route { get; } 11 // 12 // 摘要: 13 // Gets the URI that represents the virtual path of the current HTTP route. 14 // 15 // 返回结果: 16 // The URI that represents the virtual path of the current HTTP route. 17 string VirtualPath { get; set; } 18 }
1 // 摘要: 2 // Presents the data regarding the HTTP virtual path. 3 public class HttpVirtualPathData : IHttpVirtualPathData 4 { 5 // 摘要: 6 // Initializes a new instance of the System.Web.Http.Routing.HttpVirtualPathData 7 // class. 8 // 9 // 参数: 10 // route: 11 // The route of the virtual path. 12 // 13 // virtualPath: 14 // The URL that was created from the route definition. 15 public HttpVirtualPathData(IHttpRoute route, string virtualPath); 16 17 // 摘要: 18 // Gets or sets the route of the virtual path.. 19 // 20 // 返回结果: 21 // The route of the virtual path. 22 public IHttpRoute Route { get; } 23 // 24 // 摘要: 25 // Gets or sets the URL that was created from the route definition. 26 // 27 // 返回结果: 28 // The URL that was created from the route definition. 29 public string VirtualPath { get; set; } 30 }
3.HttpRouteConstraint
一个HttpRoute能否与HTTP请求相匹配,必须同时满足两个条件:其一,请求URL具有与 Route的路由模板相匹配的模式;其二,当前请求必须通过定义在 Route上的所有约束。WebAPI中HttpRouteConstraint表示约束,该类实现了IHttpRouteConstraint接口。
1 // 摘要: 2 // Represents a base class route constraint. 3 public interface IHttpRouteConstraint 4 { 5 // 摘要: 6 // Determines whether this instance equals a specified route. 7 // 8 // 参数: 9 // request: 10 // The request. 11 // 12 // route: 13 // The route to compare. 14 // 15 // parameterName: 16 // The name of the parameter. 17 // 18 // values: 19 // A list of parameter values. 20 // 21 // routeDirection: 22 // The route direction. 23 // 24 // 返回结果: 25 // True if this instance equals a specified route; otherwise, false. 26 bool Match(System.Net.Http.HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection); 27 }
URL路由具有两个“方向”上的应用:其一,利用路由模板匹配 “入栈” 请求进而得到相应的路由数据;其二,根据定义的路由规则和提供的路由变量生成 “出栈”URL 。
1 // 摘要: 2 // Specifies an enumeration of route direction. 3 public enum HttpRouteDirection 4 { 5 // 摘要: 6 // The UriResolution direction. 7 UriResolution = 0, 8 // 9 // 摘要: 10 // The UriGeneration direction. 11 UriGeneration = 1, 12 }
在很多情况下注册的路由都具有针对HTTP方法的限制。ASP.NET路由系统定义了一个HttpMethodConstraint类型实现针对HTTP方法的约束,WebAPI路由系统也定义了如下一个同名的类型。
1 // 摘要: 2 // Enables you to define which HTTP verbs are allowed when ASP.NET routing determines 3 // whether a URL matches a route. 4 public class HttpMethodConstraint : IHttpRouteConstraint 5 { 6 // 摘要: 7 // Initializes a new instance of the System.Web.Http.Routing.HttpMethodConstraint 8 // class by using the HTTP verbs that are allowed for the route. 9 // 10 // 参数: 11 // allowedMethods: 12 // The HTTP verbs that are valid for the route. 13 public HttpMethodConstraint(params System.Net.Http.HttpMethod[] allowedMethods); 14 15 // 摘要: 16 // Gets or sets the collection of allowed HTTP verbs for the route. 17 // 18 // 返回结果: 19 // A collection of allowed HTTP verbs for the route. 20 public Collection<System.Net.Http.HttpMethod> AllowedMethods { get; } 21 22 // 摘要: 23 // Determines whether the request was made with an HTTP verb that is one of 24 // the allowed verbs for the route. 25 // 26 // 参数: 27 // request: 28 // The request that is being checked to determine whether it matches the URL. 29 // 30 // route: 31 // The object that is being checked to determine whether it matches the URL. 32 // 33 // parameterName: 34 // The name of the parameter that is being checked. 35 // 36 // values: 37 // An object that contains the parameters for a route. 38 // 39 // routeDirection: 40 // An object that indicates whether the constraint check is being performed 41 // when an incoming request is processed or when a URL is generated. 42 // 43 // 返回结果: 44 // When ASP.NET routing is processing a request, true if the request was made 45 // by using an allowed HTTP verb; otherwise, false. When ASP.NET routing is 46 // constructing a URL, true if the supplied values contain an HTTP verb that 47 // matches one of the allowed HTTP verbs; otherwise, false. The default is true. 48 protected virtual bool Match(System.Net.Http.HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection); 49 }
除HttpMethodConstraint之外,在WebAP路由系统的应用编程接口中还定义了一系列的约束类型(验证数据类型的,验证字符串长度的等等)。这一系列的约束验证是基于特性(Attribute)的路由而设计的。【在以后的篇幅中会讲到特性路由】
4.HttpRoute
Asp.NET路由系统中的Route类均为RouteBase的子类。因为WebAPI中的路由对象的类型实现了IHttpRoute接口,我们将其统称为HttpRoute。
1 // 摘要: 2 // System.Web.Http.Routing.IHttpRoute defines the interface for a route expressing 3 // how to map an incoming System.Net.Http.HttpRequestMessage to a particular 4 // controller and action. 5 public interface IHttpRoute 6 { 7 // 摘要: 8 // Gets the constraints for the route parameters. 9 // 10 // 返回结果: 11 // The constraints for the route parameters. 12 IDictionary<string, object> Constraints { get; } 13 // 14 // 摘要: 15 // Gets any additional data tokens not used directly to determine whether a 16 // route matches an incoming System.Net.Http.HttpRequestMessage. 17 // 18 // 返回结果: 19 // The additional data tokens. 20 IDictionary<string, object> DataTokens { get; } 21 // 22 // 摘要: 23 // Gets the default values for route parameters if not provided by the incoming 24 // System.Net.Http.HttpRequestMessage. 25 // 26 // 返回结果: 27 // The default values for route parameters. 28 IDictionary<string, object> Defaults { get; } 29 // 30 // 摘要: 31 // Gets the message handler that will be the recipient of the request. 32 // 33 // 返回结果: 34 // The message handler. 35 System.Net.Http.HttpMessageHandler Handler { get; } 36 // 37 // 摘要: 38 // Gets the route template describing the URI pattern to match against. 39 // 40 // 返回结果: 41 // The route template. 42 string RouteTemplate { get; } 43 44 // 摘要: 45 // Determine whether this route is a match for the incoming request by looking 46 // up the <see cref="!:IRouteData" /> for the route. 47 // 48 // 参数: 49 // virtualPathRoot: 50 // The virtual path root. 51 // 52 // request: 53 // The request. 54 // 55 // 返回结果: 56 // The <see cref="!:RouteData" /> for a route if matches; otherwise null. 57 IHttpRouteData GetRouteData(string virtualPathRoot, System.Net.Http.HttpRequestMessage request); 58 // 59 // 摘要: 60 // Gets a virtual path data based on the route and the values provided. 61 // 62 // 参数: 63 // request: 64 // The request message. 65 // 66 // values: 67 // The values. 68 // 69 // 返回结果: 70 // The virtual path data. 71 IHttpVirtualPathData GetVirtualPath(System.Net.Http.HttpRequestMessage request, IDictionary<string, object> values); 72 }
HttpRoute的作用体现在两点 :对请求的 URL进行解析并生成封装路由数据的HttpRouteData对象,以及将提供的路由变量绑定到路由模板以生成一个完整的URL。这两个功能分别通过调用方法CetRouteData和GetVirtualPathData来完成 。
1 // 摘要: 2 // Represents a route class for self-host (i.e. hosted outside of ASP.NET). 3 public class HttpRoute : IHttpRoute 4 { 5 // 摘要: 6 // Specifies the HTTP route key. 7 public static readonly string HttpRouteKey; 8 9 // 摘要: 10 // Initializes a new instance of the System.Web.Http.Routing.HttpRoute class. 11 public HttpRoute(); 12 // 13 // 摘要: 14 // Initializes a new instance of the System.Web.Http.Routing.HttpRoute class. 15 // 16 // 参数: 17 // routeTemplate: 18 // The route template. 19 public HttpRoute(string routeTemplate); 20 // 21 // 摘要: 22 // Initializes a new instance of the System.Web.Http.Routing.HttpRoute class. 23 // 24 // 参数: 25 // routeTemplate: 26 // The route template. 27 // 28 // defaults: 29 // The default values for the route parameters. 30 public HttpRoute(string routeTemplate, HttpRouteValueDictionary defaults); 31 // 32 // 摘要: 33 // Initializes a new instance of the System.Web.Http.Routing.HttpRoute class. 34 // 35 // 参数: 36 // routeTemplate: 37 // The route template. 38 // 39 // defaults: 40 // The default values for the route parameters. 41 // 42 // constraints: 43 // The constraints for the route parameters. 44 public HttpRoute(string routeTemplate, HttpRouteValueDictionary defaults, HttpRouteValueDictionary constraints); 45 // 46 // 摘要: 47 // Initializes a new instance of the System.Web.Http.Routing.HttpRoute class. 48 // 49 // 参数: 50 // routeTemplate: 51 // The route template. 52 // 53 // defaults: 54 // The default values for the route parameters. 55 // 56 // constraints: 57 // The constraints for the route parameters. 58 // 59 // dataTokens: 60 // Any additional tokens for the route parameters. 61 public HttpRoute(string routeTemplate, HttpRouteValueDictionary defaults, HttpRouteValueDictionary constraints, HttpRouteValueDictionary dataTokens); 62 // 63 // 摘要: 64 // Initializes a new instance of the System.Web.Http.Routing.HttpRoute class. 65 // 66 // 参数: 67 // routeTemplate: 68 // The route template. 69 // 70 // defaults: 71 // The default values for the route parameters. 72 // 73 // constraints: 74 // The constraints for the route parameters. 75 // 76 // dataTokens: 77 // Any additional tokens for the route parameters. 78 // 79 // handler: 80 // The message handler that will be the recipient of the request. 81 public HttpRoute(string routeTemplate, HttpRouteValueDictionary defaults, HttpRouteValueDictionary constraints, HttpRouteValueDictionary dataTokens, System.Net.Http.HttpMessageHandler handler); 82 83 // 摘要: 84 // Gets the constraints for the route parameters. 85 // 86 // 返回结果: 87 // The constraints for the route parameters. 88 public IDictionary<string, object> Constraints { get; } 89 // 90 // 摘要: 91 // Gets any additional data tokens not used directly to determine whether a 92 // route matches an incoming System.Net.Http.HttpRequestMessage. 93 // 94 // 返回结果: 95 // Any additional data tokens not used directly to determine whether a route 96 // matches an incoming System.Net.Http.HttpRequestMessage. 97 public IDictionary<string, object> DataTokens { get; } 98 // 99 // 摘要: 100 // Gets the default values for route parameters if not provided by the incoming 101 // System.Net.Http.HttpRequestMessage. 102 // 103 // 返回结果: 104 // The default values for route parameters if not provided by the incoming System.Net.Http.HttpRequestMessage. 105 public IDictionary<string, object> Defaults { get; } 106 // 107 // 摘要: 108 // Gets or sets the http route handler. 109 // 110 // 返回结果: 111 // The http route handler. 112 public System.Net.Http.HttpMessageHandler Handler { get; } 113 // 114 // 摘要: 115 // Gets the route template describing the URI pattern to match against. 116 // 117 // 返回结果: 118 // The route template describing the URI pattern to match against. 119 public string RouteTemplate { get; } 120 121 // 摘要: 122 // Determines whether this route is a match for the incoming request by looking 123 // up the System.Web.Http.Routing.HttpRouteData for the route. 124 // 125 // 参数: 126 // virtualPathRoot: 127 // The virtual path root. 128 // 129 // request: 130 // The HTTP request. 131 // 132 // 返回结果: 133 // The System.Web.Http.Routing.HttpRouteData for a route if matches; otherwise 134 // null. 135 public virtual IHttpRouteData GetRouteData(string virtualPathRoot, System.Net.Http.HttpRequestMessage request); 136 // 137 // 摘要: 138 // Attempts to generate a URI that represents the values passed in based on 139 // current values from the System.Web.Http.Routing.HttpRouteData and new values 140 // using the specified System.Web.Http.Routing.HttpRoute. 141 // 142 // 参数: 143 // request: 144 // The HTTP request message. 145 // 146 // values: 147 // The route values. 148 // 149 // 返回结果: 150 // A System.Web.Http.Routing.HttpVirtualPathData instance or null if URI cannot 151 // be generated. 152 public virtual IHttpVirtualPathData GetVirtualPath(System.Net.Http.HttpRequestMessage request, IDictionary<string, object> values); 153 // 154 // 摘要: 155 // Determines whether this instance equals a specified route. 156 // 157 // 参数: 158 // request: 159 // The HTTP request. 160 // 161 // constraint: 162 // The constraints for the route parameters. 163 // 164 // parameterName: 165 // The name of the parameter. 166 // 167 // values: 168 // The list of parameter values. 169 // 170 // routeDirection: 171 // One of the enumeration values of the System.Web.Http.Routing.HttpRouteDirection 172 // enumeration. 173 // 174 // 返回结果: 175 // true if this instance equals a specified route; otherwise, false. 176 protected virtual bool ProcessConstraint(System.Net.Http.HttpRequestMessage request, object constraint, string parameterName, HttpRouteValueDictionary values, HttpRouteDirection routeDirection); 177 }
5.路由匹配与HttpRouteData的生成
示例:S210 路由注册时指定的虚拟根路径与约束对路由解析的影响
6.HttpRouteCollection
1 // 摘要: 2 // A collection of System.Web.Http.Routing.IHttpRoute instances. 3 public class HttpRouteCollection : ICollection<IHttpRoute>, IEnumerable<IHttpRoute>, IEnumerable, IDisposable 4 { 5 // 摘要: 6 // Initializes a new instance of the System.Web.Http.HttpRouteCollection class. 7 public HttpRouteCollection(); 8 // 9 // 摘要: 10 // Initializes a new instance of the System.Web.Http.HttpRouteCollection class. 11 // 12 // 参数: 13 // virtualPathRoot: 14 // The virtual path root. 15 public HttpRouteCollection(string virtualPathRoot); 16 17 // 摘要: 18 // Gets the number of items in the collection. 19 // 20 // 返回结果: 21 // The number of items in the collection. 22 public virtual int Count { get; } 23 // 24 // 摘要: 25 // Gets a value indicating whether the collection is read-only. 26 // 27 // 返回结果: 28 // true if the collection is read-only; otherwise, false. 29 public virtual bool IsReadOnly { get; } 30 // 31 // 摘要: 32 // Gets the virtual path root. 33 // 34 // 返回结果: 35 // The virtual path root. 36 public virtual string VirtualPathRoot { get; } 37 38 // 摘要: 39 // Gets or sets the element at the specified index. 40 // 41 // 返回结果: 42 // The System.Web.Http.Routing.IHttpRoute at the specified index. 43 public virtual IHttpRoute this[int index] { get; } 44 // 45 // 摘要: 46 // Gets or sets the element with the specified route name. 47 // 48 // 返回结果: 49 // The System.Web.Http.Routing.IHttpRoute at the specified index. 50 public virtual IHttpRoute this[string name] { get; } 51 52 // 摘要: 53 // Adds an System.Web.Http.Routing.IHttpRoute instance to the collection. 54 // 55 // 参数: 56 // name: 57 // The name of the route. 58 // 59 // route: 60 // The System.Web.Http.Routing.IHttpRoute instance to add to the collection. 61 public virtual void Add(string name, IHttpRoute route); 62 // 63 // 摘要: 64 // Removes all items from the collection. 65 public virtual void Clear(); 66 // 67 // 摘要: 68 // Determines whether the collection contains a specific System.Web.Http.Routing.IHttpRoute. 69 // 70 // 参数: 71 // item: 72 // The object to locate in the collection. 73 // 74 // 返回结果: 75 // true if the System.Web.Http.Routing.IHttpRoute is found in the collection; 76 // otherwise, false. 77 public virtual bool Contains(IHttpRoute item); 78 // 79 // 摘要: 80 // Determines whether the collection contains an element with the specified 81 // key. 82 // 83 // 参数: 84 // name: 85 // The key to locate in the collection. 86 // 87 // 返回结果: 88 // true if the collection contains an element with the key; otherwise, false. 89 public virtual bool ContainsKey(string name); 90 // 91 // 摘要: 92 // Copies the route names and System.Web.Http.Routing.IHttpRoute instances of 93 // the collection to an array, starting at a particular array index. 94 // 95 // 参数: 96 // array: 97 // The array that is the destination of the elements copied from the collection. 98 // 99 // arrayIndex: 100 // The zero-based index in array at which copying begins. 101 public virtual void CopyTo(IHttpRoute[] array, int arrayIndex); 102 // 103 // 摘要: 104 // Copies the System.Web.Http.Routing.IHttpRoute instances of the collection 105 // to an array, starting at a particular array index. 106 // 107 // 参数: 108 // array: 109 // The array that is the destination of the elements copied from the collection. 110 // 111 // arrayIndex: 112 // The zero-based index in array at which copying begins. 113 public virtual void CopyTo(KeyValuePair<string, IHttpRoute>[] array, int arrayIndex); 114 // 115 // 摘要: 116 // Creates an System.Web.Http.Routing.IHttpRoute instance. 117 // 118 // 参数: 119 // routeTemplate: 120 // The route template. 121 // 122 // defaults: 123 // An object that contains the default route parameters. 124 // 125 // constraints: 126 // An object that contains the route constraints. 127 // 128 // 返回结果: 129 // The new System.Web.Http.Routing.IHttpRoute instance. 130 public IHttpRoute CreateRoute(string routeTemplate, object defaults, object constraints); 131 // 132 // 摘要: 133 // Creates an System.Web.Http.Routing.IHttpRoute instance. 134 // 135 // 参数: 136 // routeTemplate: 137 // The route template. 138 // 139 // defaults: 140 // An object that contains the default route parameters. 141 // 142 // constraints: 143 // An object that contains the route constraints. 144 // 145 // dataTokens: 146 // The route data tokens. 147 // 148 // 返回结果: 149 // The new System.Web.Http.Routing.IHttpRoute instance. 150 public IHttpRoute CreateRoute(string routeTemplate, IDictionary<string, object> defaults, IDictionary<string, object> constraints, IDictionary<string, object> dataTokens); 151 // 152 // 摘要: 153 // Creates an System.Web.Http.Routing.IHttpRoute instance. 154 // 155 // 参数: 156 // routeTemplate: 157 // The route template. 158 // 159 // defaults: 160 // An object that contains the default route parameters. 161 // 162 // constraints: 163 // An object that contains the route constraints. 164 // 165 // dataTokens: 166 // The route data tokens. 167 // 168 // handler: 169 // The message handler for the route. 170 // 171 // 返回结果: 172 // The new System.Web.Http.Routing.IHttpRoute instance. 173 public virtual IHttpRoute CreateRoute(string routeTemplate, IDictionary<string, object> defaults, IDictionary<string, object> constraints, IDictionary<string, object> dataTokens, System.Net.Http.HttpMessageHandler handler); 174 // 175 // 摘要: 176 // Performs application-defined tasks associated with freeing, releasing, or 177 // resetting unmanaged resources. 178 public void Dispose(); 179 // 180 // 摘要: 181 // Releases the unmanaged resources that are used by the object and, optionally, 182 // releases the managed resources. 183 // 184 // 参数: 185 // disposing: 186 // true to release both managed and unmanaged resources; false to release only 187 // unmanaged resources. 188 protected virtual void Dispose(bool disposing); 189 // 190 // 摘要: 191 // Returns an enumerator that iterates through the collection. 192 // 193 // 返回结果: 194 // An System.Collections.Generic.IEnumerator<T> that can be used to iterate 195 // through the collection. 196 public virtual IEnumerator<IHttpRoute> GetEnumerator(); 197 // 198 // 摘要: 199 // Gets the route data for a specified HTTP request. 200 // 201 // 参数: 202 // request: 203 // The HTTP request. 204 // 205 // 返回结果: 206 // AnSystem.Web.Http.Routing.IHttpRouteData instance that represents the route 207 // data. 208 public virtual IHttpRouteData GetRouteData(System.Net.Http.HttpRequestMessage request); 209 // 210 // 摘要: 211 // Gets a virtual path. 212 // 213 // 参数: 214 // request: 215 // The HTTP request. 216 // 217 // name: 218 // The route name. 219 // 220 // values: 221 // The route values. 222 // 223 // 返回结果: 224 // An System.Web.Http.Routing.IHttpVirtualPathData instance that represents 225 // the virtual path. 226 public virtual IHttpVirtualPathData GetVirtualPath(System.Net.Http.HttpRequestMessage request, string name, IDictionary<string, object> values); 227 // 228 // 摘要: 229 // Inserts an System.Web.Http.Routing.IHttpRoute instance into the collection. 230 // 231 // 参数: 232 // index: 233 // The zero-based index at which value should be inserted. 234 // 235 // name: 236 // The route name. 237 // 238 // value: 239 // The System.Web.Http.Routing.IHttpRoute to insert. The value cannot be null. 240 public virtual void Insert(int index, string name, IHttpRoute value); 241 // 242 // 摘要: 243 // Called internally to get the enumerator for the collection. 244 // 245 // 返回结果: 246 // An System.Collections.IEnumerator that can be used to iterate through the 247 // collection. 248 protected virtual IEnumerator OnGetEnumerator(); 249 // 250 // 摘要: 251 // Removes an System.Web.Http.Routing.IHttpRoute instance from the collection. 252 // 253 // 参数: 254 // name: 255 // The name of the route to remove. 256 // 257 // 返回结果: 258 // true if the element is successfully removed; otherwise, false. This method 259 // also returns false if name was not found in the collection. 260 public virtual bool Remove(string name); 261 // 262 // 摘要: 263 // Gets the System.Web.Http.Routing.IHttpRoute with the specified route name. 264 // 265 // 参数: 266 // name: 267 // The route name. 268 // 269 // route: 270 // When this method returns, contains the System.Web.Http.Routing.IHttpRoute 271 // instance, if the route name is found; otherwise, null. This parameter is 272 // passed uninitialized. 273 // 274 // 返回结果: 275 // true if the collection contains an element with the specified name; otherwise, 276 // false. 277 public virtual bool TryGetValue(string name, out IHttpRoute route); 278 }
注册路由映射
与 Asp.NET路由系统下的路由映射类似,Web API下的路由映射就是为针对应用的路由表添加相应HttpRoute对象的过程。
Web API的消息处理管道所做的所有配置基本上都是通过一个类型为System.Web.HttpConfiguration的对象来完成的,路由注册自然也不例外 。
HttpConfiguration具有一个类型为HttpRouteCollection的只读属性Routes,我们进行路 由映射注册的HttpRoute正是被添加于此 。
1 // 摘要: 2 // Represents a configuration of System.Web.Http.HttpServer instances. 3 public class HttpConfiguration : IDisposable 4 { 5 // 摘要: 6 // Initializes a new instance of the System.Web.Http.HttpConfiguration class. 7 public HttpConfiguration(); 8 // 9 // 摘要: 10 // Initializes a new instance of the System.Web.Http.HttpConfiguration class 11 // with an HTTP route collection. 12 // 13 // 参数: 14 // routes: 15 // The HTTP route collection to associate with this instance. 16 public HttpConfiguration(HttpRouteCollection routes); 17 18 // 摘要: 19 // Gets or sets the dependency resolver associated with thisinstance. 20 // 21 // 返回结果: 22 // The dependency resolver. 23 public IDependencyResolver DependencyResolver { get; set; } 24 // 25 // 摘要: 26 // Gets the list of filters that apply to all requests served using this System.Web.Http.HttpConfiguration 27 // instance. 28 // 29 // 返回结果: 30 // The list of filters. 31 public HttpFilterCollection Filters { get; } 32 // 33 // 摘要: 34 // Gets the media-type formatters for this instance. 35 // 36 // 返回结果: 37 // A collection of System.Net.Http.Formatting.MediaTypeFormatter objects. 38 public MediaTypeFormatterCollection Formatters { get; } 39 // 40 // 摘要: 41 // Gets or sets a value indicating whether error details should be included 42 // in error messages. 43 // 44 // 返回结果: 45 // The System.Web.Http.IncludeErrorDetailPolicy value that indicates that error 46 // detail policy. 47 public IncludeErrorDetailPolicy IncludeErrorDetailPolicy { get; set; } 48 // 49 // 摘要: 50 // Gets or sets the action that will perform final initialization of the System.Web.Http.HttpConfiguration 51 // instance before it is used to process requests. 52 // 53 // 返回结果: 54 // The action that will perform final initialization of the System.Web.Http.HttpConfiguration 55 // instance. 56 public Action<HttpConfiguration> Initializer { get; set; } 57 // 58 // 摘要: 59 // Gets an ordered list of System.Net.Http.DelegatingHandler instances to be 60 // invoked as an System.Net.Http.HttpRequestMessage travels up the stack and 61 // an System.Net.Http.HttpResponseMessage travels down in stack in return. 62 // 63 // 返回结果: 64 // The message handler collection. 65 public Collection<System.Net.Http.DelegatingHandler> MessageHandlers { get; } 66 // 67 // 摘要: 68 // Gets the collection of rules for how parameters should be bound. 69 // 70 // 返回结果: 71 // A collection of functions that can produce a parameter binding for a given 72 // parameter. 73 public ParameterBindingRulesCollection ParameterBindingRules { get; internal set; } 74 // 75 // 摘要: 76 // Gets the properties associated with this instance. 77 // 78 // 返回结果: 79 // The System.Collections.Concurrent.ConcurrentDictionary<TKey,TValue>that contains 80 // the properties. 81 public ConcurrentDictionary<object, object> Properties { get; } 82 // 83 // 摘要: 84 // Gets the System.Web.Http.HttpRouteCollection associated with this System.Web.Http.HttpConfiguration 85 // instance. 86 // 87 // 返回结果: 88 // The System.Web.Http.HttpRouteCollection. 89 public HttpRouteCollection Routes { get; } 90 // 91 // 摘要: 92 // Gets the container of default services associated with this instance. 93 // 94 // 返回结果: 95 // The System.Web.Http.Controllers.ServicesContainer that contains the default 96 // services for this instance. 97 public ServicesContainer Services { get; internal set; } 98 // 99 // 摘要: 100 // Gets the root virtual path. 101 // 102 // 返回结果: 103 // The root virtual path. 104 public string VirtualPathRoot { get; } 105 106 // 摘要: 107 // Performs application-defined tasks associated with freeing, releasing, or 108 // resetting unmanaged resources. 109 public void Dispose(); 110 // 111 // 摘要: 112 // Releases the unmanaged resources that are used by the object and, optionally, 113 // releases the managed resources. 114 // 115 // 参数: 116 // disposing: 117 // true to release both managed and unmanaged resources; false to release only 118 // unmanaged resources. 119 protected virtual void Dispose(bool disposing); 120 // 121 // 摘要: 122 // Invoke the Intializer hook. It is considered immutable from this point forward. 123 // It's safe to call this multiple times. 124 public void EnsureInitialized(); 125 }
我们可以直接根据制定的路由模版,以及针对路由变量的默认值和约束来创建相应的HttpRoute,并最终将其添加到通过HttpConfigurationo的Routes对象表示的路由表中从而达到注册路由映射的目的。
另外,我们可以直接调用HttpRouteCollection如下一系列重载的扩展方法MapHttpRoute达到相同的目的。实际上这些扩展方法最终还是调用HttpRouteCollection的Add方法将创建的HttpRoute添加到路由表中的。
1 // 摘要: 2 // Extension methods for System.Web.Http.HttpRouteCollection 3 [EditorBrowsable(EditorBrowsableState.Never)] 4 public static class HttpRouteCollectionExtensions 5 { 6 // 摘要: 7 // Maps the specified route for handling HTTP batch requests. 8 // 9 // 参数: 10 // routes: 11 // A collection of routes for the application. 12 // 13 // routeName: 14 // The name of the route to map. 15 // 16 // routeTemplate: 17 // The route template for the route. 18 // 19 // batchHandler: 20 // The System.Web.Http.Batch.HttpBatchHandler for handling batch requests. 21 public static IHttpRoute MapHttpBatchRoute(this HttpRouteCollection routes, string routeName, string routeTemplate, HttpBatchHandler batchHandler); 22 // 23 // 摘要: 24 // Maps the specified route template. 25 // 26 // 参数: 27 // routes: 28 // A collection of routes for the application. 29 // 30 // name: 31 // The name of the route to map. 32 // 33 // routeTemplate: 34 // The route template for the route. 35 // 36 // 返回结果: 37 // A reference to the mapped route. 38 public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate); 39 // 40 // 摘要: 41 // Maps the specified route template and sets default route values. 42 // 43 // 参数: 44 // routes: 45 // A collection of routes for the application. 46 // 47 // name: 48 // The name of the route to map. 49 // 50 // routeTemplate: 51 // The route template for the route. 52 // 53 // defaults: 54 // An object that contains default route values. 55 // 56 // 返回结果: 57 // A reference to the mapped route. 58 public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults); 59 // 60 // 摘要: 61 // Maps the specified route template and sets default route values and constraints. 62 // 63 // 参数: 64 // routes: 65 // A collection of routes for the application. 66 // 67 // name: 68 // The name of the route to map. 69 // 70 // routeTemplate: 71 // The route template for the route. 72 // 73 // defaults: 74 // An object that contains default route values. 75 // 76 // constraints: 77 // A set of expressions that specify values for routeTemplate. 78 // 79 // 返回结果: 80 // A reference to the mapped route. 81 public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, object constraints); 82 // 83 // 摘要: 84 // Maps the specified route template and sets default route values, constraints, 85 // and end-point message handler. 86 // 87 // 参数: 88 // routes: 89 // A collection of routes for the application. 90 // 91 // name: 92 // The name of the route to map. 93 // 94 // routeTemplate: 95 // The route template for the route. 96 // 97 // defaults: 98 // An object that contains default route values. 99 // 100 // constraints: 101 // A set of expressions that specify values for routeTemplate. 102 // 103 // handler: 104 // The handler to which the request will be dispatched. 105 // 106 // 返回结果: 107 // A reference to the mapped route. 108 public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, object constraints, HttpMessageHandler handler); 109 }
ps:博客内容是根据《ASP.NET Web API 2 框架揭秘》一书总结归纳写的,“2.3 两个路由系统的衔接”这一节因为时间问题就不写进去了,大家有空可以看看蒋大叔的这本书。