6

I need to get the ApplicationDbContext within a Model.

I am creating a ValidationAttribute. That validation will check some records on database and generate an error if necessary.

public class MyModel
{
  public int? ID { get; set; }
  [MyValidationForName]
  public string Name { get; set; }
}


public class MyValidationForName : ValidationAttribute
{
  protected ValidationResult IsValid(object value, ValidationContext validationContext)
  {
    /* code here */
    return new ValidationResult("This field contains an error");
  }
}

The example above generates an error (DataAnnotation) when saving the record. It is okay only to check dates, lenghts, etc.

But I have to query some records on database. To perform that, the DB context can not be passed to the model.

All SO topics I've read explains how to validate with Remote and JS, putting the validation on the Controller. I do not want this.

The most related SO topic is: Using DB Context in a Custom Validation Attribute (by adding the context it still not work)

Can anyone help me to pass the ApplicationDbContext to the model to perform queries and validate it with ValidationAttribute?

3
  • Why not take the code that does the validation out of the attribute? Then you can apply the same validation wherever you need it - in the attribute or on the database records. Commented Oct 31, 2018 at 17:50
  • That validation is very specific. I have to validate the field before create the record. For me, its normal to put the validation in the model. Do you have an example of your solution? Commented Oct 31, 2018 at 17:52
  • I understand you want the model to validate the name, but the model doesn't have to contain the actual validation code, which could be located in another class. This then allows it to be called from the model and other places, like applying the validation to existing DB data, or unit-testing the validation code. Commented Oct 31, 2018 at 17:57

1 Answer 1

16

I never found the answer, even on Stack Overflow. But after many days, I got the solution. So, I'm answering below, I hope it helps.

First of all, add using System.Linq; in your model class.

So, apply the context:

var _context = (ApplicationDbContext)validationContext.GetService(typeof(ApplicationDbContext));

Now we are able to perform queries within the ValidationAttribute.

A full example:

using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq;

public class MyModel
{

  public int? ID { get; set; }

  [Required(ErrorMessage = "Name can not be blank")]
  [ExampleValidation]
  public string Name { get; set; }

}

public class ExampleValidation : ValidationAttribute
{

  protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
      var _context = (ApplicationDbContext)validationContext
                         .GetService(typeof(ApplicationDbContext));

      /* my query here using the _context, and if necessary, apply the error message below: */
      return new ValidationResult("My error message here");

    }

  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

It helped me greatly! This answer should have hundreds of votes since it's the only good one currently in the internet.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.