Reputation: 8490
I'm using the validation of the Entity Framework which relies on System.ComponentModel.DataAnnotations.ValidationAttribute
s. So when I call DbContext.SaveChanges()
and an entity property fails validation, a DbEntityValidationException
is thrown.
What I need to know is which ValidationAttribute
exactly caused that validation error. I.e. I need to know the Type
of ValidationAttribute
causing the DbEntityValidationException
within my program.
I already know how to iterate through the collections of validation errors inside the DbEntityValidationException
. However the required information is not in there.
Example
Say I have this simple model with a single property which has two data annotations...
class Model
{
[Required]
[MaxLength(3)]
string Code { ... }
}
...and want to add a new instance of it like so:
try
{
var model = new Model { Code = "ThisIsTooLong" };
dbContext.Set<Model>().Add(model);
dbContext.SaveChanges();
}
catch (DbEntityValidationException e)
{
Type unsatisfiedValidationAttribute = MagicFunction();
}
In the above case an DbEntityValidationException
is thrown and the variable unsatisfiedValidationAttribute
should be equal to typeof(MaxLengthAttribute)
.
What does MagicFunction()
has to do to know whether the Required
or the MaxLength
annotation triggered the validation error?
Upvotes: 4
Views: 1087
Reputation: 39376
I think what you looking for is Validator.TryValidateObject
static method:
var modelToSave = new Model { Code = "ThisIsTooLong" };
var results = new List<ValidationResult>();
bool isValid=Validator.TryValidateObject( modelToSave, context, results, true);
In case your entity is not valid you are going to hold each failed validation in results
list.
Well, a generic solution to get the ValidationAttribute
using the ErrorMessage
could be doing this:
public static ValidationAttribute GetAttribute(Type entityType, string property, string errorMessage)
{
var attributes = typeof(entityType)
.GetProperty(property)
.GetCustomAttributes(false)
.OfType<ValidationAttribute>()
.ToArray();
var attribute= attributes.FirstOrDefault(a => a.ErrorMessage == errorMessage);
return attribute;
}
Upvotes: 1
Reputation: 367
This might help you If you are using Entity Framework 4.1+. You can implement your own validation logic in your entity and return your own error codes for different validation issues.
IValidatableObject is an interface that lives in System.ComponentModel.DataAnnotations. While it is not part of the Entity Framework API, you can still leverage it for server-side validation in your Entity Framework classes. IValidatableObject provides a Validate method that Entity Framework will call during SaveChanges or you can call yourself any time you want to validate the classes.
Configurations such as Required and MaxLength perform validaton on a single field. In the Validate method you can have even more complex logic, for example, comparing two fields.
public class Blog : IValidatableObject
{
public int Id { get; set; }
[Required]
public string Title { get; set; }
public string BloggerName { get; set; }
public DateTime DateCreated { get; set; }
public virtual ICollection<Post> Posts { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Title == BloggerName)
{
yield return new ValidationResult
("Blog Title cannot match Blogger Name", new[] { "Title", “BloggerName” });
}
}
}
Upvotes: 0