• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ASP.NETWebAPI框架研究Controller创建HttpController介绍

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

  对请求进行路由解析以及消息处理管道进行处理后,最后可以从HttpRequestMessage对象的属性字典中获取解析的路由数据,后边我们就可以根据其进行HttpController的创建,从前边几篇可知道,消息处理管道的末端即最后一个处理器HttpRoutingDispatcher会把消息派送给其一个内部处理器HttpControllerDispatcher进行HttpController的创建。这篇先介绍下HttpController,先熟悉下相关类,后边都会用到,后边会把这些类联系起来。

  关注点:

  • 熟悉下各类成员及关系,基本都有注释
  • 主要看ApiController抽象类的方法,项目中创建的控制器都继承它,很多方法都可以直接使用,核心逻辑方法是ExecuteAsync,创建控制器对象后,会调用ExecuteAsync方法,进行后续操作,由于还没讲控制器的创建,里边的逻辑以后再细说

一、涉及的类及源码分析

 

 

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;
            }
        }
public HttpControllerDescriptor ControllerDescriptor { get { return _controllerDescriptor; } set { if (value == null) { throw Error.PropertyNull(); } _controllerDescriptor = value; } }
public IHttpController Controller { get { return _controller; } set { if (value == null) { throw Error.PropertyNull(); } _controller = value; } } public HttpRequestMessage Request { get { return _request; } set { if (value == null) { throw Error.PropertyNull(); } _request = value; } } public HttpRequestContext RequestContext { get { return _requestContext; } set { if (value == null) { throw Error.PropertyNull(); } _requestContext = value; } } public IHttpRouteData RouteData { get { return _requestContext.RouteData; } set { if (value == null) { throw Error.PropertyNull(); } _requestContext.RouteData = 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上下文
  HttpConfiguration Configration 全局配置 同 HttpControllerContext
  HttpRequestMessage Request 请求消息 同 HttpControllerContext
  HttpRouteData  RouteData  路由解析数据 同 HttpControllerContext
  ModelstateDictionary Modelstate  包含其中的数据会被以Model绑定的形式绑定到目标Aotion方法的对应的参数

  UrlHelper Url  可以根据注册的HttpRoute和提供的路由变量生成—个完整的URL   
  IPrincipal User 返回当前线程的Principal ,前几篇中HttpServer在SendAsync方法执行过程中,如果当前线程中的当前线程的Principal为Null,创建一个空的GenericPrincipaI对象作为当前线程的匿名Principal。

  主要方法有以下几个:

  virtual Task<HttpRequsetMessage> ExecuteAsync(HttpControllerContext controllerContext,...)  实现IHttpController接口

  virtual void Initialize(HttpControllerContext  controllerContext) 受保护方法

  //资源回收

  void Dispose()
  virtual void Dispose(bool disposing)

  另外,特别注意,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 
                      

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
asp.net2.0中允许一次上传多个文件的设计发布时间:2022-07-10
下一篇:
中文VS2008安装ASP.NETMVC框架问题(没有MVC模板)发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap