Skip to content

Commit 7e26f42

Browse files
committed
fix: 更新 ValidateForm 验证逻辑
1 parent 3cb9837 commit 7e26f42

File tree

1 file changed

+58
-40
lines changed

1 file changed

+58
-40
lines changed

src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)