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

Blazor数据注解验证中无法从ValidationContext获取EFCore上下文

解决Blazor数据注解验证中注入EFCore Context的问题

核心问题分析

Blazor默认的ValidationContext并未关联应用的DI服务提供者,导致自定义ValidationAttribute无法直接获取EFCore Context等依赖服务,这是你遇到各类报错的根本原因。

步骤1:确认服务注册正确性

首先确保IMyContext及实现类已在Program.cs中正确注册:

// 注册DbContext
builder.Services.AddDbContext<MyContext>(options => 
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
// 注册接口到实现的映射
builder.Services.AddScoped<IMyContext>(sp => sp.GetRequiredService<MyContext>());

步骤2:自定义ValidationContext并传入服务提供者

在Blazor组件中,手动创建关联DI容器的ValidationContext,替代默认的验证逻辑:

  1. 组件中注入IServiceProvider:
[Inject]
private IServiceProvider ServiceProvider { get; set; }
  1. 自定义提交处理方法,手动执行验证:
private async Task HandleSubmit()
{
    var validationContext = new ValidationContext(YourModelInstance)
    {
        ServiceProvider = ServiceProvider
    };
    
    var validationResults = new List<ValidationResult>();
    bool isValid = Validator.TryValidateObject(
        YourModelInstance, 
        validationContext, 
        validationResults, 
        validateAllProperties: true
    );

    if (isValid)
    {
        // 执行提交逻辑,比如保存到数据库
        await using var dbContext = ServiceProvider.GetRequiredService<IMyContext>();
        dbContext.YourEntities.Add(YourModelInstance);
        await dbContext.SaveChangesAsync();
    }
    else
    {
        // 将验证错误同步到EditContext,更新UI状态
        foreach (var result in validationResults)
        {
            foreach (var memberName in result.MemberNames)
            {
                EditContext.SetFieldCssClass(
                    FieldIdentifier.Create(YourModelInstance, memberName), 
                    "invalid"
                );
            }
        }
    }
}

修正后的自定义ValidationAttribute

此时你的MyEntityExistsAttribute可以保持最初的实现,因为ValidationContext已能正确获取DI服务:

public class MyEntityExistsAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value is not int id)
        {
            return new ValidationResult("ID必须是数字");
        }
        
        var dbContext = validationContext.GetRequiredService<IMyContext>();

        return dbContext.MyEntity.Any(s => s.Id == id) 
            ? ValidationResult.Success 
            : new ValidationResult("该ID不存在");
    }
}

错误原因解释

  • No service for type 'IMyContext' registered:要么是服务未在DI容器中注册,要么是默认ValidationContext的ServiceProvider为空,无法获取服务。
  • No service for type 'IServiceScopeFactory' registered:默认ValidationContext无有效ServiceProvider,调用CreateScope时无法找到依赖的IServiceScopeFactory服务。
  • context为null:同样是因为ValidationContext的ServiceProvider为空,GetService返回null。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 21:27:33