[整理]ASP.NET WEB API 2学习

时间:2023-03-09 18:55:31
[整理]ASP.NET WEB API 2学习

目录

1 快速入门

入门最好的资料就是看官方的文章介绍和实例,以获得最新的知识的更新。

当然,还有国人翻译的http://aehyok.com/Blog/Detail/67.html

1.1实例

1.1.1初识WEB API 2

http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api

和WEB API 相比,结构上大致没什么区别。

1.1.2 Action Results 的改变

http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/action-results

在原有的基础上新增了异步处理机制,对应不同的IHttpActionResult的具体实现。

  • void
  • HttpResponseMessage
  • IHttpActionResult(WEB API 2新增)
  • Some other type

1.1.2.1 IHttpActionResult

IHttpActionResult 定义一个用于以异步方式创建 System.Net.Http.HttpResponseMessage 的命令的借口。

在System.Web.Http.Results命名空间(System.Web.Http.dll)下,可以找到一些常用的IHttpActionResult的实现,异步创建不同HttpStatusCode的HttpResponseMessage。

1.1.2.2 ApiController

ApiController类中,也同时也对应新增了返回IHttpActionResult子类的快捷方法,如OK()方法,会返回OKResult对象等。当然,我们也可以自定义实现IHttpActionResult,满足不同的HttpStatusCode的需要。

1.1.3 路由的新增特性

http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

http://www.asp.net/web-api/overview/web-api-routing-and-actions/create-a-rest-api-with-attribute-routing

通过新增的RoutePrefixAttribute、RouteAttribute 、IHttpRouteConstraint,可以灵活的配置不同层次的路由及其路由约束,通过直接对外暴露API(无需匹配WebApiConfig里的routetemplate),以满足不同场景下的需要。

1.1.3.1 RoutePrefixAttribute

1.1.3.2 RouteAttribute

1.1.3.3 IHttpRouteConstraint

在System.Web.Http.Routing.Constraints命名空间下,默认提供了一系列的路由约束IHttpRouteConstraint的具体实现,如AlphaRouteConstraint、DateTimeRouteConstraint等。

当然,可以通过自定义路由约束,实现路由匹配。自定义的IHttpRouteConstraint,为了能运行自定义的IHttpRouteConstraint,必须先进行注册,通过HttpConfiguration.MapHttpAttributeRoutes来注册新的特性路由解析器

1.1.3.4 DefaultInlineConstraintResolver

1.1.4 消息管道的变化

1.1.4.1 HttpMessageHandler

1.1.4.2 DelegatingHandler

1.1.4.3 HttpServer

HttpRoutingDispatcher

1.2 了解更多

1.2.1 MSDN

MSDN关于WEB API 2各个方面的官方指导

https://msdn.microsoft.com/zh-cn/library/dn448365(v=vs.108).aspx

1.2.2 HTTP Message Lifecyle

WEB API 2中独立于IIS的消息管道是其整个核心,其整个消息生命周期在该PDF里有非常详细的说明,从图中可以看到在整个消息生命周期里可以自定义扩展的地方,这个是非常重要的,值得关注的。

http://www.asp.net/media/4071077/aspnet-web-api-poster.pdf

http://www.asp.net/web-api/overview/advanced/http-message-handlers

HttpRequestMessage

在System.Net.Http.dll中的HttpRequestMessage类,是对一个实际的HTTP 请求消息(HTTP请求报文)的包装。

HttpRequestMessage包含了HttpContent、HttpHeaders、HttpMethod和Version这几个类型的属性来对应HTTP请求报文的报文主题,报头,HTTP方法和HTTP协议版本(默认http 1.1版本)

还有一个public IDictionary<string, object> Properties { get; }的属性,HTTP 请求的属性集,是非常重要的。在Web API 中,是不存在HttpContext上下文对象的,而类似的上下文对象会被存储在该Properties 属性对象里,还有,RouteData也是。

MS内置的键值主要都在System.Web.Http.Hosting.HttpPropertyKeys类的字段列表中。

HttpRequestContext

这个类就是类似ASP.NET中的HttpContext的类型,在整个消息处理链中,通过存储在前面的HttpRequestMessage对象的Properties的属性列表里,我们可以在消息处理链中的任一Handler中来获取这一上下文对象,通过System.Web.Http.Hosting.HttpPropertyKeys类的键值名称和System.Net.Http.HttpRequestMessageExtensions静态类的多种扩展方法来方便我们访问不同的属性对象。

HttpServer

根据PDF周期里的图所示,由于HttpServer是整个消息处理链的头(HttpMessageHandler链),于是好奇HttpServer是如何被创建的。查看了源码,分2种情况,一种是基于WebHost,另一种基于SelfHost。分别对应的GlobalConfiguration(System.Web.Http.WebHost.dll的System.Web.Http命名空间下)类和WebApiAppBuilderExtensions(System.Web.Http.Owin.dll的Owin命名空间下),可以找到创建HttpServer相关的代码。不过在System.Web.Http.SelfHost.dll 中存在一个HttpSelfHostServer,继承HttpServer的子类。

HttpServer的Initialize方法中,调用 InnerHandler = HttpClientFactory.CreatePipeline(_dispatcher, _configuration.MessageHandlers);来生成整个管道,自此,整个消息管道的头HttpServer、尾HttpRoutingDispatcher和以及整个链HttpMessageHandlers就准备好了。

