Action的激活大概可以分为如下两个步骤:Action对应方法的调用,执行结果的协商。在WebAPI中由HttpActionInvoker(System.Web.Http.Controllers)进行Action的执行。
public interface IHttpActionInvoker { Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, CancellationToken cancellationToken); }
HttpActionInvoker也是"标准化组件",,WebAPI的默认实现为:ApiControllerActionInvoker (System.Web.Http.Controllers,ApiControllerActionInvoker的实现中Action方法的调用实际上交由HttpActionDescriptor的ExecuteAsync的方法去执行,内容协商交由ContentNegotiator处理。
Action的执行
ActionExecutor
ReflectedHttpActionDescriptor在ExecuteAsync方法实现中把Action的执行又交给了它的内部类ActionExecutor
public class ReflectedHttpActionDescriptor : HttpActionDescriptor { public abstract Task<object> ExecuteAsync(HttpControllerContext controllerContext, IDictionary<string, object> arguments, CancellationToken cancellationToken); }
在ReflectedHttpActionDescriptor其实又将Action的执行交由其内部类ActionExecutor执行。
public override Task<object> ExecuteAsync(HttpControllerContext controllerContext, IDictionary<string, object> arguments, CancellationToken cancellationToken) { if (controllerContext == null) { throw Error.ArgumentNull("controllerContext"); } if (arguments == null) { throw Error.ArgumentNull("arguments"); } if (cancellationToken.IsCancellationRequested) { return TaskHelpers.Canceled<object>(); } try { object[] argumentValues = PrepareParameters(arguments, controllerContext); return _actionExecutor.Value.Execute(controllerContext.Controller, argumentValues); } catch (Exception e) { return TaskHelpers.FromError<object>(e); } }
ActionExecutor对于Action的执行采用的是表达示树的方式,这个后续我会写一个Action执行的demo。
内容协商(结果序列化)
在之前的参数绑定一文中讲到参数的反序列化是根据请求头信息中的Content-Type获取不同的序列化对象,在对结果进行序列化的过程中也是如此,不过获取的头信息是Accept。
对于Action的返回结果大概有如下几种情况:void,,object,ActionResult,HttpResponseMessage。对于HttpResponseMessage因为整个HttpMessageHandler的返回值就是HttpResponseMessage,所以可以直接返回.对于IActionResult,它本身有ExecuteAsync方法(返回结果)可以返回HttpResponseMessage。不同的ActionResult会用不用的序列化策略.JsonResult<T>是直接将结果序列化Json形式。对于 OkNegotiatedContentResult类型,因为它不像JsonResult<T>一样有明确的序列化方式,所以这个时候就要根据客户端请求进行获取序列化。这种方式同样适用于object与void类型的返回值,但这个具体的实现由HttpResponseMessage的扩展方法CreateResponse完成。
ContentNegotiator
IContentNegotiator(System.Net.Http.Formatting)在WebAPI中也是"标准化组件",它的默认实现为DefaultContentNegotiator(System.Net.Http.Formatting)。
public interface IContentNegotiator { ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters); }
IContentNegotiator只有一个Negotiator方法,该方法的返回值ContentNegotiationResult 包含了MedioType信息与获取到的序列化对象。
public class ContentNegotiationResult { public MediaTypeFormatter Formatter { get; set; } public MediaTypeHeaderValue MediaType { get; set; } }
在demo中我自定义了一个MyContentNegotiationResult<T>用来展示内容协商的具体处理逻辑。
源码
Github: https://github.com/BarlowDu/WebAPI (API_12)