2017-09-29 26 views
0

Pourrait-on m'aider s'il vous plaît à résoudre ce problème? J'essaye de changer CustomAsync à MustAsync, mais je ne pourrais pas faire des choses au travail. Ci-dessous est ma méthode personnaliséeValidation fluide changement CustomAsync à MustAsync

RuleFor(o => o).MustAsync(o => { 
      return CheckIdNumberAlreadyExist(o) 
      }); 

     private static async Task<ValidationFailure> CheckIdNumberAlreadyExist(SaveProxyCommand command) 
     { 
      if (command.Id > 0) 
       return null; 

      using (IDbConnection connection = new SqlConnection(ConnectionSettings.LicensingConnectionString)) 
      { 
       var param = new DynamicParameters(); 
       param.Add("@idnumber", command.IdNumber); 

       var vehicle = await connection.QueryFirstOrDefaultAsync<dynamic>("new_checkDuplicateProxyIdNumber", param, commandType: CommandType.StoredProcedure); 

       return vehicle != null 
        ? new ValidationFailure("IdNumber", "Id Number Already Exist") 
        : null; 
      } 
     } 

Répondre

0

Je suppose que vous utilisez une version de FluentValidation avant la version 6, comme vous n'êtes pas passer dans une continuation Jeton, donc j'ai fondé ma réponse sur la version 5.6 .2.

Votre code d'exemple ne compile pas, pour commencer, car il vous manque un point-virgule dans votre règle actuelle. Vous évaluez également deux propriétés différentes sur le paramètre SaveProxyCommand.

J'ai construit un très petit POC en fonction de certaines hypothèses:

Étant donné 2 classes:

public class SaveProxyCommand { 
    public int Id { get; set; } 
} 

public class ValidationFailure { 
    public string PropertyName { get; } 
    public string Message { get; } 

    public ValidationFailure(string propertyName, string message){ 
     Message = message; 
     PropertyName = propertyName; 
    } 
} 

et un validateur:

public class SaveProxyCommandValidator : AbstractValidator<SaveProxyCommand>{ 

    public SaveProxyCommandValidator() 
    { 
     RuleFor(o => o).MustAsync(CheckIdNumberAlreadyExists) 
         .WithName("Id") 
         .WithState(o => new ValidationFailure(nameof(o.IdNumber), "Id Number Already Exist")); 
    } 

    private static async Task<bool> CheckIdNumberAlreadyExists(SaveProxyCommand command) { 
     if (command.Id > 0) 
      return true; 

     var existingIdNumbers = new[] { 
      1, 2, 3, 4 
     }; 

     // This is a fudge, but you'd make your db call here 
     var isNewNumber = !(await Task.FromResult(existingIdNumbers.Contains(command.IdNumber))); 

     return isNewNumber; 

    } 
} 

je ne comprend pas l'appel à la base de données, car cela ne fait pas partie de votre problème. Il y a deux ou trois choses à remarquer ici:

  1. Vous n'êtes pas régler la méthode d'annotation .WithName, mais quand vous configurez une règle de validation pour un objet que vous avez à faire, comme FluentValidation vous attend spécifier des propriétés spécifiques à valider par défaut, si vous transmettez un objet entier, il ne sait tout simplement pas comment rapporter les erreurs. Doit/MustAsync doit retourner un bool/Task<bool> au lieu d'un objet personnalisé. Pour contourner ce problème, vous pouvez spécifier un état personnalisé à renvoyer en cas d'échec de la validation.

Vous pouvez avoir accès à cela comme ceci:

var sut = new SaveProxyCommand { Id = 0, IdNumber = 3 }; 
var validator = new SaveProxyCommandValidator(); 
var result = validator.ValidateAsync(sut).GetAwaiter().GetResult(); 
var ValidationFailures = result.Errors?.Select(s => s.CustomState).Cast<ValidationFailure>(); 

Le ci-dessus pas prendre en compte les collections vides, il est juste un exemple de la façon de creuser dans le graphe d'objet pour récupérer personnalisée Etat. À titre de suggestion, fluentvalidation fonctionne mieux si vous définissez des règles individuelles par propriété, au lieu de valider l'objet entier. Mon point de vue sur ce serait quelque chose comme ceci:

public class SaveProxyCommandValidator : AbstractValidator<SaveProxyCommand>{ 

    public SaveProxyCommandValidator() 
    { 
     RuleFor(o => o.IdNumber).MustAsync(CheckIdNumberAlreadyExists) 
           .Unless(o => o.Id > 0) 
           .WithState(o => new ValidationFailure(nameof(o.IdNumber), "Id Number Already Exist")); 
    } 

    private static async Task<bool> CheckIdNumberAlreadyExists(int numberToEvaluate) { 
     var existingIdNumbers = new[] { 
      1, 2, 3, 4 
     }; 

     // This is a fudge, but you'd make your db call here 
     var isNewNumber = !(await Task.FromResult(existingIdNumbers.Contains(numberToEvaluate))); 

     return isNewNumber; 
    } 
} 

Cette lecture plus comme un récit, il utilise la .Unless construction pour exécuter uniquement la règle si Id est pas plus de 0, et ne nécessite pas l'évaluation de la objet entier.