c# - Blazor EditForm 验证仅在使用“验证器组件”时部分有效(在“业务逻辑验证”函数中)
问题描述
问题是我无法获得针对字段显示的验证消息。尽管错误消息确实出现在验证摘要中。
这个问题也进一步仅限于复杂的模型属性。在这种情况下,使用“ValidateComplexType”、“ObjectGraphDataAnnotationsValidator”解决复杂模型属性验证限制的方法没有帮助。
下面我为演示该问题而创建的示例代码实际上是来自 Microsoft 文档网站 ( https://docs.microsoft.com/en-us/aspnet/core/blazor/forms-validation ) 的所有代码。
索引.razor
@page "/"
@using System.ComponentModel.DataAnnotations;
<h1>Starfleet Starship Database</h1>
<h2>New Ship Entry Form</h2>
<EditForm Model="@starship" OnValidSubmit="@HandleValidSubmit">
<DataAnnotationsValidator />
<CustomValidator @ref="customValidator" />
<ValidationSummary />
@*<ObjectGraphDataAnnotationsValidator />*@ @* does not work!*@
<p>
<label>
Identifier:
<InputText @bind-Value="starship.Identifier" disabled="@disabled" />
<ValidationMessage For="@(() => starship.Identifier)" />
</label>
</p>
<p>
<label>
Description (optional):
<InputTextArea @bind-Value="starship.Description" disabled="@disabled" />
<ValidationMessage For="@(() => starship.Description)" />
</label>
</p>
<p>
<label>
Primary Classification:
<InputSelect @bind-Value="starship.Classification" disabled="@disabled">
<option value="">Select classification ...</option>
<option value="Exploration">Exploration</option>
<option value="Diplomacy">Diplomacy</option>
<option value="Defense">Defense</option>
</InputSelect>
<ValidationMessage For="@(() => starship.Classification)" />
</label>
</p>
<p>
<label>
Maximum Accommodation:
<InputNumber @bind-Value="starship.MaximumAccommodation" disabled="@disabled" />
<ValidationMessage For="@(() => starship.MaximumAccommodation)" />
</label>
</p>
<p>
<label>
Engineering Approval:
<InputCheckbox @bind-Value="starship.IsValidatedDesign" disabled="@disabled" />
<ValidationMessage For="@(() => starship.IsValidatedDesign)" />
</label>
</p>
<p>
<label>
Production Date:
<InputDate @bind-Value="starship.ProductionDate" disabled="@disabled" />
<ValidationMessage For="@(() => starship.ProductionDate)" />
</label>
</p>
<p>
<strong>Captain's Name</strong>
</p>
<p>
<label>
Firstname:
<InputText @bind-Value="starship.CaptainsName.Firstname" disabled="@disabled" />
<ValidationMessage For="@(() => starship.CaptainsName.Firstname)" />
</label>
</p>
<p>
<label>
Lastname:
<InputText @bind-Value="starship.CaptainsName.Lastname" disabled="@disabled" />
<ValidationMessage For="@(() => starship.CaptainsName.Lastname)" />
</label>
</p>
<button type="submit" disabled="@disabled">Submit</button>
<p style="@messageStyles">
@message
</p>
<p>
<a href="http://www.startrek.com/">Star Trek</a>,
©1966-2019 CBS Studios, Inc. and
<a href="https://www.paramount.com">Paramount Pictures</a>
</p>
</EditForm>
@code {
private bool disabled;
private string message;
private string messageStyles = "visibility:hidden";
private CustomValidator customValidator;
private Starship starship = new Starship() { ProductionDate = DateTime.UtcNow };
protected override void OnInitialized()
{
base.OnInitialized();
customValidator = new CustomValidator();
starship = new Starship()
{
ProductionDate = DateTime.UtcNow,
Identifier = "1",
Classification = "Defense",
MaximumAccommodation = 100,
IsValidatedDesign = true,
CaptainsName = new PersonsName { Firstname = "John", Lastname = "Kirk" }
};
}
private async Task HandleValidSubmit(EditContext editContext)
{
bool isValid = editContext.Validate(); // Data Annotations validation
if (isValid)
{
BusinessLogicValidation();
}
}
private bool BusinessLogicValidation()
{
customValidator.ClearErrors();
var errors = new Dictionary<string, List<string>>();
if (starship.Classification == "Defense" &&
string.IsNullOrEmpty(starship.Description))
{
errors.Add(nameof(starship.Description),
new List<string>() { "For a 'Defense' ship classification, 'Description' is required." });
}
if (starship.CaptainsName.Firstname != "James")
{
//errors.Add(nameof(starship.CaptainsName.Firstname), new List<string>() { "Firstname must be James" }); // does not work (as expected)!
errors.Add("CaptainsName.Firstname", new List<string>() { "Firstname must be James" });
}
if (errors.Count() > 0)
{
customValidator.DisplayErrors(errors);
return true;
}
return false;
}
}
星际飞船.cs
using System;
using System.ComponentModel.DataAnnotations;
namespace BlazorTest1.Client.Shared
{
public class Starship
{
[Required]
[StringLength(16, ErrorMessage = "Identifier too long (16 character limit).")]
public string Identifier { get; set; }
public string Description { get; set; }
[Required]
public string Classification { get; set; }
[Range(1, 100000, ErrorMessage = "Accommodation invalid (1-100000).")]
public int MaximumAccommodation { get; set; }
[Required]
[Range(typeof(bool), "true", "true", ErrorMessage = "This form disallows unapproved ships.")]
public bool IsValidatedDesign { get; set; }
[Required]
public DateTime ProductionDate { get; set; }
// [ValidateComplexType] // does not work!
public PersonsName CaptainsName { get; set; }
}
}
人名.cs
namespace BlazorTest1.Client.Shared
{
public class PersonsName
{
public string Firstname { get; set; }
public string Lastname { get; set; }
}
}
CustomValidator.cs
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
public class CustomValidator : ComponentBase
{
private ValidationMessageStore messageStore;
[CascadingParameter]
private EditContext CurrentEditContext { get; set; }
protected override void OnInitialized()
{
if (CurrentEditContext == null)
{
throw new InvalidOperationException(
$"{nameof(CustomValidator)} requires a cascading " +
$"parameter of type {nameof(EditContext)}. " +
$"For example, you can use {nameof(CustomValidator)} " +
$"inside an {nameof(EditForm)}.");
}
messageStore = new ValidationMessageStore(CurrentEditContext);
CurrentEditContext.OnValidationRequested += (s, e) =>
messageStore.Clear();
CurrentEditContext.OnFieldChanged += (s, e) =>
messageStore.Clear(e.FieldIdentifier);
}
public void DisplayErrors(Dictionary<string, List<string>> errors)
{
foreach (var err in errors)
{
messageStore.Add(CurrentEditContext.Field(err.Key), err.Value);
}
CurrentEditContext.NotifyValidationStateChanged();
}
public void ClearErrors()
{
messageStore.Clear();
CurrentEditContext.NotifyValidationStateChanged();
}
}
知道为什么我没有收到针对该字段的验证消息吗?
解决方案
推荐阅读
- c - 使用套接字从使用 C 的网络中读取 RFID 设备
- php - 如何在php中使用2个单词搜索目录中的文件
- javascript - d3.js v4 sankey 图——粒子和拖动不起作用
- office-js - 使用函数文件以编程方式打开任务窗格
- python - Pygame 碰撞处理
- python - 为什么使用 re.search(r'regex').group() 做空不会被所有数字做空
- python - Flask 耗尽虚拟环境
- javascript - 为什么 webpack4 生产包总是包含 style-loader、css-loader 和 vue-loader 内容?
- javascript - 异步函数内的 Promise.all 错误:未定义不是函数
- angular - IE vtt轨道背景颜色