ASP.NET WebAPI 08 Message,HttpConfiguration,DependencyResolver

 

Message

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

HttpRequestMessage

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    public class HttpRequestMessage : IDisposable
    {
        public HttpRequestMessage();       
        public HttpRequestMessage(HttpMethod method, string requestUri);       
        public HttpRequestMessage(HttpMethod method, Uri requestUri);
        public HttpContent Content { getset; }       
        public HttpRequestHeaders Headers { get; }    
        public HttpMethod Method { getset; }      
        public IDictionary<stringobject> Properties { get; }       
        public Uri RequestUri { getset; }       
        public Version Version { getset; }
        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)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    public class HttpRequestMessage : IDisposable
    {
        public HttpRequestMessage();       
        public HttpRequestMessage(HttpMethod method, string requestUri);       
        public HttpRequestMessage(HttpMethod method, Uri requestUri);
        public HttpContent Content { getset; }       
        public HttpRequestHeaders Headers { get; }    
        public HttpMethod Method { getset; }      
        public IDictionary<stringobject> Properties { get; }       
        public Uri RequestUri { getset; }       
        public Version Version { getset; }
        public void Dispose();       
        protected virtual void Dispose(bool disposing);      
        public override string ToString();
}

HttpConfiguration

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

  1. 设置通信管道
  2. 存储全局信息(比如Filter,Route,Formatter)
  3. 提供一个Ioc架构,用于WebAPI的扩展
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class HttpConfiguration : IDisposable
{
    public HttpConfiguration();
    public HttpConfiguration(HttpRouteCollection routes);
    public IDependencyResolver DependencyResolver { getset; }
    public HttpFilterCollection Filters { get; }
    public MediaTypeFormatterCollection Formatters { get; }
    public IncludeErrorDetailPolicy IncludeErrorDetailPolicy { getset; }
    public Action<HttpConfiguration> Initializer { getset; }
    public Collection<System.Net.Http.DelegatingHandler> MessageHandlers { get; }
    public ParameterBindingRulesCollection ParameterBindingRules { getinternal set; }
    public ConcurrentDictionary<objectobject> Properties { get; }
    public HttpRouteCollection Routes { get; }
    public ServicesContainer Services { getinternal 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的构造中注入的。

1
2
3
4
5
6
7
8
9
10
11
12
    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);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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 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 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的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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默认就是采用直接反射方式.

源码

Github: https://github.com/BarlowDu/WebAPI (API_8)

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

  1. ASP.NET WEBAPI 的身份验证和授权

    定义 身份验证(Authentication):确定用户是谁. 授权(Authorization):确定用户能做什么,不能做什么. 身份验证 WebApi 假定身份验证发生在宿主程序称中.对于 web ...

  2. 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 i ...

  3. 在ASP.NET WebAPI 中使用缓存【Redis】

    初步看了下CacheCow与OutputCache,感觉还是CacheOutput比较符合自己的要求,使用也很简单 PM>Install-Package Strathweb.CacheOutpu ...

  4. 基于OWIN ASP.NET WebAPI 使用OAUTH2授权服务的几点优化

    前面在ASP.NET WEBAPI中集成了Client Credentials Grant与Resource Owner Password Credentials Grant两种OAUTH2模式,今天 ...

  5. Asp.net WebAPI 单元测试

    现在Asp.net webapi 运用的越来越多,其单元而是也越来越重要.一般软件开发都是多层结构,上层调用下层的接口,而各层的实现人员不同,一般大家都只写自己对应单元测试.对下层的依赖我们通过IOC ...

  6. ASP.NET WebAPI 09 Controller的激活

    在Controller之前我们先回顾一下HttpMessageHandler通道. 在这个图中我留一个HttpContollerDispatcher没有说明.因为这个类也是继承自HttpMessage ...

  7. 重温ASP.NET WebAPI(二)进阶

    重温ASP.NET WebAPI(二)进阶   介绍 本文为个人对WebApi的回顾无参考价值. 本文内容: Rest和UnitOfWork 创建WebAPi的流程 IOC-Unity的使用 MEF ...

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

    初步看了下CacheCow与OutputCache,感觉还是CacheOutput比较符合自己的要求,使用也很简单 PM>Install-Package Strathweb.CacheOutpu ...

  9. Asp.Net WebApi核心对象解析(下篇)

    在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...

随机推荐

  1. js闭包详解

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 闭包的特性 闭包有三个特性: 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数 ...

  2. jquery读取iframe子页面和父页面的处理

    1. jquery 在iframe子页面获取父页面元素代码如下: $("#objid", parent.document) 2. jquery在父页面 获取iframe子页面的元素 ...

  3. Windows 8.1 安装Ruby on Rails手记

    最近喜欢上了狂拽酷炫的Ruby 看了诸多文章都是Linux或Mac OS X环境配置,文章末尾还不忘把windows黑成一坨... 表示很无语.. 作为新世纪隐秘而强大的 .Net程序员 怎能脱离宇宙 ...

  4. 【POJ 1523】SPF(割点)

    儿子数大于1的树根或者 Low[v] >= DFN[u]的非树根节点v 就是割点. #include <cstdio> #include <cstring> const ...

  5. bzoj4401: 块的计数

    首先,块的大小确定的话,可以发现方案最多只有1种 然后就可以O(nsqrt(n))搞,不过会TLE 接着我们又发现,一个节点可以作一个块的根,当且仅当该节点的size能被块的大小整除 然后就可以O(n ...

  6. 深入理解Java多态机制

    从字节码层面来看,Java中的所有方法调用,最终无外乎转换为如下几条调用指令. invokestatic: 调用静态方法. invokespecial: 调用实例构造器<init>方法,私 ...

  7. 前端打包/自动化构建工具:fis3

    据说这个可以进行打包,并且可以实现类似/script/test-adsf123.js或者/script/test.js?v=asdf123 先做个记号 参考:http://fis.baidu.com/

  8. 对接微信红包时:CA证书出错,请登录微信支付商户平台下载证书

    今天在对接微信支付的微信红包发放时,出现““CA证书出错,请登录微信支付商户平台下载证书”的错误,特此记录一下: 如果你也在对接微信红包,并且你也在这个页面上下载了demo,再就是你也参照了里面的文档 ...

  9. bzoj1124[POI2008]枪战maf

    这代码快写死我了.....死人最多随便推推结论.死人最少,每个环可以单独考虑,每个环上挂着的每棵树也可以分别考虑.tarjan找出所有环,对环上每个点,求出选它和不选它时以它为根的树的最大独立集(就是 ...

  10. Math.Round四舍五入

    Math.Round函数四舍五入的问题   今天客户跑过来跟我说,我们程序里面计算的价格不对,我检查了一下,发现价格是经过折算后的价格,结果是可能小数位较多,而单据上只能打印两位价格,所以就对价格调用 ...