Dependency Resolution in Web API

The new Web API feature (refer to Chapter 11) also includes the ability to support dependency resolution. The design of the dependency resolver in Web API is slightly different from the one in MVC but, in principle, serves the same purposes: to allow developers to easily get dependency injection for their controllers, as well as making it easy to provide services to Web API that are themselves created via dependency-injection techniques.

There are two significant differences in the dependency resolution implementation in Web API. First, there are no static APIs for default registration of services; these old static APIs in MVC were there for historical reasons. Instead, there is a loosely typed service locator that can be accessed at HttpConfiguration.Services, where developers can enumerate and replace the default services used by Web API.

Second, the actual dependency resolver API has been modified slightly to support the notion of scopes. One criticism of the original dependency resolver interface in MVC was the lack of any kind of resource-cleanup mechanism. After consultation with the community, we landed on a design that used the concept of a scope as the way that Web API would trigger this cleanup. The system automatically creates a new scope per request, which is available as an HttpRequestMessage extension method named GetDependencyScope. Like the dependency resolver interface, the scope interface has both GetService and GetServices methods; the difference is that resources acquired from the request-local scope will be released when the request is completed.

Getting or setting the dependency resolver for Web API is done via HttpConfiguration.DependencyResolver.

Singly Registered Services in Web API

Like MVC, Web API has services that it consumes for which the user can register one (and exactly one) instance of that service. The resolver retrieves these singly registered services by calling GetService.

For all the singly registered services, Web API consults the dependency resolver for the service the first time it is needed, and caches the result for the lifetime of the application. When Web API cannot find the service in the resolver, it uses the service found in the default services list in HttpConfiguration.Services. Table 12.3 shows the list of singly registered services that Web API uses.

Table 12.3 Singly Registered Services in Web API

Service Default Service Implementation
IActionValueBinder DefaultActionValueBinder
IApiExplorer ApiExplorer
IAssembliesResolver DefaultAssembliesResolver*
IBodyModelValidator DefaultBodyModelValidator
IContentNegotiator DefaultContentNegotiator
IDocumentationProvider None
IHostBufferPolicySelector None
IHttpActionInvoker ApiControllerActionInvoker
IHttpActionSelector ApiControllerActionSelector
IHttpControllerActivator DefaultHttpControllerActivator
IHttpControllerSelector DefaultHttpControllerSelector
IHttpControllerTypeResolver DefaultHttpControllerTypeResolver**
ITraceManager TraceManager
ITraceWriter None
ModelMetadataProvider CachedDataAnnotationsModel-MetadataProvider

* When the application is running in ASP.NET, this is replaced by WebHostAssembliesResolver.

** When the application is running in ASP.NET, this is replaced by WebHostHttpControllerTypeResolver.

Multiply Registered Services in Web API

Again borrowing the concepts from MVC, Web API has multiply registered services, and combines the list of those services from the dependency resolver with the list in HttpConfiguration.Services. To retrieve the services from the dependency resolver, Web API will call the GetServices method. Table 12.4 lists the multiply registered services that Web API uses, and whether those services are cooperative or competitive.

Table 12.4 Multiply Registered Services in Web API

Service

Default Service Implementations
IFilterProvider
Multi-service model: cooperative
ConfigurationFilterProvider
ActionDescriptorFilterProvider
ModelBinderProvider
Multi-service model: competitive
TypeConverterModelBinderProvider
TypeMatchModelBinderProvider
KeyValuePairModelBinderProvider
ComplexModelDtoModelBinderProvider
ArrayModelBinderProvider
DictionaryModelBinderProvider
CollectionModelBinderProvider
MutableObjectModelBinderProvider
ModelValidatorProvider
Multi-service model: cooperative
DataAnnotationsModelValidatorProvider
DataMemberModelValidatorProvider
InvalidModelValidatorProvider
ValueProviderFactory
Multi-service model: competitive
QueryStringValueProviderFactory
RouteDataValueProviderFactory

Arbitrary Objects in Web API

There are three special cases where the Web API framework will request a dependency resolver to manufacture arbitrary objects — that is, objects that are not (strictly speaking) services. Like MVC, controllers are one class of these objects. The other two are model binders attached with the [ModelBinder] attribute and the per-controller services that are attached to controllers via [HttpControllerConfiguration].

The services attached via the attributes are cached for the lifetime of the application, just like the built-in services, which means Web API will request them from the dependency resolver attached to the configuration. Controllers, on the other hand, typically have request-scoped lifetimes, so they are requested from the scope that's attached to the request.

Dependency Resolvers in MVC vs. Web API

Although MVC and Web API share the idea of dependency resolvers, the actual interfaces are different, as described previously. In addition, the actual services that might be contained in those dependency resolvers are different, since MVC and Web API share no common service interfaces, either. That means that the implementation of the two dependency resolver interfaces differ, and you shouldn't expect an MVC dependency resolver to work in Web API (or vice versa).

That said, it is perfectly reasonable to have those two dependency resolver interface implementations backed by the same concrete dependency injection container so that any custom services you use throughout your application would be available to both MVC and Web API controllers. You should consult the documentation for your dependency injection container to determine how to use a single container for an application that includes both MVC and Web API.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset