ASP.NET WebAPI 08 Message,HttpConfiguration,DependencyResolver

Message

WebAPI作为通信架构必定包含包含请求与响应两个方法上的报文,在WebAPI它们分别是HttpRequestMessage,HttpResponseMessage。对于HttpResponseMessage之前在WebAPI返回结果中有应用。

HttpRequestMessage

请求报文包含请求地址(RequestUri),请求方法(Method),头信息(Headers),报文信息(Content)以及Http版本(Versions)

    public class HttpRequestMessage : IDisposable
    {
        public HttpRequestMessage();
        public HttpRequestMessage(HttpMethod method, string requestUri);
        public HttpRequestMessage(HttpMethod method, Uri requestUri);
        public HttpContent Content { get; set; }
        public HttpRequestHeaders Headers { get; }
        public HttpMethod Method { get; set; }
        public IDictionary<string, object> Properties { get; }
        public Uri RequestUri { get; set; }
        public Version Version { get; set; }
        public void Dispose();
        protected virtual void Dispose(bool disposing);
        public override string ToString();
}

另外,WebAPI提供了一个类型为IDictionary<string,object>的属性Properties。我们可以将做任意对象作为附加属性添加到HttpRequestMessage.

HttpResponseMessage

请求报文包含状态码(StatusCode),原因短句(ReasonPhrase),头信息(Headers),报文信息(Content)以及Http版本(Versions)

    public class HttpRequestMessage : IDisposable
    {
        public HttpRequestMessage();
        public HttpRequestMessage(HttpMethod method, string requestUri);
        public HttpRequestMessage(HttpMethod method, Uri requestUri);
        public HttpContent Content { get; set; }
        public HttpRequestHeaders Headers { get; }
        public HttpMethod Method { get; set; }
        public IDictionary<string, object> Properties { get; }
        public Uri RequestUri { get; set; }
        public Version Version { get; set; }
        public void Dispose();
        protected virtual void Dispose(bool disposing);
        public override string ToString();
}

HttpConfiguration

HttpConfiguration在WebAPI大概有如下几个作用:

  1. 设置通信管道
  2. 存储全局信息(比如Filter,Route,Formatter)
  3. 提供一个Ioc架构,用于WebAPI的扩展
    public class HttpConfiguration : IDisposable
    {
        public HttpConfiguration();
        public HttpConfiguration(HttpRouteCollection routes);
        public IDependencyResolver DependencyResolver { get; set; }
        public HttpFilterCollection Filters { get; }
        public MediaTypeFormatterCollection Formatters { get; }
        public IncludeErrorDetailPolicy IncludeErrorDetailPolicy { get; set; }
        public Action<HttpConfiguration> Initializer { get; set; }
        public Collection<System.Net.Http.DelegatingHandler> MessageHandlers { get; }
        public ParameterBindingRulesCollection ParameterBindingRules { get; internal set; }
        public ConcurrentDictionary<object, object> Properties { get; }
        public HttpRouteCollection Routes { get; }
        public ServicesContainer Services { get; internal set; }
        public string VirtualPathRoot { get; }
        public void Dispose();
        protected virtual void Dispose(bool disposing);
        public void EnsureInitialized();
    }

对于第1 点我们在每6篇已经用到。第2点后面会陆续讲到,本篇只重点讲下第3点。这一功能主要是通过ServicesContainer来完成,即HttpConfiguration中的Services属性。

WebAPI对ServicesContainer的提供的派生类是DefaultServices,在DefaultServices,包含了两种依赖注入方法:1,单一派生类型注入(multi),2,多派生类型注入(single),即在注入派生类型的数量有区别。比如在获取url参数的时候有QueryString,RouteData两种方式,而这两种方式是通过QueryStringValueProvider与RouteDataValueProvider两种类型来实现的(实际在DefaultServices注入是这人两个类对应的Factory类),这两种类型属于平行关系,所以这个时候能需要采用multi方法注入。

