c# - 如何在自定义验证属性中获取/注入(inject)服务

标签 c# validation .net-core dependency-injection blazor

我们在 .NET Core 3.1.5 上,这是一个 Blazor 服务器应用程序。
我们有一个 ValidationAttribute 并且需要访问外部服务来验证对象。
ValidationAttribute 有 IsValid 方法:
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
ValidationContext 有一个 GetService 方法,它委托(delegate)给 ServiceProvider 的一个实例。
不幸的是,服务提供者字段从未初始化,因此我们无法检索任何服务。
这是在 Mvc 中提出(并修复)的:aspnet/Mvc#6346
但是我们的验证器是通过以下两个之一调用的:
https://github.com/dotnet/aspnetcore/blob/master/src/Components/Forms/src/EditContextDataAnnotationsExtensions.cs#L47
https://github.com/dotnet/aspnetcore/blob/master/src/Components/Forms/src/EditContextDataAnnotationsExtensions.cs#L75
后来在堆栈中,服务提供者也永远不会设置。
我犹豫是否要打开一个错误(但可以这样做),但这对我来说似乎是错误的(或者至少应该记录在案)。
任何 Google 搜索最终都会出现在这篇博客文章中,但正如我刚才提到的那样,这不起作用。
所以我们的问题是:将服务注入(inject)到 ValidationAttribute 中的正确方法是什么,或者更一般地说,验证需要调用外部服务的模型字段的正确方法是什么?
statup.cs :

services.AddTransient<IMarktTypDaten, MarktTypDaten>();
我们尝试注入(inject)服务并应用验证的类。
public class MarktTypNameValidation : ValidationAttribute {
    protected override ValidationResult IsValid(object value, ValidationContext validationContext) {    
        var service = (IMarktTypDaten) validationContext.GetRequiredService(typeof(IMarktTypDaten));
        ...some code...
        return ValidationResult.Success;
    }
}
调用 GetRequiredService 时出现异常消息: 'No service for type 'DataAccessLibrary.Interfaces.IMarktTypDaten' has been registered.它也在 Github 上发布:https://github.com/dotnet/aspnetcore/discussions/23305
另外:我在 15 年左右第一次使用 C#/.NET,请温柔 ;-)

最佳答案

正如 Steven 在评论部分所建议的那样,你不应该那样做。相反,您可以按照以下代码片段中的描述执行此操作,其中一部分只是伪代码,用于指出您需要做什么......它不应该按原样工作。
您可以为此覆盖 EditContext 的 FieldChanged 方法。
假设您有一个带有电子邮件地址输入字段的表单,并且您想检查此电子邮件是否已被其他用户使用...检查
输入的电子邮件地址的可用性,您必须调用您的数据存储并验证这一点。请注意,FieldChanged 方法中描述的某些操作可以移动到单独的验证服务...

<EditForm EditContext="@EditContext" 
                                      OnValidSubmit="HandleValidSubmit">
    <DataAnnotationsValidator />

    <div class="form-group">
        <label for="name">Name: </label>
        <InputText Id="name" Class="form-control" @bind- 
                                     Value="@Model.Name"></InputText>
        <ValidationMessage For="@(() => Model.Name)" />

    </div>
    <div class="form-group">
        <label for="body">Text: </label>
        <InputText Id="body" Class="form-control" @bind-Value="@Model.Text"></InputText>
        <ValidationMessage For="@(() => Model.Text)" />
    </div>
    <div class="form-group">
        <label for="body">Email: </label>
        <InputText Id="body" Class="form-control" @bind-Value="@Model.EmailAddress"></InputText>
        <ValidationMessage For="@(() => Model.EmailAddress)" />
    </div>
    <p>

        <button type="submit">Save</button>

    </p>
</EditForm>

@code
    {

    private EditContext EditContext;
    private Comment Model = new Comment();
    ValidationMessageStore messages;

    protected override void OnInitialized()
    {
        EditContext = new EditContext(Model);
        EditContext.OnFieldChanged += EditContext_OnFieldChanged;
        messages = new ValidationMessageStore(EditContext);

        base.OnInitialized();
    }

    // Note: The OnFieldChanged event is raised for each field in the 
    // model. Here you should validate the email address
    private void EditContext_OnFieldChanged(object sender, 
                                               FieldChangedEventArgs e)
    {
         // Call your database to check if the email address is 
         // available
         // Retrieve the value of the input field for email
         // Pseudocode...
         var email = "enet.xxxx@gmail.com";
         var exists =  VerifyEmail(email);
         
         messages.Clear();
         // If exists is true, form a message about this, and add it 
         // to the messages object so that it is displayed in the  
         // ValidationMessage component for email
       
    }

}
希望这可以帮助...

关于c# - 如何在自定义验证属性中获取/注入(inject)服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62559817/

相关文章:

c# - Unity Netcode (MLAPI) 主机移动且客户端连接,但客户端不移动

c# - EF Core 已跟踪具有相同 id 的实体

.net-core - .Net Core 的控制台应用程序 list 图标未更新

c# - 如何在 Windows 窗体应用程序中使用 C#.NET 正确实现 MVC

c# - 如何制作这样的数组

c# - 无法将列名称放入GetString

c# - 我可以将 MVC 2 DataAnnotation 属性添加到现有属性吗?

mongodb - Mongoose 验证子文档数组

asp.net - 如何只验证网页中的某些元素而不验证其他元素?

c# - File.Exists 可以抛出异常吗?