FluentValidation – 如何实现 WithMessageAsync?

huangapple go评论76阅读模式
英文:

FluentValidation - how to implement a WithMessageAsync?

问题

使用FluentValidation在我们的.NET MVC项目中,我需要通过我们的翻译服务运行Fluent Validation消息的翻译。这个翻译服务会异步地从我们的数据库中获取翻译后的文本。

没有翻译的情况下:

RuleFor(x => x.FirstName).NotEmpty().WithMessage("First name is empty!");

有翻译的情况下(如果我们的翻译不是异步的):

RuleFor(x => x.FirstName).NotEmpty().WithMessage(_siteTextTranslationService.Translate("First name is empty!"));

问题是,当它是异步的时候,我唯一找到的方法是:

When(model => model.FirstName.IsNullOrWhiteSpace(), () =>
{
    RuleFor(p => p.FirstName)
        .CustomAsync(async (value, context, ct) =>
         {
             var message = await _siteTextTranslationService.Translate("First name is empty!");
             context.AddFailure(message);
         });
});

但这比起一开始就不使用Fluent Validation来说还要更加繁琐!而且我们不能调用Fluent Validation的许多验证函数,比如 NotEmpty(),这意味着我们失去了Fluent Validation 的很多优点。

我如何在保持Fluent流畅性的同时异步调用一个服务的翻译方法,或者换句话说,如何实现一个 WithMessageAsync

英文:

In our .NET MVC project using FluentValidation I need to run the messages fluent validation through our translation service. This translation service asynchronously pulls the translated text from our database.

Without translation:

RuleFor(x => x.FirstName).NotEmpty().WithMessage("First name is empty!");

With translation (if our translate wasn't async)

RuleFor(x => x.FirstName).NotEmpty().WithMessage(_siteTextTranslationService.Translate("First name is empty!"));

The problem is when it is async the only way I have found to do it would be:

When(model => model.FirstName.IsNullOrWhiteSpace(), () =>
{
    RuleFor(p => p.FirstName)
        .CustomAsync(async (value, context, ct) =>
         {
             var message = await _siteTextTranslationService.Translate("First name is empty!");
             context.AddFailure(message);
         });
});

But this is more boilerplate than just not using fluent validation in the first place! Not only that we can't call much of fluent validations validation function such as NotEmpty(), meaning we lose out on much of the fluent part of fluentvalidation.

How can I asynchronously call a service translation method on fluentvalidation error messages while keeping a fluent flow, or to put it another way, how to implement a WithMessageAsync?

答案1

得分: 1

你可以将这个样板代码封装成扩展方法,然后在你的Fluent Validation构造函数中使用它

```csharp
public static class FluentValidationExtensions
{
    public static void WithMessageAsync<T, TProperty>(this IRuleBuilderOptions<T, TProperty> ruleBuilderOptions,
                                                      Task<string> messageTask)
    {
        ruleBuilderOptions.CustomAsync(async (_, context, _) =>
        {
            var message = await messageTask;
            context.AddFailure(message);
        });
    }
}

然后在你的验证器中使用:

RuleFor(model => model.FirstName)
    .NotEmpty()
    .WithMessageAsync(_siteTextTranslationService.Translate("First name is empty!"));

当然,你可以添加方法重载以支持带有取消令牌等参数的任务。注意,我丢弃了未使用的参数_


<details>
<summary>英文:</summary>

You can wrap this boilerplate in extension method, and then use that in your fluent validation constructor.

```csharp
public static class FluentValidationExtensions
{
    public static void WithMessageAsync&lt;T, TProperty&gt;(this IRuleBuilderOptions&lt;T, TProperty&gt; ruleBuilderOptions,
                                                      Task&lt;string&gt; messageTask)
    {
        ruleBuilderOptions.CustomAsync(async (_, context, _) =&gt;
        {
            var message = await messageTask;
            context.AddFailure(message);
        });
    }
}

And then in your validator:

RuleFor(model =&gt; model.FirstName)
    .NotEmpty()
    .WithMessageAsync(_siteTextTranslationService.Translate(&quot;First name is empty!&quot;));

Of course, you may add method overloads to support parametrized tasks, such as with cancellation token. Note that I discarded unused parameters with _.

huangapple
  • 本文由 发表于 2023年6月5日 22:47:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76407629.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定