这些类型都是在DefaultServces的构造中注入的。

    public class DefaultServices : ServicesContainer
    {
        protected DefaultServices();
        public DefaultServices(HttpConfiguration configuration);
        protected override void ClearSingle(Type serviceType);
        public override object GetService(Type serviceType);
        protected override List<object> GetServiceInstances(Type serviceType);
        public override IEnumerable<object> GetServices(Type serviceType);
        public override bool IsSingleService(Type serviceType);
        protected override void ReplaceSingle(Type serviceType, object service);
        protected override void ResetCache(Type serviceType);
}
    public abstract class ServicesContainer : IDisposable
    {
        protected ServicesContainer();
        public void Add(Type serviceType, object service);
        public void AddRange(Type serviceType, IEnumerable<object> services);
        public virtual void Clear(Type serviceType);
        public virtual void Dispose();
        public int FindIndex(Type serviceType, Predicate<object> match);
        public abstract object GetService(Type serviceType);
        public abstract IEnumerable<object> GetServices(Type serviceType);
        public void Insert(Type serviceType, int index, object service);
viceType, int index, IEnumerable<object> services);
        public abstract bool IsSingleService(Type serviceType);
        public bool Remove(Type serviceType, object service);
        public int RemoveAll(Type serviceType, Predicate<object> match);
        public void RemoveAt(Type serviceType, int index);
        public void Replace(Type serviceType, object service);
        public void ReplaceRange(Type serviceType, IEnumerable<object> services);
    }

ServicesContainer只提供的了替换与获取的公共方法。因为ServicesContainer只提供了WebAPI中的标准组件,并不想作为一个公共的Ioc容器,而这些标准的组件是WebAPI进行扩展的基础。

下面我写的四个Action分别是获取所有multiServices,获取所有singleServices,向multiServices中添加一个自定义的ValueProviderFactory,向singleServices中添加自定义的IExceptionHandler.

        public Dictionary<Type, List<Type>> GetAllMultiServices()
        {
            Dictionary<Type, List<Type>> result = new Dictionary<Type, List<Type>>();
            FieldInfo field = RequestContext.Configuration.Services.GetType().GetField("_defaultServicesMulti",
                BindingFlags.NonPublic|BindingFlags.Instance);
            Dictionary<Type, List<object>> multiServices = (Dictionary<Type, List<object>>)field.GetValue(RequestContext.Configuration.Services);
            foreach (var s in multiServices)
            {
                List<Type> items = new List<Type>();
                foreach (var item in s.Value) {
                    items.Add(item.GetType());
                }
                result[s.Key] = items;
            }
            return result;
        }

        public Dictionary<Type, Type> GetAllSingleServices()
        {
            Dictionary<Type, Type> result = new Dictionary<Type, Type>();
            FieldInfo field = RequestContext.Configuration.Services.GetType().GetField("_defaultServicesSingle",
                BindingFlags.NonPublic | BindingFlags.Instance);
            Dictionary<Type, object> services = (Dictionary<Type, object>)field.GetValue(RequestContext.Configuration.Services);
            foreach (var s in services)
            {

                result.Add(s.Key, s.Value==null?null:s.Value.GetType());
            }
            return result;
        }

        public Dictionary<Type, List<Type>> AddMultiService()
        {
            List<ValueProviderFactory> valueProviderFactories=new List<ValueProviderFactory>(){
            new QueryStringValueProviderFactory(),
            new RouteDataValueProviderFactory(),
            new MyValueProviderFactory()
            };
            RequestContext.Configuration.Services.ReplaceRange(typeof(ValueProviderFactory), valueProviderFactories);
            return GetAllMultiServices();
        }

        public Dictionary<Type, Type> ReplaceSingleService()
        {
            RequestContext.Configuration.Services.Replace(typeof(IExceptionHandler), new MyExceptionHandler());
            return GetAllSingleServices();
        }

