Rog*_*MKE 8 asp.net-core-webapi blazor
我正在学习 Blazor,并且我有一个 WebAssembly 客户端应用程序。
我在服务器上创建了一个 WebAPI,它在标准数据注释验证之外做了一些额外的验证。例如,当它尝试将记录写入数据库时,它会检查是否不存在具有相同电子邮件地址的其他记录。某些类型的验证不能在客户端可靠地发生,特别是在竞争条件可能产生不良结果的情况下。
API 控制器向客户端返回一个ValidationProblem结果,Postman 将结果的正文显示为:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "|f06d4ffe-4aa836b5b3f4c9ae.",
"errors": {
"Email": [
"The email address already exists."
]
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,验证错误位于 JSON 中的“errors”数组中。
回到 Blazor 客户端应用程序,我有一个典型的 HandleValidSubmit 函数,它将数据发布到 API 并接收响应,如下所示:
private async void HandleValidSubmit()
{
var response = await Http.PostAsJsonAsync<TestModel>("api/Test", testModel);
if (response.StatusCode != System.Net.HttpStatusCode.Created)
{
// How to handle server-side validation errors?
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,如何最好地处理服务器端验证错误?用户体验应该与任何其他验证错误相同,突出显示该字段,显示验证消息,以及页面顶部的摘要。
我最终通过创建一个 ServerValidator 组件解决了这个问题。我会在此处发布代码,以防其他人寻求解决相同问题的方法。
此代码假定您正在调用 Web API 端点,如果出现问题,该端点将返回 ValidationProblem 结果。
public class ServerValidator : ComponentBase
{
[CascadingParameter]
EditContext CurrentEditContext { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
if (this.CurrentEditContext == null)
{
throw new InvalidOperationException($"{nameof(ServerValidator)} requires a cascading " +
$"parameter of type {nameof(EditContext)}. For example, you can use {nameof(ServerValidator)} " +
$"inside an EditForm.");
}
}
public async void Validate(HttpResponseMessage response, object model)
{
var messages = new ValidationMessageStore(this.CurrentEditContext);
if (response.StatusCode == HttpStatusCode.BadRequest)
{
var body = await response.Content.ReadAsStringAsync();
var validationProblemDetails = JsonSerializer.Deserialize<ValidationProblemDetails>(body);
if (validationProblemDetails.Errors != null)
{
messages.Clear();
foreach (var error in validationProblemDetails.Errors)
{
var fieldIdentifier = new FieldIdentifier(model, error.Key);
messages.Add(fieldIdentifier, error.Value);
}
}
}
CurrentEditContext.NotifyValidationStateChanged();
}
// This is to hold the response details when the controller returns a ValidationProblem result.
private class ValidationProblemDetails
{
[JsonPropertyName("status")]
public int? Status { get; set; }
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("errors")]
public IDictionary<string, string[]> Errors { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
要使用这个新组件,您需要在 EditForm 中添加该组件:
<EditForm Model="agency" OnValidSubmit="HandleValidSubmit">
<ServerValidator @ref="serverValidator" />
<ValidationSummary />
... put all your form fields here ...
</EditForm>
Run Code Online (Sandbox Code Playgroud)
最后,您可以在您的@code部分开始验证:
@code {
private TestModel testModel = new TestModel();
private ServerValidator serverValidator;
private async void HandleValidSubmit()
{
var response = await Http.PostAsJsonAsync<TestModel>("api/TestModels", testModel);
if (response.StatusCode != System.Net.HttpStatusCode.Created)
{
serverValidator.Validate(response, testModel);
}
else
{
Navigation.NavigateTo(response.Headers.Location.ToString());
}
}
}
Run Code Online (Sandbox Code Playgroud)
从理论上讲,这应该允许您完全绕过客户端验证并依靠您的 Web API 来完成。在实践中,我发现 Blazor 会在您的模型上有注释时执行客户端验证,即使<DataAnnotationsValidator />您的表单中没有包含 a 。但是,它仍然会在服务器上捕获任何验证问题并将它们返回给您。
| 归档时间: |
|
| 查看次数: |
2652 次 |
| 最近记录: |