You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

IdentityResult验证错误无法在Blazor UI显示的技术求助

解决Blazor组件无法显示Identity更新用户时的DuplicateUserName验证错误

一、优化API错误返回,关联具体字段

当前API将所有错误都添加为全局错误,导致前端无法精准关联到对应输入框。修改API的错误处理逻辑,把Identity的错误代码映射到对应的模型字段:

[HttpPost("EditSaveUser")]
public async Task<ActionResult> EditSaveUser(EditUserModel model)
{
    var user = await _userManager.FindByIdAsync(model.Id);

    if (user == null)
    {
        return BadRequest($"User with Id = {model.Id} cannot be found");
    }
    
    user.Email = model.Email;
    user.UserName = model.UserName;
    user.City = model.City;

    var result = await _userManager.UpdateAsync(user);

    if (result.Succeeded)
    {
        return Ok(result);
    }
    else
    {
        foreach (var error in result.Errors)
        {
            // 根据Identity错误代码绑定到对应字段
            var targetField = error.Code switch
            {
                "DuplicateUserName" => nameof(EditUserModel.UserName),
                "DuplicateEmail" => nameof(EditUserModel.Email),
                _ => ""
            };
            ModelState.AddModelError(targetField, error.Description);
        }
        return BadRequest(ModelState);
    }
}

二、修改AdminService,解析后端错误并返回

原服务方法未处理后端返回的错误信息,需要新增结果封装类并完善请求逻辑:

1. 新增服务结果类

public class ServiceResult
{
    public bool Success { get; set; }
    public Dictionary<string, List<string>> Errors { get; set; } = new();
}

2. 完善EditSaveUser方法

public async Task<ServiceResult> EditSaveUser(EditUserModel model)
{
    var result = await _httpClient.PostAsJsonAsync("/api/administration/EditSaveUser/", model);
    
    var serviceResult = new ServiceResult();
    if (result.IsSuccessStatusCode)
    {
        serviceResult.Success = true;
        return serviceResult;
    }
    
    // 解析后端返回的ModelState错误
    var apiErrors = await result.Content.ReadFromJsonAsync<Dictionary<string, string[]>>();
    if (apiErrors != null)
    {
        foreach (var kvp in apiErrors)
        {
            serviceResult.Errors[kvp.Key] = kvp.Value.ToList();
        }
    }
    serviceResult.Success = false;
    return serviceResult;
}

三、Blazor组件处理错误并同步到验证系统

在组件中注入验证消息存储,将后端错误添加到Blazor的验证体系中:

1. 组件C#逻辑修改

private EditUserModel model = new();
private EditContext? _editContext;
private ValidationMessageStore? _validationMessageStore;

protected override void OnInitialized()
{
    _editContext = new EditContext(model);
    _validationMessageStore = new ValidationMessageStore(_editContext);
}

protected async override Task OnInitializedAsync()
{
    var result = await AdminService.EditUser(Id);
    if (result != null)
    {
        model = result;
        _editContext?.SetModel(model);
    }
}

private async Task HandleSubmit()
{
    // 清空之前的验证错误
    _validationMessageStore?.Clear();
    
    var serviceResult = await AdminService.EditSaveUser(model);
    if (!serviceResult.Success)
    {
        // 将后端错误添加到验证存储
        foreach (var kvp in serviceResult.Errors)
        {
            var field = _editContext?.Field(kvp.Key);
            if (field != null)
            {
                foreach (var error in kvp.Value)
                {
                    _validationMessageStore?.Add(field.Value, error);
                }
            }
            else
            {
                // 无对应字段的错误添加到全局
                _validationMessageStore?.Add(_editContext!.Model, kvp.Value);
            }
        }
        // 通知验证系统更新UI
        _editContext?.NotifyValidationStateChanged();
        return;
    }
    
    // 保存成功后的逻辑(如跳转回用户列表)
    // NavigationManager.NavigateTo("/admin/users");
}

2. 组件UI修改

使用自定义的EditContext,并添加对应字段的验证消息:

<EditForm EditContext="_editContext" OnValidSubmit="HandleSubmit">
    <DataAnnotationsValidator/>
    <ValidationSummary />

    <div class="mb-3">
        <label class="form-label">用户名</label>
        <InputText @bind-Value="model.UserName" class="form-control" />
        <ValidationMessage For="@(() => model.UserName)" class="text-danger" />
    </div>

    <div class="mb-3">
        <label class="form-label">邮箱</label>
        <InputText @bind-Value="model.Email" class="form-control" />
        <ValidationMessage For="@(() => model.Email)" class="text-danger" />
    </div>

    <div class="mb-3">
        <label class="form-label">城市</label>
        <InputText @bind-Value="model.City" class="form-control" />
    </div>

    <button type="submit" class="btn btn-primary">保存</button>
</EditForm>

额外注意事项

  • 确保API路由与AdminService中的请求地址一致,建议使用相对路径避免硬编码域名
  • 检查Identity配置,确保用户名唯一性验证处于启用状态(默认开启)
  • Blazor Server环境下,确认HttpClient的注入配置正确

内容的提问来源于stack exchange,提问作者Anunnaki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 20:40:25