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)