In MVC, a ModelValidatorProvider
is instantiated and called to validate a model on each request. This means that in a DI environment, it can take dependencies on objects scoped within a single request, such as a Unit of Work or Database context. In Web API, this appears to have been significantly changed. Instead of being instantiated per-request, the ModelValidatorProvider
appears to be long-lived and instantiated within the application startup. The WebAPI then caches the results from the ModelValidatorProvider
per-type, meaning that the ModelValidator
cannot take any dependencies from DI.
I am trying to implement my ModelValidator
to use a factory using a Service Locator (please, no automatic 'anti-pattern' comments!). This would allow me to construct an internal validator object within each request, which would be able to take dependencies from the container. However, I cannot get hold of a Dependency Resolver or container scoped to the current request from within this ModelValidator
which is essentially scoped as a Singleton. I've tried to use GlobalConfiguration.Configuration.DependencyResolver
, but this only returns globally-scoped services (from the root scope, also mentioned here)
I'm working in Autofac, so an autofac-specific solution would be suitable (e.g. MVC has AutofacDependencyResolver.Current
, which internally uses DependencyResolver.GetService
). There is no equivalent available in the WebAPI integration, presumably because of the reason mentioned above where the global DependencyResolver
only returns globally-scoped services.
The reason I'm trying to do this (as well as for my own use) is to implement the Web API integration for FluentValidation, which currently does not exist. There have been two attempts so far, but neither of these handle the Dependency Injection issue and instead result in a single static ModelValidator.
Things I've tried so far:
GlobalConfiguration.Configuration.DependencyResolver
(returns objects from the root scope)Func<IComponentContext>
(always returns the root context)In an answer which has since been removed, it was suggested to remove IModelValidatorProvider
service from the Web API config. This had to be done using reflection since the interface and the implementing classes are all defined as internal, but it did make the validators work better (because the ModelValidator was constructed per request). However, there is a significant performance hit to doing it this way due to the use of reflection to check for validators on the model and every property it has, so I don't want to take this option.
Filip W's answer suggests using HttpRequestMessage to get the Dependency Scope, but I've not found anything such as HttpRequestMessage.Current
which would provide access to this object from within a long-lived object - if that could be achieved I believe everything would fall into place.
To get current dependency scope, you have to use (surprise, surprise :) GetDependencyScope()
of the current HttpRequestMessage
(more about which you can read up on MSDN) instead of GlobalConfiguration
.
I blogged about Web API per-request dependency scope a while ago - that should be helpful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With