Efcore: Validate attributes on SaveChanges not working

Created on 31 Aug 2017  路  10Comments  路  Source: dotnet/efcore

I want to check some validation rules first when I call SaveChanges();

My method currently looks like this trying to apply one of this solutions:
http://www.bricelam.net/2016/12/13/validation-in-efcore.html
or
https://github.com/aspnet/EntityFrameworkCore/issues/4434

public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            var entities = (from entry in ChangeTracker.Entries()
                            where entry.State == EntityState.Modified || entry.State == EntityState.Added
                            select entry.Entity);

            var validationResults = new List<ValidationResult>();
            foreach (var entity in entities)
            {
                if (!Validator.TryValidateObject(entity, new ValidationContext(entity), validationResults))
                {
                    throw new ValidationException();
                }
            }

            var entities2 = from e in ChangeTracker.Entries()
                           where e.State == EntityState.Added
                               || e.State == EntityState.Modified
                           select e.Entity;
            foreach (var entity in entities2)
            {
                var validationContext = new ValidationContext(entity);
                Validator.ValidateObject(entity, validationContext);
            }

            return base.SaveChangesAsync(cancellationToken);


        }

And my model is:

    public class User : EntityBase
    {
        [StringLength(60, MinimumLength = 10)]
        [RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
        public string UserName { get; set; }
     }

In the controller ModelState has the error count

        [HttpPost]
        public async Task<RG<string>> Post([FromBody] User model)
        {
            try
            {
                if (ModelState.IsValid || model != null)
                {

So this part it is working but since I am going to use view models instead the models from the database I don't want to repeat myself and use attributes in both models, so that's why I want to put the validation on save changes (following DRY).

Any solution for this?
Right now my method SaveChangesAsync() is not detecting any validation errors when Model State does.

I am using EF Core 2

closed-question

Most helpful comment

@Jonatthu Looks like you need to call the TryValidateObject method with an additional bool parameter:
C# if (!Validator.TryValidateObject(entity, new ValidationContext(entity), validationResults, true))
It works for me when I do this.

All 10 comments

@Jonatthu We're trying to understand the issue here. Are you saying that with your example ModelState is reporting the entity as invalid, but if you call SaveChangesAsync with your override, then it doesn't detect any validation errors?

Exactly! SaveAsync is not detecting nothing! @ajcvickers

Note for triage: I was able to reproduce this. The code validates [Required] but seems to ignore StringLength and RegularExpression.

@ajcvickers Is this going to be fix? or Is it supposed to do that?

@Jonatthu It's not an EF issue. It may be an issue with data annotations/validation, but I'm not sure about that since I don't have enough context on how that stuff is supposed to work. I'm leaving this issue open to discuss with others.

@ajcvickers Should I open this issue on the asp.net repository ?

@Jonatthu We have a triage scheduled for tomorrow and I'll get back to you after that.

@Jonatthu Looks like you need to call the TryValidateObject method with an additional bool parameter:
C# if (!Validator.TryValidateObject(entity, new ValidationContext(entity), validationResults, true))
It works for me when I do this.

@ajcvickers Thanks! good catch :D

Just some additional info... When using the TryValidateObject method in EF 6.1.3, I also need to add the bool parameter for the validation to evaluate everything except [Required].

Was this page helpful?
0 / 5 - 0 ratings