从静态方法HttpClientFactory.CreatePipeline可以明显看到,整个消息处理HttpMessageHandler列表通过其innerHandler串联起来,成为消息处理链。

HttpRoutingDispatcher

整个消息处理链的尾部,系统自动创建,直接继承HttpMessageHandler,而非DelegatingHandler,通过其SendAsync方法可以发现HttpRequestMessage对象的IHttpRouteData类型的RouteData属性的获取,主要是通过其public IDictionary<string, object> Properties { get; }属性,指定键值获取的。

protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

{

// Lookup route data, or if not found as a request property then we look it up in the route table

IHttpRouteData routeData = request.GetRouteData();

if (routeData == null)

{

routeData = _configuration.Routes.GetRouteData(request);

if (routeData != null)

{

request.SetRouteData(routeData);

}

}

  //...

}

从以上的HttpRoutingDispatcher的SendAsync方法代码可以看出,HttpRoutingDispatcher只是一个代理的作用,不做实际的消息处理,

但是会进行路由的匹配,从而找到对应的IHttpRoute对象,并通过调用IHttpRoute对象的Handler属性(HttpMessageHandler类型)来执行最终的消息处理,如果该Handler不存在,则使用HttpRoutingDispatcher类中默认的一个HttpMessageHandler类型的实例defaultHandler来接管处理。

这个defaultHander实际上是HttpControllerDispatcher类型的,同样是直接继承了HttpMessageHandler抽象类,在其重载方法SendAsync中,会创建根据当前路由来创建最映射到的IHttpController对象实例,最终映射到其方法,返回一个请求HttpMessageResponse对象.

HttpControllerDispatcher

该对象是最终Controller选择调度的地方,同时生成HttpControllerContext控制器上下文对象和HttpControllerDescriptor对象,最后执行找到的IHttpController对象的ExecuteAsync方法。

如果该IHttpController创建失败,直接返回NotFound的HttpMessageResponse消息响应对象。

可以看出,HttpControllerDescriptor.CreateController(request)是实际创建IHttpController对象实例的方法。

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpControllerContext controllerContext = null; //...
HttpControllerDescriptor controllerDescriptor = ControllerSelector.SelectController(request); //...
IHttpController controller = controllerDescriptor.CreateController(request); //...
controllerContext = CreateControllerContext(request, controllerDescriptor, controller);
return await controller.ExecuteAsync(controllerContext, cancellationToken);
}

HttpControllerContext

HttpControllerDescriptor

让我们看看HttpControllerDescriptor到底是如何创建最终匹配的IHttpController的,追朔到具体的代码,IHttpControllerActivator,看名字应该是一个根据具体的Controller的Type类型,通过反射创建IHttpController实例的类。

public virtual IHttpController CreateController(HttpRequestMessage request)
{
if (request == null)
{
throw Error.ArgumentNull("request");
} // Invoke the controller activator
IHttpControllerActivator activator = Configuration.Services.GetHttpControllerActivator();
IHttpController instance = activator.Create(request, this, ControllerType);
return instance;
}

DefaultHttpControllerActivator

追根溯源,到底IHttpController是在哪里生成的,继续在HttpControllerDescriptor.CreateController的方法里查找,

在命名空间System.Web.Http.Dispatcher下,有DefaultHttpControllerActivator类,继承IHttpControllerActivator接口,

因为是用到反射创建Controller,理所当然,有个缓存的私有属性private Tuple<HttpControllerDescriptor, Func> _fastCache;来尽量减少放射的次数。

1.3 OWIN

我们可以使用OWIN 自宿主(SelfHost) ASP.NET WebAPI 2应用。

http://www.asp.net/web-api/overview/hosting-aspnet-web-api/use-owin-to-self-host-web-api

//TODO

1.4 获取MS的知识更新

channel9会时常更新新的技术教程,正巧发现这2天有WEB API Design的视频更新,目前有6集。

http://channel9.msdn.com/Series/Web-API-Design/01

2.进阶

2.1 通过WEB API 2的源码学习

通过源码学习是最好的方式

http://aspnetwebstack.codeplex.com/

2.2 优秀开源项目的学习

//TODO

3 实际开发

3.1 WCF and ASP.NET Web API

WCF和WEB API的抉择

https://msdn.microsoft.com/en-us/library/jj823172.aspx

3.2 WP移动开发

移动开发是目前整个开发的趋势,迫切地需要开始有针对性的在移动开发方面做一些实践。同时WEB API 又非常适合移动端的数据交互。

要注意的是,必须在window 8操作系统下, 才可以开发WP8.0+应用。

http://www.asp.net/web-api/overview/mobile-clients/calling-web-api-from-a-windows-phone-8-application

http://azure.microsoft.com/en-us/documentation/articles/mobile-services-dotnet-backend-windows-store-dotnet-leaderboard/?WT.mc_id=zumo_aspnet&rnd=1

http://blogs.msdn.com/b/webdev/archive/2013/07/19/writing-web-api-client-code-for-multiple-platforms-using-portable-libraries.aspx

3.3 WEB API与SignalR

Web API与SignalR一起同为构建Service的框架。Web API负责构建http常规服务,而SingalR主要负责的是构建实时服务,例如股票,聊天室,在线游戏等实时性要求比较高的服务。