ASP.NET WebAPI 08 Message,HttpConfiguration,DependencyResolver
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 { 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)
|
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 { 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大概有如下几个作用:
- 设置通信管道
- 存储全局信息(比如Filter,Route,Formatter)
- 提供一个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 { 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的构造中注入的。
|
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 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的方法
|
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的更多相关文章
- ASP.NET WEBAPI 的身份验证和授权
定义 身份验证(Authentication):确定用户是谁. 授权(Authorization):确定用户能做什么,不能做什么. 身份验证 WebApi 假定身份验证发生在宿主程序称中.对于 web ...
- 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 ...
- 在ASP.NET WebAPI 中使用缓存【Redis】
初步看了下CacheCow与OutputCache,感觉还是CacheOutput比较符合自己的要求,使用也很简单 PM>Install-Package Strathweb.CacheOutpu ...
- 基于OWIN ASP.NET WebAPI 使用OAUTH2授权服务的几点优化
前面在ASP.NET WEBAPI中集成了Client Credentials Grant与Resource Owner Password Credentials Grant两种OAUTH2模式,今天 ...
- Asp.net WebAPI 单元测试
现在Asp.net webapi 运用的越来越多,其单元而是也越来越重要.一般软件开发都是多层结构,上层调用下层的接口,而各层的实现人员不同,一般大家都只写自己对应单元测试.对下层的依赖我们通过IOC ...
- ASP.NET WebAPI 09 Controller的激活
在Controller之前我们先回顾一下HttpMessageHandler通道. 在这个图中我留一个HttpContollerDispatcher没有说明.因为这个类也是继承自HttpMessage ...
- 重温ASP.NET WebAPI(二)进阶
重温ASP.NET WebAPI(二)进阶 介绍 本文为个人对WebApi的回顾无参考价值. 本文内容: Rest和UnitOfWork 创建WebAPi的流程 IOC-Unity的使用 MEF ...
- [转]在ASP.NET WebAPI 中使用缓存【Redis】
初步看了下CacheCow与OutputCache,感觉还是CacheOutput比较符合自己的要求,使用也很简单 PM>Install-Package Strathweb.CacheOutpu ...
- Asp.Net WebApi核心对象解析(下篇)
在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...
随机推荐
- 编译php5.4的时候出现错误----configure: error: in `/usr/local/src/php540/php-5.4.0':
错误如下:checking for grep that handles long lines and -e... /bin/grep checking for egrep... /bin/grep - ...
- java的执行与加载的过程
第一.我们编写一个.java源文件: 第二.通过编译器javac.exe把.java源文件编译为.class字节码文件并装入类装载器里: 第三.java虚拟机java.exe把字节码文件解释为各个平台 ...
- 14 接口-interface的定义与实现
接口的基本语法一: 1.使用interface 定义 2.接口当中的方法都是抽象方法 3.接口当中的方法都是public权限 接口的定义: interface USB { public void re ...
- How to fix the sources list
How to fix the sources list Sometimes the apt-get may not work, it is often caused by the misspelled ...
- 55.Android之AsyncTask介绍 (转)
AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操 ...
- 【BZOJ-3757】苹果树 块状树 + 树上莫队
3757: 苹果树 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1305 Solved: 503[Submit][Status][Discuss] ...
- 【bzoj3218】 a + b Problem
http://www.lydsy.com/JudgeOnline/problem.php?id=3218 (题目链接) 题意 给${n}$个格子涂白或黑色,白则${w_i}$,黑则${b_i}$的好看 ...
- POJ2796 Feel Good 单调栈
题意:给定一个序列,需要找出某个子序列S使得Min(a[i])*Σa[i] (i属于S序列)最大 正解:单调栈 这题的暴力还是很好想的,只需3分钟的事就可以码完,以每个点拓展即可,但这样的复杂度是O( ...
- 洛谷P1565 牛宫
题目描述 AP 神牛准备给自己盖一座很华丽的宫殿.于是,他看中了一块N*M 的矩形空地. 空地中每个格子都有自己的海拔高度.AP 想让他的宫殿的平均海拔在海平面之上(假设 海平面的高度是0,平均数都会 ...
- ffmpeg]ffmpeg使用参数的中文说明
基本选项: -formats 输出所有可用格式 -f fmt 指定格式(音频或视频格式) -i filename 指定输入文件名,在linux下当然也能指定:0.0(屏幕录制)或摄像头 -y 覆盖已有 ...