Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.Net MVC 4 Custom ValidationAttribute Dependency Injection

In a ASP.Net MVC 4 application that I am currently working on there are a number of models that have a warehouse property. I want all of these models to have validation that makes sure that the warehouse entered is a valid warehouse. It seemed like the easiest way to do this was to use a custom ValidationAttribute class. Then the validation code would be centralized, and I could just add the attribute to the property in each of the models.

I need to call a service to make sure that the warehouse is a valid warehouse. I have a interface that represents this service and I am using Ninject to do dependency injection in my applications where this service is used. That way I can use mocking and easily do unit testing on the application.

I want my custom ValidationAttribute class to use dependency injection when using this service. Here is the class that I have 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>();
    }
}

The dependency injection works correctly, however it is not easy to test. There is no way to inject a mock IInventService into the class in a unit test. Normally in order to resolve this I would have the class constructor take a IInventService parameter so that I could pass in a mock object in my unit test. However I don't think that I can have this class constructor take a IInventService class as a parameter because then I believe that I would have to pass in that parameter when I added this attribute in my class.

Is there a way to make this code more testable? If not then is there a better way to approach this?

like image 751
Eric Maibach Avatar asked Nov 26 '13 14:11

Eric Maibach


1 Answers

You need to use DependencyResolver class in ASP.NET MVC. If you wire your container correctly DependencyResolver.Current will use your container to resolve the 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 like this:

DependencyResolver.SetResolver(resolverMock);
like image 89
Ufuk Hacıoğulları Avatar answered Sep 28 '22 20:09

Ufuk Hacıoğulları