@@ -21,15 +21,13 @@ public partial class ValidateForm
2121 /// <see cref="EditContext"/> is determined to be valid.
2222 /// </summary>
2323 [ Parameter ]
24- [ NotNull ]
2524 public Func < EditContext , Task > ? OnValidSubmit { get ; set ; }
2625
2726 /// <summary>
2827 /// A callback that will be invoked when the form is submitted and the
2928 /// <see cref="EditContext"/> is determined to be invalid.
3029 /// </summary>
3130 [ Parameter ]
32- [ NotNull ]
3331 public Func < EditContext , Task > ? OnInvalidSubmit { get ; set ; }
3432
3533 /// <summary>
@@ -107,6 +105,11 @@ public partial class ValidateForm
107105 /// </summary>
108106 private readonly ConcurrentDictionary < ( string FieldName , Type ModelType ) , ( FieldIdentifier FieldIdentifier , IValidateComponent ValidateComponent ) > _validatorCache = new ( ) ;
109107
108+ /// <summary>
109+ /// 验证组件验证结果缓存
110+ /// </summary>
111+ private readonly ConcurrentDictionary < IValidateComponent , List < ValidationResult > > _validateResults = new ( ) ;
112+
110113 private string ? DisableAutoSubmitString => ( DisableAutoSubmitFormByEnter . HasValue && DisableAutoSubmitFormByEnter . Value ) ? "true" : null ;
111114
112115 /// <summary>
@@ -165,7 +168,7 @@ internal void AddValidator((string FieldName, Type ModelType) key, (FieldIdentif
165168 /// </summary>
166169 /// <param name="key"></param>
167170 /// <param name="value"></param>
168- internal bool TryRemoveValidator ( ( string FieldName , Type ModelType ) key , [ MaybeNullWhen ( false ) ] out ( FieldIdentifier FieldIdentifier , IValidateComponent IValidateComponent ) value ) => _validatorCache . TryRemove ( key , out value ) ;
171+ internal bool TryRemoveValidator ( ( string FieldName , Type ModelType ) key , out ( FieldIdentifier FieldIdentifier , IValidateComponent IValidateComponent ) value ) => _validatorCache . TryRemove ( key , out value ) ;
169172
170173 /// <summary>
171174 /// 设置指定字段错误信息
@@ -187,19 +190,23 @@ public void SetError<TModel>(Expression<Func<TModel, object?>> expression, strin
187190 private void InternalSetError ( MemberExpression exp , string errorMessage )
188191 {
189192 var fieldName = exp . Member . Name ;
190- if ( exp . Expression ! = null )
193+ if ( exp . Expression = = null )
191194 {
192- var modelType = exp . Expression . Type ;
193- var validator = _validatorCache . FirstOrDefault ( c => c . Key . ModelType == modelType && c . Key . FieldName == fieldName ) . Value . ValidateComponent ;
194- if ( validator != null )
195- {
196- var results = new List < ValidationResult >
197- {
198- new ( errorMessage , new string [ ] { fieldName } )
199- } ;
200- validator . ToggleMessage ( results ) ;
201- }
195+ return ;
202196 }
197+
198+ var modelType = exp . Expression . Type ;
199+ var validator = _validatorCache . FirstOrDefault ( c => c . Key . ModelType == modelType && c . Key . FieldName == fieldName ) . Value . ValidateComponent ;
200+ if ( validator == null )
201+ {
202+ return ;
203+ }
204+
205+ var results = new List < ValidationResult >
206+ {
207+ new ( errorMessage , [ fieldName ] )
208+ } ;
209+ validator . ToggleMessage ( results ) ;
203210 }
204211
205212 /// <summary>
@@ -213,7 +220,7 @@ public void SetError(string propertyName, string errorMessage)
213220 {
214221 var results = new List < ValidationResult >
215222 {
216- new ( errorMessage , new string [ ] { fieldName } )
223+ new ( errorMessage , [ fieldName ] )
217224 } ;
218225 validator . ToggleMessage ( results ) ;
219226 }
@@ -241,7 +248,7 @@ private bool TryGetModelField(string propertyName, [MaybeNullWhen(false)] out Ty
241248 return propNames . IsEmpty ;
242249 }
243250
244- private bool TryGetValidator ( Type modelType , string fieldName , [ NotNullWhen ( true ) ] out IValidateComponent validator )
251+ private bool TryGetValidator ( Type modelType , string fieldName , out IValidateComponent validator )
245252 {
246253 validator = _validatorCache . FirstOrDefault ( c => c . Key . ModelType == modelType && c . Key . FieldName == fieldName ) . Value . ValidateComponent ;
247254 return validator != null ;
@@ -256,6 +263,8 @@ private bool TryGetValidator(Type modelType, string fieldName, [NotNullWhen(true
256263 /// <param name="results"></param>
257264 internal async Task ValidateObject ( ValidationContext context , List < ValidationResult > results )
258265 {
266+ _validateResults . Clear ( ) ;
267+
259268 if ( ValidateAllProperties )
260269 {
261270 await ValidateProperty ( context , results ) ;
@@ -266,30 +275,29 @@ internal async Task ValidateObject(ValidationContext context, List<ValidationRes
266275 foreach ( var key in _validatorCache . Keys )
267276 {
268277 // 验证 DataAnnotations
269- var validatorValue = _validatorCache [ key ] ;
270- var validator = validatorValue . ValidateComponent ;
271- var fieldIdentifier = validatorValue . FieldIdentifier ;
272- if ( validator . IsNeedValidate )
278+ var ( fieldIdentifier , validator ) = _validatorCache [ key ] ;
279+ if ( ! validator . IsNeedValidate )
273280 {
274- var messages = new List < ValidationResult > ( ) ;
275- var pi = key . ModelType . GetPropertyByName ( key . FieldName ) ;
276- if ( pi != null )
281+ continue ;
282+ }
283+
284+ var messages = new List < ValidationResult > ( ) ;
285+ var pi = key . ModelType . GetPropertyByName ( key . FieldName ) ;
286+ if ( pi != null )
287+ {
288+ var propertyValidateContext = new ValidationContext ( fieldIdentifier . Model , context , null )
277289 {
278- var propertyValidateContext = new ValidationContext ( fieldIdentifier . Model , context , null )
279- {
280- MemberName = fieldIdentifier . FieldName ,
281- DisplayName = fieldIdentifier . GetDisplayName ( )
282- } ;
290+ MemberName = fieldIdentifier . FieldName ,
291+ DisplayName = fieldIdentifier . GetDisplayName ( )
292+ } ;
283293
284- // 设置其关联属性字段
285- var propertyValue = Utility . GetPropertyValue ( fieldIdentifier . Model , fieldIdentifier . FieldName ) ;
294+ // 设置其关联属性字段
295+ var propertyValue = Utility . GetPropertyValue ( fieldIdentifier . Model , fieldIdentifier . FieldName ) ;
286296
287- await ValidateAsync ( validator , propertyValidateContext , messages , pi , propertyValue ) ;
288- }
289- // 客户端提示
290- validator . ToggleMessage ( messages ) ;
291- results . AddRange ( messages ) ;
297+ await ValidateAsync ( validator , propertyValidateContext , messages , pi , propertyValue ) ;
292298 }
299+ _validateResults . TryAdd ( validator , messages ) ;
300+ results . AddRange ( messages ) ;
293301 }
294302
295303 // 验证 IValidatableObject
@@ -306,22 +314,32 @@ internal async Task ValidateObject(ValidationContext context, List<ValidationRes
306314 }
307315 if ( validate != null )
308316 {
309- var messages = validate . Validate ( context ) ;
310- if ( messages . Any ( ) )
317+ var messages = validate . Validate ( context ) . ToList ( ) ;
318+ if ( messages . Count > 0 )
311319 {
312320 foreach ( var key in _validatorCache . Keys )
313321 {
314322 var validatorValue = _validatorCache [ key ] ;
315323 var validator = validatorValue . ValidateComponent ;
316324 if ( validator . IsNeedValidate )
317325 {
318- validator . ToggleMessage ( messages ) ;
326+ _validateResults . AddOrUpdate ( validator , k => messages , ( k , m ) =>
327+ {
328+ m . AddRange ( messages ) ;
329+ return m ;
330+ } ) ;
319331 }
320332 }
321333 results . AddRange ( messages ) ;
322334 }
323335 }
324336 }
337+
338+ ValidMemberNames . RemoveAll ( name => _validateResults . Values . SelectMany ( i => i ) . Any ( i => i . MemberNames . Contains ( name ) ) ) ;
339+ foreach ( var ( validator , messages ) in _validateResults )
340+ {
341+ validator . ToggleMessage ( messages ) ;
342+ }
325343 }
326344 }
327345
@@ -425,7 +443,7 @@ private void ValidateDataAnnotations(object? value, ValidationContext context, L
425443 var errorMessage = ! string . IsNullOrEmpty ( rule . ErrorMessage ) && rule . ErrorMessage . Contains ( "{0}" )
426444 ? rule . FormatErrorMessage ( displayName )
427445 : rule . ErrorMessage ;
428- results . Add ( new ValidationResult ( errorMessage , new string [ ] { memberName } ) ) ;
446+ results . Add ( new ValidationResult ( errorMessage , [ memberName ] ) ) ;
429447 }
430448 }
431449 }
@@ -507,7 +525,7 @@ private async Task ValidateAsync(IValidateComponent validator, ValidationContext
507525 if ( messages . Count == 0 )
508526 {
509527 // 自定义验证组件
510- _tcs = new ( ) ;
528+ _tcs = new TaskCompletionSource < bool > ( ) ;
511529 await validator . ValidatePropertyAsync ( propertyValue , context , messages ) ;
512530 _tcs . TrySetResult ( messages . Count == 0 ) ;
513531 }
0 commit comments