每当我运行附带调试器的以下任一单元测试时,我都会VerificationException在此时获得一个内部FluentValidation代码(如果需要,将在稍后发布整个堆栈跟踪):
at FluentValidation.Resources.LocalizedStringSource.CreateFromExpression(Expression`1 expression, IResourceAccessorBuilder resourceProviderSelectionStrategy)
in ...\FluentValidation\Resources\LocalizedStringSource.cs:line 66
Run Code Online (Sandbox Code Playgroud)
测试是:
using FluentValidation;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var c = new MyClass();
var v = new MyValidator();
v.Validate(c);
}
[TestMethod]
public void TestMethod2()
{
Exception ex = null;
var done = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(
o =>
{
try
{
TestMethod1();
}
catch (Exception e)
{
ex = e;
}
finally
{
done.Set();
}
});
done.WaitOne(); …Run Code Online (Sandbox Code Playgroud) FluentValidation 库相对于 .NET System.ComponentModel.DataAnnotations 有什么优势?
它是否提供更灵活的验证,因为它没有在属性上进行注释(静态字段验证),例如根据另一个属性值验证属性?
我有以下 DTO:
public class SomethingRequest {
public string Code { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
Code 必须是唯一的,所以我创建了一个验证器来检查是否已经有提供代码的记录,如下所示
public class SomethingValidator: AbstractValidator<SomethingRequest>
{
public SomethingValidator(ISomethingRepository repo) {
RuleFor(something => something.Code).Must(BeUnique);
}
private bool BeUnique(string code) { ... uniqueness check... }
}
Run Code Online (Sandbox Code Playgroud)
当我使用验证功能时,验证器会自动连接到所有带有 的方法SomethingRequest,这真的很棒。
当条件失败时,我想返回409 ConflictHTTP 状态代码,但400 Bad Request总是返回。
所以,问题是:
400 BadRequest验证器的状态代码吗?例如,我有两个验证规则的验证器:
// Rule 1
RuleFor(o => o.Email).Must((email) => this.GetDataDataFromDB(email) != 0)
.WithMessage("User with provided Email was not found in database!");
// Rule 2
RuleFor(o => o.Email).Must((email) => this.GetDataDataFromDB(email) >= 1)
.WithMessage("There are multiple users with provided Email in database!");
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,使用相同的方法对数据库进行了两次调用.如何调用一次并将数据重用于其他规则?
显示错误消息时的另一个问题:
RuleFor(o => o.Email).Must((email) => this.GetDataDataFromDB(email) >= 1)
.WithMessage("There are multiple users with following Email '{0}' in database!",
(model, email) => { return email; });
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来显示错误消息,而不是一直写这些lambda表达式来检索属性?就像在某处保存模型一样,然后再使用它.
简单易行的解决方案会很棒!
在负责验证的类内部我有简单的规则:
RuleFor(u => u.Id)
.Cascade(CascadeMode.StopOnFirstFailure)
.NotEmpty().WithMessage("Id is required")
.Must(ValidateId);
Run Code Online (Sandbox Code Playgroud)
下面是我的ValidateId功能:
private bool ValidateId(CreateAccountBindingModel model, string id, PropertyValidatorContext context)
{
if (id=="test")
{
context.Rule.CurrentValidator.ErrorCodeSource = new StaticStringSource("You are testing");
return false;
}
var idValid = IdValidator.IsValid(id);
if (!idValid)
{
context.Rule.CurrentValidator.ErrorCodeSource = new StaticStringSource("Id is invalid");
return false;
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
如果我运行我的验证器,我会得到默认错误,而不是我在函数中指定的自定义错误。
我尝试使用以下方法设置它们:
context.Rule.CurrentValidator.ErrorCodeSource = new StaticStringSource("Id is invalid");
Run Code Online (Sandbox Code Playgroud)
但没有任何运气。
如何在验证函数中定义错误消息?
这是我的验证类之一:
public class StocksValidator : AbstractValidator<Stocks>
{
public StocksValidator()
{
RuleFor(x => x.SellerId).GreaterThan(1).WithMessage("SellerId should be greater than 1")
.LessThan(100).WithMessage("SellerId should be less than 100");
RuleFor(x => x.SellerType).GreaterThan(101).WithMessage("SellerType should be greater than 101")
.LessThan(200).WithMessage("SellerType should be less than 200");
RuleFor(x => x.SourceId).GreaterThan(201).WithMessage("SourceId should be greater than 201")
.LessThan(300).WithMessage("SourceId should be less than 300");
}
}
Run Code Online (Sandbox Code Playgroud)
我知道这些消息,例如{field}应该少于{x}应该位于公共位置,而不是这里。但是我不知道如何集中他们?
一种方法是使用所有这些常量字符串创建新的c#文件。这很简单。
在Web API中使用本地化和流畅的验证。这有什么好处。我在哪里可以找到好的教程?
关注点分离 (SoC)
在 ConfigureServices 中注册的依赖指令(启动类的方法)由不同的 DI 组成,如 Repository、Fluent Validations 等。
我将如何将 DI 注册分成单独的文件(如下所示)
c# dependency-injection separation-of-concerns repository-pattern fluentvalidation
我有一个 MediatR 管道行为,用于使用 FluentValidation 库验证命令。我看过很多例子,你从行为中抛出 ValidationException,这对我来说很好用。但是在我的场景中,我想用验证错误更新我的响应对象。
我能够构建和运行以下代码。当我在 if 语句中设置断点时,CommandResponse 是按预期使用验证错误构造的 - 但是当原始调用者收到响应时,它为空:
public class RequestValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
public RequestValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var context = new ValidationContext(request);
// Run the associated validator against the request
var failures = _validators
.Select(v => v.Validate(context))
.SelectMany(result => result.Errors)
.Where(f => f != null)
.ToList();
if(failures.Count != 0)
{
var commandResponse …Run Code Online (Sandbox Code Playgroud) 我有一个像这样的简单表单,它使用了 @Html.EditorFor 扩展名:
<form method="post">
@Html.EditorFor(x => x.SystemSettings.EmailFromAddress)
<submit-button title="Save"></submit-button>
</form>
Run Code Online (Sandbox Code Playgroud)
我想利用 .NET Core 的标签助手,让我的表单看起来像这样:
<form method="post">
<editor asp-for="SystemSettings.EmailFromAddress"/>
<submit-button title="Save"></submit-button>
</form>
Run Code Online (Sandbox Code Playgroud)
我最终也想拥有自己的自定义标签助手,这样我就可以做这样的事情:
<text-box asp-for="SystemSettings.EmailFromAddress"></text-box>
Run Code Online (Sandbox Code Playgroud)
我有一个由 @Html.EditorFor 扩展呈现的字符串模板:
@model string
<div class="form-group">
<label asp-for="@Model" class="m-b-none"></label>
<span asp-description-for="@Model" class="help-block m-b-none small m-t-none"></span>
<div class="input-group">
<input asp-for="@Model" class="form-control" />
<partial name="_ValidationIcon" />
</div>
<span asp-validation-for="@Model" class="validation-message"></span>
</div>
Run Code Online (Sandbox Code Playgroud)
为此,我看到有人实现了一个EditorTagHelper,它看起来像这样:
[HtmlTargetElement("editor", TagStructure = TagStructure.WithoutEndTag,
Attributes = ForAttributeName)]
public class EditorTagHelper : TagHelper
{
private readonly IHtmlHelper _htmlHelper;
private const string …Run Code Online (Sandbox Code Playgroud) 只需将基于 EditForm 的包装器放在一起并使用 Fluent Validation。我在这个表单上创建了两个属性,如下所示:
if (ModelValidation)
{
editContext.OnValidationRequested +=
(sender, eventArgs) => ValidateModel((EditContext)sender, messages);
}
if (FieldValidation)
{
editContext.OnFieldChanged +=
(sender, eventArgs) => ValidateField(editContext, messages, eventArgs.FieldIdentifier);
}
Run Code Online (Sandbox Code Playgroud)
这允许在 OnFieldChanged(值更改,在退出字段上验证)或按下提交按钮时进行验证(OnValidationRequested)
但是,如果我说一个文本字段是空的(应该是非空的)选项卡,则 OnFieldChanged() 处理程序不会触发......(该字段没有改变也就不足为奇了)。有没有办法强制调用 OnFieldChanged() 或终止焦点处理程序而不使用 javascript?
fluentvalidation ×10
c# ×8
asp.net-core ×2
asp.net ×1
asp.net-mvc ×1
autofac ×1
blazor ×1
cqrs ×1
debugging ×1
exception ×1
intellitrace ×1
localization ×1
mediatr ×1
servicestack ×1
tag-helpers ×1