在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
对请求进行路由解析以及消息处理管道进行处理后,最后可以从HttpRequestMessage对象的属性字典中获取解析的路由数据,后边我们就可以根据其进行HttpController的创建,从前边几篇可知道,消息处理管道的末端即最后一个处理器HttpRoutingDispatcher会把消息派送给其一个内部处理器HttpControllerDispatcher进行HttpController的创建。这篇先介绍下HttpController,先熟悉下相关类,后边都会用到,后边会把这些类联系起来。 关注点:
一、涉及的类及源码分析
1、IHttpController 我们创建的Web API项目中的所有的Controller最后都要继承该接口,如ProductController先继承ApiController,ApiController再继承IHttpController,接口定义如下,就一个方法ExecuteAsync方法,主要是一个参数HttpControllerContext,其具体见下一个类。
2、HttpControllerContext 表示执行HttpController的上下文,作为IHttpController接口的ExecuteAsync方法的参数,主要包含以下五个属性,前三个可以在构造函数里指定,也可以直接赋值 HttpConfiguration 全局配置 IHttpRouteData 解析的路由数据 HttpRequestMessage 表示当前请求 HttpControIlerDesciptor 描述HttpController HttpControIler 控制器对象 这个类没什么逻辑,只是在构造函数可以创建一个RequestContext _requestContext = new HttpRequestContext
{
Configuration = configuration,
RouteData = routeData
};
public class HttpControllerContext { private HttpRequestContext _requestContext; private HttpRequestMessage _request; private HttpControllerDescriptor _controllerDescriptor; private IHttpController _controller; public HttpControllerContext(HttpRequestContext requestContext, HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, IHttpController controller) { if (requestContext == null) { throw Error.ArgumentNull("requestContext"); } if (request == null) { throw Error.ArgumentNull("request"); } if (controllerDescriptor == null) { throw Error.ArgumentNull("controllerDescriptor"); } if (controller == null) { throw Error.ArgumentNull("controller"); } _requestContext = requestContext; _request = request; _controllerDescriptor = controllerDescriptor; _controller = controller; } public HttpControllerContext(HttpConfiguration configuration, IHttpRouteData routeData, HttpRequestMessage request) { if (configuration == null) { throw Error.ArgumentNull("configuration"); } if (routeData == null) { throw Error.ArgumentNull("routeData"); } if (request == null) { throw Error.ArgumentNull("request"); } //requestContext包含了Configuration和RouteData _requestContext = new HttpRequestContext { Configuration = configuration, RouteData = routeData }; _request = request; } public HttpControllerContext() { _requestContext = new HttpRequestContext(); } public HttpConfiguration Configuration { get { return _requestContext.Configuration; } set { if (value == null) { throw Error.PropertyNull(); } _requestContext.Configuration = value; } } 3、HttpControllerDescriptor 描述HttpController对象,封装了HttpController元数据,系统就是根据HttpControllerDescriptor创建Controller的;主要有以下三个属性,可以在构造函数指定,也可以直接赋值。 HttpConfiguration 全局配置 ControllerName 描述HttpCoutroller的控制器名称 ControllerType 描述HttpCoutroller的Type 还有个特殊的属性,类似HttpRequestMessage和HttpConfiguration类似的设计,可以添加任何对象到该属性 Properties 类型为ConcurrentDictionary(object, object) 另外,有以下主要方法: IHttpController CreateController(HttpRequestMessage request) 创建Controller核心方法,主要逻辑都在这 Collection<T> GetCustomAttributes<T>() where T: class 获取定义在控制器上的自定义属性 Collection<T> GetCustomAttributes(bool inherit)where T: class 同上 virtual Collection<IFilter> GetFilters() 获取定在在控制器上的过滤器 public class HttpControllerDescriptor { //附加任何对象到该字典属性 private readonly ConcurrentDictionary<object, object> _properties = new ConcurrentDictionary<object, object>(); private HttpConfiguration _configuration; private string _controllerName; private Type _controllerType; //缓存用 private object[] _attributeCache; private object[] _declaredOnlyAttributeCache; //后边文章介绍,解析出ControllerType时候会调用该构造函数创建HttpControllerDescriptor public HttpControllerDescriptor(HttpConfiguration configuration, string controllerName, Type controllerType) { if (configuration == null) { throw Error.ArgumentNull("configuration"); } if (controllerName == null) { throw Error.ArgumentNull("controllerName"); } if (controllerType == null) { throw Error.ArgumentNull("controllerType"); } _configuration = configuration; _controllerName = controllerName; _controllerType = controllerType; //构造函数里直接调用Initialize Initialize(); } //默认构造函数,单元测试用 public HttpControllerDescriptor() { } //默认构造函数,单元测试用 internal HttpControllerDescriptor(HttpConfiguration configuration) { Initialize(configuration); } /// <summary> /// 附加任何对象到该字典属性 /// </summary> public virtual ConcurrentDictionary<object, object> Properties { get { return _properties; } } public HttpConfiguration Configuration { get { return _configuration; } set { if (value == null) { throw Error.PropertyNull(); } _configuration = value; } } //控制器名称 public string ControllerName { get { return _controllerName; } set { if (value == null) { throw Error.PropertyNull(); } _controllerName = value; } } //控制器类型 public Type ControllerType { get { return _controllerType; } set { if (value == null) { throw Error.PropertyNull(); } _controllerType = value; } } //主要方法 根据HttpRequestMessage创建一个IHttpController public virtual IHttpController CreateController(HttpRequestMessage request) { if (request == null) { throw Error.ArgumentNull("request"); } //先从ServicesContainer获取默认的IHttpControllerActivator IHttpControllerActivator activator = Configuration.Services.GetHttpControllerActivator(); //调用IHttpControllerActivator的Create方法,创建,这个后一篇会说到 IHttpController instance = activator.Create(request, this, ControllerType); return instance; } //描述符对应的控制器定义的过滤器列表 public virtual Collection<IFilter> GetFilters() { return GetCustomAttributes<IFilter>(); } //获取泛型的自定义特性的集合,对应控制器上定义的 public virtual Collection<T> GetCustomAttributes<T>() where T : class { return GetCustomAttributes<T>(inherit: true); } //获取泛型的自定义特性的集合,对应控制器上定义的 public virtual Collection<T> GetCustomAttributes<T>(bool inherit) where T : class { object[] attributes; //反射获取自定义特性很慢,所以使用缓存_attributeCache,第二次开始,就直接从其获取 //inherit决定是否要去控制器类型继承结构中去找所有特性 if (inherit) { if (_attributeCache == null) { _attributeCache = ControllerType.GetCustomAttributes(inherit: true); } attributes = _attributeCache; } else { if (_declaredOnlyAttributeCache == null) { //是从ControllerType属性上去寻找特性的 _declaredOnlyAttributeCache = ControllerType.GetCustomAttributes(inherit: false); } attributes = _declaredOnlyAttributeCache; } return new Collection<T>(TypeHelper.OfType<T>(attributes)); } private void Initialize() { InvokeAttributesOnControllerType(this, ControllerType); } //先略过 private static void InvokeAttributesOnControllerType(HttpControllerDescriptor controllerDescriptor, Type type) { Contract.Assert(controllerDescriptor != null); if (type == null) { return; } InvokeAttributesOnControllerType(controllerDescriptor, type.BaseType); object[] attrs = type.GetCustomAttributes(inherit: false); foreach (object attr in attrs) { var controllerConfig = attr as IControllerConfiguration; if (controllerConfig != null) { var originalConfig = controllerDescriptor.Configuration; var controllerSettings = new HttpControllerSettings(originalConfig); controllerConfig.Initialize(controllerSettings, controllerDescriptor); controllerDescriptor.Configuration = HttpConfiguration.ApplyControllerSettings(controllerSettings, originalConfig); } } } } 4、ApiController WebAPI项目创建的HttpController类型默认继承ApiController,ApiController又继承自IHttpController和IDisposable HttpControllerContext ControllerContext 表示执行当前ApiController上下文 UrlHelper Url 可以根据注册的HttpRoute和提供的路由变量生成—个完整的URL 主要方法有以下几个: virtual Task<HttpRequsetMessage> ExecuteAsync(HttpControllerContext controllerContext,...) 实现IHttpController接口 virtual void Initialize(HttpControllerContext controllerContext) 受保护方法 //资源回收 void Dispose() 另外,特别注意,ApiController不能重复使用,每次请求都会使用一个新的HttpController来处理请求,ExecuteAsync方法的时候发现当前的ApiController已经处于“初始化”的状态,系统会直接抛出一个InvaIidationException异常。 public abstract class ApiController : IHttpController, IDisposable { private HttpActionContext _actionContext = new HttpActionContext(); private bool _initialized; //获取HttpConfiguration //setter 单元测试用 public HttpConfiguration Configuration { get { return ControllerContext.Configuration; } set { ControllerContext.Configuration = value; } } //获取HttpControllerContext //setter 单元测试用 public HttpControllerContext ControllerContext { get { // unit test only if (ActionContext.ControllerContext == null) { ActionContext.ControllerContext = new HttpControllerContext { RequestContext = new RequestBackedHttpRequestContext() }; } return ActionContext.ControllerContext; } set { if (value == null) { throw Error.PropertyNull(); } ActionContext.ControllerContext = value; } } //获取HttpRequestMessage //setter 单元测试用 public HttpActionContext ActionContext { get { return _actionContext; } set { if (value == null) { throw Error.PropertyNull(); } _actionContext = value; } } //在模型绑定之后获取ModelState,绑定之前是空的,模型绑定以后再说 public ModelStateDictionary ModelState { get { return ActionContext.ModelState; } } //获取HttpRequestMessage //setter 单元测试用 public HttpRequestMessage Request { get { return ControllerContext.Request; } set { if (value == null) { throw Error.PropertyNull(); } HttpRequestContext contextOnRequest = value.GetRequestContext(); HttpRequestContext contextOnController = RequestContext; if (contextOnRequest != null && contextOnRequest != contextOnController) { // Prevent unit testers from setting conflicting requests contexts. throw new InvalidOperationException(SRResources.RequestContextConflict); } ControllerContext.Request = value; value.SetRequestContext(contextOnController); RequestBackedHttpRequestContext requestBackedContext = contextOnController as RequestBackedHttpRequestContext; if (requestBackedContext != null) { requestBackedContext.Request = value; } } } //获取HttpRequestContext //setter 单元测试用 public HttpRequestContext RequestContext { get { return ControllerContext.RequestContext; } set { if (value == null) { throw Error.PropertyNull(); } HttpRequestContext oldContext = ControllerContext.RequestContext; HttpRequestMessage request = Request; if (request != null) { HttpRequestContext contextOnRequest = request.GetRequestContext(); if (contextOnRequest != null && contextOnRequest != oldContext && contextOnRequest != value) { // Prevent unit testers from setting conflicting requests contexts. throw new InvalidOperationException(SRResources.RequestContextConflict); } request.SetRequestContext(value); } ControllerContext.RequestContext = value; } } //获取UrlHelper用来对其他APIS生成URLS //setter 单元测试用 public UrlHelper Url { get { return RequestContext.Url; } set { RequestContext.Url = value; } } //获取或设置当前请求的Principal //setter 单元测试用 public IPrincipal User { get { return RequestContext.Principal; } set { RequestContext.Principal = value; } } //主要方法,创建控制器对象后,会调用ExecuteAsync方法,进行后续操作,由于还没讲控制器的创建,里边的逻辑以后再细说 public virtual Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken) { if (_initialized) { // 如果已经创建过该实例,就抛出异常,一个控制器实例,多次请求不能重复使用 throw Error.InvalidOperation(SRResources.CannotSupportSingletonInstance, typeof(ApiController).Name, typeof(IHttpControllerActivator).Name); } Initialize(controllerContext); if (Request != null) { //先注册到待销毁集合,待请求完成后一起销毁改控制器实例 Request.RegisterForDispose(this); } HttpControllerDescriptor controllerDescriptor = controllerContext.ControllerDescriptor; ServicesContainer controllerServices = controllerDescriptor.Configuration.Services; //选择Action HttpActionDescriptor actionDescriptor = controllerServices.GetActionSelector().SelectAction(controllerContext); ActionContext.ActionDescriptor = actionDescriptor; if (Request != null) { Request.SetActionDescriptor(actionDescriptor); } FilterGrouping filterGrouping = actionDescriptor.GetFilterGrouping(); //ActionFilters IActionFilter[] actionFilters = filterGrouping.ActionFilters; //身份认证过滤器 IAuthenticationFilter[] authenticationFilters = filterGrouping.AuthenticationFilters; //授权过滤器 IAuthorizationFilter[] authorizationFilters = filterGrouping.AuthorizationFilters; //ExceptionFilters IExceptionFilter[] exceptionFilters = filterGrouping.ExceptionFilters; IHttpActionResult result = new ActionFilterResult(actionDescriptor.ActionBinding, ActionContext, controllerServices, actionFilters); if (authorizationFilters.Length > 0) { result = new AuthorizationFilterResult(ActionContext, authorizationFilters, result); } if (authenticationFilters.Length > 0) { result = new AuthenticationFilterResult(ActionContext, this, authenticationFilters, result); } if (exceptionFilters.Length > 0) { IExceptionLogger exceptionLogger = ExceptionServices.GetLogger(controllerServices); IExceptionHandler exceptionHandler = ExceptionServices.GetHandler(controllerServices); result = new ExceptionFilterResult(ActionContext, exceptionFilters, exceptionLogger, exceptionHandler, result); } //执行IHttpActionResult的ExecuteAsync return result.ExecuteAsync(cancellationToken); } //验证entity,并把验证错误添加到ModelState public void Validate<TEntity>(TEntity entity) { Validate(entity, keyPrefix: String.Empty); } //验证entity,并把验证错误添加到ModelState public void Validate<TEntity>(TEntity entity, string keyPrefix) { if (Configuration == null) { throw Error.InvalidOperation(SRResources.TypePropertyMustNotBeNull, typeof(ApiController).Name, "Configuration"); } IBodyModelValidator validator = Configuration.Services.GetBodyModelValidator(); if (validator != null) { ModelMetadataProvider metadataProvider = Configuration.Services.GetModelMetadataProvider(); Contract.Assert(metadataProvider != null, "GetModelMetadataProvider throws on null."); validator.Validate(entity, typeof(TEntity), metadataProvider, ActionContext, keyPrefix); } } //创建一个400 Bad Request,项目中的Controller里可以直接使用 protected internal virtual BadRequestResult BadRequest() { return new BadRequestResult(this); } //根据message 创建一个400 Bad Request,项目中的Controller里可以直接使用 protected internal virtual BadRequestErrorMessageResult BadRequest(string message) { return new BadRequestErrorMessageResult(message, this); } //根据指定的modelState创建一个 400 Bad Request. protected internal virtual InvalidModelStateResult BadRequest(ModelStateDictionary modelState) { return new InvalidModelStateResult(modelState, this); } //创建一个 409 Conflict protected internal virtual ConflictResult Conflict() { return new ConflictResult(this); } /// <summary>创建一个内容协商结果响应</summary> /// <typeparam name="T">主体内容中的数据类型</typeparam> /// <param name="statusCode">响应状态码</param> /// <param name="value">在主体中要协商和格式化的数据</param> /// <returns>A <see cref="NegotiatedContentResult{T}"/> with the specified values.</returns> protected internal virtual NegotiatedContentResult<T> Content<T>(HttpStatusCode statusCode, T value) { return new NegotiatedContentResult<T>(statusCode, value, this); } /// <summary>创建一个指定格式化的内容响应</summary> /// <typeparam name="T">主体内容中的数据类型</typeparam> /// <param name="statusCode">响应状态码</param> /// <param name="value">在主体中要协商和格式化的数据</param> /// <param name="formatter">格式化器</param> /// <returns>A <see cref="FormattedContentResult{T}"/> with the specified values.</returns> protected internal FormattedContentResult<T> Content<T>(HttpStatusCode statusCode, T value, MediaTypeFormatter formatter) { return Content(statusCode, value, formatter, (MediaTypeHeaderValue)null); } /// <summary>创建一个指定媒体类型的格式化的内容响应</summary> /// <typeparam name="T">主体内容中的数据类型</typeparam> /// <param name="statusCode">响应状态码</param> /// <param name="value">在主体中要协商和格式化的数据</param> /// <param name="formatter">格式化器</param> /// <param name="mediaType">媒体类型</param> /// <returns>A <see cref="FormattedContentResult{T}"/> with the specified values.</returns> protected |
请发表评论