@@ -495,6 +495,95 @@ public async Task Validate_RequiredOnPropertyShortCircuitsOtherValidations()
495495 Assert . Equal ( "The Password field is required." , error . Value . Single ( ) ) ;
496496 }
497497
498+ [ Fact ]
499+ public async Task Validate_IValidatableObject_WithZeroAndMultipleMemberNames_BehavesAsExpected ( )
500+ {
501+ var globalType = new TestValidatableTypeInfo (
502+ typeof ( GlobalErrorObject ) ,
503+ [ ] ) ; // no properties – nothing sets MemberName
504+
505+ var context = new ValidateContext
506+ {
507+ ValidationOptions = new TestValidationOptions ( new Dictionary < Type , ValidatableTypeInfo >
508+ {
509+ { typeof ( GlobalErrorObject ) , globalType }
510+ } )
511+ } ;
512+
513+ var globalErrorInstance = new GlobalErrorObject { Data = - 1 } ;
514+ context . ValidationContext = new ValidationContext ( globalErrorInstance ) ;
515+
516+ await globalType . ValidateAsync ( globalErrorInstance , context , default ) ;
517+
518+ Assert . NotNull ( context . ValidationErrors ) ;
519+ var globalError = Assert . Single ( context . ValidationErrors ) ;
520+ Assert . Equal ( string . Empty , globalError . Key ) ;
521+ Assert . Equal ( "Data must be positive." , globalError . Value . Single ( ) ) ;
522+
523+ var multiType = new TestValidatableTypeInfo (
524+ typeof ( MultiMemberErrorObject ) ,
525+ [
526+ CreatePropertyInfo ( typeof ( MultiMemberErrorObject ) , typeof ( string ) , "FirstName" , "FirstName" , [ ] ) ,
527+ CreatePropertyInfo ( typeof ( MultiMemberErrorObject ) , typeof ( string ) , "LastName" , "LastName" , [ ] )
528+ ] ) ;
529+
530+ context . ValidationErrors = [ ] ;
531+ context . ValidationOptions = new TestValidationOptions ( new Dictionary < Type , ValidatableTypeInfo >
532+ {
533+ { typeof ( MultiMemberErrorObject ) , multiType }
534+ } ) ;
535+
536+ var multiErrorInstance = new MultiMemberErrorObject { FirstName = "" , LastName = "" } ;
537+ context . ValidationContext = new ValidationContext ( multiErrorInstance ) ;
538+
539+ await multiType . ValidateAsync ( multiErrorInstance , context , default ) ;
540+
541+ Assert . NotNull ( context . ValidationErrors ) ;
542+ Assert . Collection ( context . ValidationErrors ,
543+ kvp =>
544+ {
545+ Assert . Equal ( "FirstName" , kvp . Key ) ;
546+ Assert . Equal ( "FirstName and LastName are required." , kvp . Value . First ( ) ) ;
547+ } ,
548+ kvp =>
549+ {
550+ Assert . Equal ( "LastName" , kvp . Key ) ;
551+ Assert . Equal ( "FirstName and LastName are required." , kvp . Value . First ( ) ) ;
552+ } ) ;
553+ }
554+
555+ // Returns no member names to validate https://github.com/dotnet/aspnetcore/issues/61739
556+ private class GlobalErrorObject : IValidatableObject
557+ {
558+ public int Data { get ; set ; }
559+
560+ public IEnumerable < ValidationResult > Validate ( ValidationContext validationContext )
561+ {
562+ if ( Data <= 0 )
563+ {
564+ yield return new ValidationResult ( "Data must be positive." ) ;
565+ }
566+ }
567+ }
568+
569+ // Returns multiple member names to validate https://github.com/dotnet/aspnetcore/issues/61739
570+ private class MultiMemberErrorObject : IValidatableObject
571+ {
572+ public string ? FirstName { get ; set ; }
573+ public string ? LastName { get ; set ; }
574+
575+ public IEnumerable < ValidationResult > Validate ( ValidationContext validationContext )
576+ {
577+ if ( string . IsNullOrEmpty ( FirstName ) || string . IsNullOrEmpty ( LastName ) )
578+ {
579+ // MULTIPLE member names
580+ yield return new ValidationResult (
581+ "FirstName and LastName are required." ,
582+ [ nameof ( FirstName ) , nameof ( LastName ) ] ) ;
583+ }
584+ }
585+ }
586+
498587 private ValidatablePropertyInfo CreatePropertyInfo (
499588 Type containingType ,
500589 Type propertyType ,
@@ -534,7 +623,7 @@ public IEnumerable<ValidationResult> Validate(ValidationContext validationContex
534623 {
535624 if ( Salary < 0 )
536625 {
537- yield return new ValidationResult ( "Salary must be a positive value." , new [ ] { nameof ( Salary ) } ) ;
626+ yield return new ValidationResult ( "Salary must be a positive value." , [ " Salary" ] ) ;
538627 }
539628 }
540629 }
0 commit comments