英文:
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<T, TProperty>(this IRuleBuilderOptions<T, TProperty> ruleBuilderOptions,
Task<string> messageTask)
{
ruleBuilderOptions.CustomAsync(async (_, context, _) =>
{
var message = await messageTask;
context.AddFailure(message);
});
}
}
And then in your validator:
RuleFor(model => model.FirstName)
.NotEmpty()
.WithMessageAsync(_siteTextTranslationService.Translate("First name is empty!"));
Of course, you may add method overloads to support parametrized tasks, such as with cancellation token. Note that I discarded unused parameters with _
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论