ASP.Net MVC 4 Custom ValidationAttribute Dependency Injection

In the ASP.Net MVC 4 application I'm working on now, there are several models that have a repository property. I want all of these models to have validation, which ensures that the entered warehouse is a valid warehouse. It seemed that the easiest way to do this was to use the special ValidationAttribute class. Then the validation code will be centralized, and I could just add an attribute to the property in each of the models.

I need to call a service to make sure the repository is a valid repository. I have an interface that represents this service, and I use Ninject to inject dependencies in my applications that use this service. This way I can use the mockery and easily do unit testing in the application.

I want my custom ValidationAttribute class to use dependency injection when using this service. Here is the class I created:

public class MustBeValidWarehouse : ValidationAttribute { public override bool IsValid(object value) { if (value is string) { string warehouse = value.ToString(); NinjectDependencyResolver depres = new NinjectDependencyResolver(); Type inventServiceType = typeof(IInventService); IInventService inventserv = depres.GetService(inventServiceType) as IInventService; return (inventserv.GetWarehouses().Where(m => m.WarehouseId == warehouse).Count() != 0); } else { return false; } } } public class NinjectDependencyResolver : IDependencyResolver { private IKernel kernel; public NinjectDependencyResolver() { kernel = new StandardKernel(); AddBindings(); } public object GetService(Type serviceType) { return kernel.TryGet(serviceType); } public IEnumerable<object> GetServices(Type serviceType) { return kernel.GetAll(serviceType); } private void AddBindings() { kernel.Bind<IInventService>().To<InventService>(); } } 

Dependency injection works correctly, but it is not easy to verify. Cannot embed an IInventService layout in a class. Normally for this, I would like the class constructor to accept the IInventService parameter so that I can pass the layout of the object in my unit test. However, I don’t think that I can have this constructor class take the IInventService class as a parameter, because then I believe that I will have to pass this parameter when I add this attribute to my class.

Is there a way to make this code more reliable? If not, is there a better way to approach this?

+6
source share
1 answer

You need to use the DependencyResolver class in ASP.NET MVC. If you connect your container correctly, DependencyResolver.Current will use your container to resolve dependencies.

 public class MustBeValidWarehouse : ValidationAttribute { public override bool IsValid(object value) { if (value is string) { string warehouse = value.ToString(); IInventService inventserv = DependencyResolver.Current.GetService<IInventService>(); return (inventserv.GetWarehouses().Where(m => m.WarehouseId == warehouse).Count() != 0); } return false; } } 

In your class tests, you can provide a mock for DepedencyResolver.Current as follows:

 DependencyResolver.SetResolver(resolverMock); 
+9
source

Source: https://habr.com/ru/post/958864/


All Articles