因为ServicesContainer中的类型注入都是固定的,所以WebAPI给ServicesContainer扩展了一组获取Service的方法

    public static class ServicesExtensions
    {
        public static IHttpActionInvoker GetActionInvoker(this ServicesContainer services);
        public static IHttpActionSelector GetActionSelector(this ServicesContainer services);
        public static IActionValueBinder GetActionValueBinder(this ServicesContainer services);
        public static IApiExplorer GetApiExplorer(this ServicesContainer services);
        public static IAssembliesResolver GetAssembliesResolver(this ServicesContainer services);
        public static IBodyModelValidator GetBodyModelValidator(this ServicesContainer services);
        public static IContentNegotiator GetContentNegotiator(this ServicesContainer services);
        public static IDocumentationProvider GetDocumentationProvider(this ServicesContainer services);
        public static IExceptionHandler GetExceptionHandler(this ServicesContainer services);
        public static IEnumerable<IExceptionLogger> GetExceptionLoggers(this ServicesContainer services);
        public static IEnumerable<System.Web.Http.Filters.IFilterProvider> GetFilterProviders(this ServicesContainer services);
        public static IHostBufferPolicySelector GetHostBufferPolicySelector(this ServicesContainer services);
        public static IHttpControllerActivator GetHttpControllerActivator(this ServicesContainer services);
        public static IHttpControllerSelector GetHttpControllerSelector(this ServicesContainer services);
        public static IHttpControllerTypeResolver GetHttpControllerTypeResolver(this ServicesContainer services);
        public static IEnumerable<System.Web.Http.ModelBinding.ModelBinderProvider> GetModelBinderProviders(this ServicesContainer services);
        public static ModelMetadataProvider GetModelMetadataProvider(this ServicesContainer services);
        public static IEnumerable<ModelValidatorProvider> GetModelValidatorProviders(this ServicesContainer services);
        public static ITraceManager GetTraceManager(this ServicesContainer services);
        public static ITraceWriter GetTraceWriter(this ServicesContainer services);
        public static IEnumerable<System.Web.Http.ValueProviders.ValueProviderFactory> GetValueProviderFactories(this ServicesContainer services);
    }

在ASP.NET WebAPI中有一个GlobalConfiguration,其实它并不是WebAPI的一部分。WebAPI只是一个独立的框架。它需要寄宿在别的应用程序下才能运行。寄宿模式则分为两种WebHost,SelfHost,WebHost是针对Web程序的寄宿。因为本系列只讨论ASP.Net下的WebAPI,所以只简单讲一下WebHost模式。

ASP.NET WebAPI中引用了程序集System.Web.Http.WebHost,GlobalConfiguration就在该程序集下.它包含了一个HttpConfiguration属性.还一个配置HttpConfiguration的方法

另外还有一个HttServer

另外在ApiController的很多属性都能找到HttpConfiguraiton
Configuration

ControllerContext.Configuration

RequestContext.Configuration

这些HttpConfiguration都来自对GlobalConfiguration.Configuration的引用.

DependencyResolver

WebAPI为我们提供了一个Ioc框架,即DependencyResolver

public interface IDependencyResolver : IDependencyScope, IDisposable

 { 

IDependencyScope BeginScope(); 

 } 

public interface IDependencyScope : IDisposable

 { 

object GetService(Type serviceType); 

IEnumerable<object> GetServices(Type serviceType); 

 }

IDependencyResolver也继承了IDependencyScope,所以我们可以将IDependencyScope视为依赖的上下文.

在WebAPI中DependencyResolver并没有像其它组件一样注册在ServicesContainer中,而是直接注册在HttpConfiguration中(DependencyResolver属性).

别个HttpRequestMessage中也有一扩展方法GetDependencyScope来获取DependencyScope,该方法获取的是HttpRequestMessage的Properties的DependencyResolver,这里的DependencyResolver也来自HttpConfiguration.

在WebAPI中也定义了一个EmptyResolver,它只是一个空的Resolver,所以在WebAPI默认就是采用直接反射方式.

时间: 2024-10-22 20:33:37

ASP.NET WebAPI 08 Message,HttpConfiguration,DependencyResolver的相关文章

Autofac 注入Asp.Net Webapi And MVC

