2

I am in need of validating field against database possibly using other registered services. I have been reading documentation, but haven't found an actual answer.

There is remote validation that calls to controller method but it is client side only so disabling JS disables validation. There is also custom validation that makes use of validation attributes and is nicely contained within ModelState.IsValid but I cannot inject dependencies into it's constructor.

I have found this question marked as answered as it speaks of dependency resolver but I cannot find any useful information about it.

I tried research it but all I came across was only about dependency injections or IServiceProvider which didn't work for me. Here are some of my failed attempts:

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        //--1-------------------------------
        var container = new ServiceContainer();
        var _context = container.GetService<ApplicationDbContext>();
        //----------------------------------

        //--2-------------------------------
        var services = new ServiceCollection();
        IServiceProvider servicesProvider = services.BuildServiceProvider();
        var _context = servicesProvider.GetService<ApplicationDbContext>();
        //----------------------------------

        return ValidationResult.Success;
    }

Each retrieved _context was null. I have really exhausted all ideas in here and I will be grateful for any help.

Community
  • 1
  • 1
Bielik
  • 922
  • 2
  • 14
  • 25
  • You should not inject dependencies into attributes as expressed [here](https://stackoverflow.com/a/29916075/264697), [here](http://blog.ploeh.dk/2014/06/13/passive-attributes/) and [here](https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=97). – Steven Sep 26 '16 at 17:04
  • In the end I did also implement a service for the remaining validations that have to be done only with the database, it's quiet a pity to don't have a simple way around using the normally inhereted `ValidationAttribute`. – Eugene May 31 '19 at 08:53

1 Answers1

1

I'm facing similar issue. I tried some "patchy" ways (just in case you "have to"). Like I got stuck with my DuplicateMatch attribute for email - which needed database access and nothing was available in my custom validationAttribute.

  1. My DAL is separate project so instead of pure DI(dependency injection) - I kept the DBConext initialization in DAL (it has its own appSettings.json) so none else is being bothered to pass DBContext, etc... just call the DAL (or Service layer) and it'll manage to init a DBContext on its own.
  2. Somehow use the "Service Locator" pattern to get the instance of DBContext and any other objects which have been configured for DI - not tested yet.
  3. Obey DI pattern and do my DuplicateMatch or any other such validation (which requires DAL access in the controller action itself or in service layer) and not with validation attribute.

Let me know if any of these helps. And I'd be interested in knowing more from the community about ways (such as 3.) which does not violate the DI pattern.

Hemant Tank
  • 1,724
  • 4
  • 28
  • 56
  • Thank you for your answer, I tried some of @Steven suggestions but I think I do not have necessary knowledge to fully comprehend them and it seems like a lot of work for such a (seemingly) simple task. I ended up using the third way, I put validation in a service. Not as elegant solution as attribute but it seems safe and keeping it in service allows controller to stay relatively clean. I will look at your others suggestion latter as I have a lot of work now. – Bielik Feb 18 '17 at 21:32