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. mnsday1t1

    贪心地选取两个后缀,然后往前补全,贪心地补全前k个不同的字符 我写了个沙茶dp,结果T掉了,明明都是n3的... #include<iostream> #include<stdio. ...

  2. 使用jmeter进行性能测试-Jmeter教程及技巧汇总 (转)

    http://www.jmeter.cf/loadtesting-jmeter.html 为什么使用jmeter, 它免费开源, 不断发展, 功能逐渐强大. 可以做功能,负载, 性能测试.一套脚本可以 ...

  3. RegExp正则校验之Java及R测试

    前言: 正则表达式(英语:Regular Expression)原属于计算机科学的一个概念.正则表达式使用单个字符串来描述.匹配一系列符合某个句法规则的字符串.在很多文本编辑器里边,正则表达式通常被用 ...

  4. Java并发和多线程(二)Executor框架

    Executor框架 1.Task?Thread? 很多人在学习多线程这部分知识的时候,容易搞混两个概念:任务(task)和线程(thread). 并发编程可以使我们的程序可以划分为多个分离的.独立运 ...

  5. 【BZOJ-4008】亚瑟王 概率与期望 + DP

    4008: [HNOI2015]亚瑟王 Time Limit: 20 Sec  Memory Limit: 512 MBSec  Special JudgeSubmit: 832  Solved: 5 ...

  6. c3p0 泄漏

    一个很重要的资料来源 http://liu.fm/2015/07/15/c3p0/ c3p0 泄漏 标签: c3p0hibernatekillloggingspringdao 2011-06-16 1 ...

  7. 【bzoj3110】 Zjoi2013—K大数查询

    http://www.lydsy.com/JudgeOnline/problem.php?id=3110 (题目链接) 题意 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在 ...

  8. MySoft.Data 2.7.3版本的GitHub托管(ORM升级封装)

    MySoft.Data 2.7.3 dotnet ORM 版权 这里版权属于老毛:http://www.cnblogs.com/maoyong 说明 MySoft体系中的ORM组件,这里的版本为2.7 ...

  9. Hackerrank Going to the Office

    传送门 Problem Statement Ms.Kox enjoys her job, but she does not like to waste extra time traveling to ...

  10. linux 学习基础7之脚本的练习

    练习:传递一个用户名参数给脚本,判断此用户的用户名跟其基本组的组名是否一致,并将结果显示出来.写一个脚本:#!/bin/bashUSER=$1if [ !  $# -eq 1 ];then  echo ...