Autofac具有解耦.管理生命周期等等好处,本文仅仅实现一个简单的控制器注入. 1.新建Asp.Net WebApi  应用程序(我用的是VS2013). 2.通过Nuget下载如下三个packet. 1 <package id="Autofac" version="3.5.2" targetFramework="net45" /> 2 <package id="Autofac.Mvc5" version=

Enable Cross-Origin Requests in Asp.Net WebApi 2[Reprint]

Browser security prevents a web page from making AJAX requests to another domain. This restriction is called the same-origin policy, and prevents a malicious site from reading sentitive data from another site. However, sometimes you might want to let

Asp.net WebAPI 单元测试

现在Asp.net webapi 运用的越来越多,其单元而是也越来越重要.一般软件开发都是多层结构,上层调用下层的接口,而各层的实现人员不同,一般大家都只写自己对应单元测试.对下层的依赖我们通过IOC来做.首先看我们的Controller定义及实现 public class ArticlesController : ApiController { private IArticleService _articleService; public ArticlesController(IArticle

重温ASP.NET WebAPI(二)进阶

介绍 本文为个人对WebApi的回顾无参考价值. 本文内容: Rest和UnitOfWork 创建WebAPi的流程 IOC-Unity的使用 MEF 自定义URL Base认证和Token自定义权限 日志NLog OData的使用 Owin自宿主的使用 代码地址:https://github.com/OtherRuan/Review-Serials WebApi的几点特性 WebApi 提供了几点特性: 1. 自动匹配HTTP方法 GetMethod(), 惯例上会直接匹配Get的http方法

[转]在ASP.NET WebAPI 中使用缓存【Redis】

初步看了下CacheCow与OutputCache,感觉还是CacheOutput比较符合自己的要求,使用也很简单 PM>Install-Package Strathweb.CacheOutput.WebApi2 基础使用 CacheOutput特性 [Route("get")] [CacheOutput(ClientTimeSpan = 60, ServerTimeSpan = 60)] public IEnumerable<string> Get() { retu

asp.net webapi 使用小结

一星期前公司用webapi处理一些事情,自己总结一下用法. 1.创建一个空的webapi会默认有一下几个方法. public class ValueController : ApiController { // GET api/value public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } // GET api/value/5 public st

使用ASP.Net WebAPI构建REST服务(二)——路由

REST并没有像传统的RPC服务那样显式指定了服务器函数的访问路径,而是将URL根据一定的规则映射为服务函数入口,这个规则就称之为路由.Asp.Net WebAPI的路由方式和Asp.Net MVC是相同的,它支持两种路由方式,传统的路由映射和特性路由. 路由规则WebApiConfig.cs中定义,它的默认内容如下: publicstaticclassWebApiConfig    {        publicstaticvoid Register(HttpConfiguration con

asp.net webapi 自托管插件式服务

webapi问世已久,稀里糊涂的人哪它都当mvc来使,毕竟已mvc使用级别的经验就可以应对webapi. webapi和mvc在asp.net5时代合体了,这告诉我们,其实 它俩还是有区别的,要不现在也不会取两个名字,但是由于本人归纳总结能力较差,各种不同也无法一一列出了. 在webapi中 HelpPage是个突出而又实用的东西,它尼玛会把我们code中的注释生成xml,然后以web页面的方式把接口文档展示出来,这尼玛无形就下岗一批文案了,以社会责任感角度来讲,ms的这个HelpPage挺不地

细说Asp.Net WebAPI消息处理管道

我们在开发完Asp.Net WebAPI程序后,可以使用WebHost寄宿方式或者SelfHost寄宿方式来部署Asp.Net WebAPI.所谓WebHost寄宿就是通过Asp.Net来实现:所谓SelfHost就是可以通过控制台.WinForm.WPF等方式寄宿.下面我们通过简单的例子来看看WebHost方式和SelfHost方式. 该Demo中包含一个类库项目.一个控制台项目以及一个空的WebForm项目.其中类库项目有一个继承自ApiController的名为HomeController