【问题标题】:How to use C# FluentValidation ValidationContext.RootContextData如何使用 C# FluentValidation ValidationContext.RootContextData
【发布时间】:2020-06-07 12:31:21
【问题描述】:

我是 FluentValidation 的新手,我正在尝试创建一个在验证时接受一些上下文/参数的验证器。我创建了一个自定义验证器,在构造函数中我有类似的东西:

RuleFor(request => request.someField).Custom((request, context) => {
    var foo = context.ParentContext.RootContextData["someDependency"];
});

在我的调用代码中:

var validator = new FooValidator();
var context = new ValidationContext<SomeRequest>(request);
context.RootContextData["someDependency"] = someDependency;
validator.Validate(context);

导致:

System.Collections.Generic.KeyNotFoundException: The given key 'someDependency' was not present in the dictionary.

有什么想法吗?我想传入一些上下文参数的原因是它们来自数据库。如果我将其传递给验证器构造函数,那么在调用 validate 方法时,那些上下文参数可能已经过时了。我也不想在验证器构造函数中从数据库中获取数据,因为我还需要在调用 validate 方法之前/之后获取相同的数据,并且在这种情况下无法进行数据库缓存,所以我会喜欢避免不必要的数据库往返。我已经阅读并且正在做的事情似乎与https://docs.fluentvalidation.net/en/latest/advanced.html#root-context-data所描述的相同

【问题讨论】:

  • 我已经复制了您发布的内容,RootContextData 字典具有预期的键/值对。此问题是否发生在 ASP.NET MVC/ASP.NET Core Web 应用程序中?从哪里抛出异常?从这个Validate 调用或控制器?该错误非常冗长,如果您的实际代码与您发布的代码相似,我猜它是作为模型绑定过程的一部分被调用的,您没有机会将依赖项弹出到字典中。如果是这种情况,您可能需要引入一个规则集以确保它仅在服务器端被调用。
  • 谢谢@rgvlee。我正在开发一个 REST API。我如何介绍您提到的规则集?
  • 在我发出相应的REST请求时忘记说错误发生了。

标签: c# fluentvalidation


【解决方案1】:

正如我的 OP 评论中提到的,代码看起来不错,但它可能在 MVC 验证管道阶段失败,并且永远不会进入您的 Validate 调用。就前者而言,您还没有将依赖项添加到字典中,所以它会出错。

可能有几种方法可以解决它。我的第一个想法是引入一个规则集,因此该规则仅在您的 Validate 调用中执行服务器端。 doco 中有一个whole section on rule sets,它很好地涵盖了它。您可能需要将它与CustomizeValidator attribute 结合使用,这样规则集就不会在 MVC 验证管道中执行(我在使用服务器端规则集时从来不需要这样做,但我'已经提到它的完整性)。

这样做的好处是您可能不需要更改很多现有代码;您已经提到您将许多依赖项加载到验证上下文中,因此它可能很合适。

另一种看起来不错但我自己没有尝试过的方法是在BeforeMvcValidation validation interceptor 中填充验证上下文。此选项的值将取决于您如何收集这些依赖项以及它们是否用于验证以外的任何其他用途。与基于您的实现描述的规则集相比,它可能需要更多的努力。

【讨论】:

    猜你喜欢
    • 2014-12-16
    • 2021-10-16
    • 2016-06-22
    • 2018-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-13
    • 1970-01-01
    相关资源
    最近更新 更多