ASP.NET MVC + FluentValidation + PartialView > 无客户端验证
-
21-12-2019 - |
题
我使用 FluentValidation 来验证 ASP.NET MVC 5.1 视图模型(使用默认的不显眼的客户端验证)。我通过 Ninject 注册/创建验证器(视图模型上没有属性):
FluentValidationModelValidatorProvider.Configure(x => x.ValidatorFactory = new NinjectValidatorFactory(_kernel));
AssemblyScanner.FindValidatorsInAssembly(Assembly.GetExecutingAssembly()).ForEach(match => _kernel.Bind(match.InterfaceType).To(match.ValidatorType));
我有一个在整个应用程序中经常使用的部分视图。该部分视图有自己的视图模型。“主”视图模型(整个视图的视图模型)只是继承自这个“部分”视图模型。
public class IndexViewModel : PersonalInfoViewModel { ... }
验证器上使用相同的模式:
public class IndexValidator : PersonalInfoValidator { ... }
这工作得很好,服务器端验证和“主”视图上的客户端验证一样有效。但是不会触发对部分视图的客户端验证(没有 data-val-*
输入字段上的属性)。
我的“主要”观点 Index.cshtml
@model IndexViewModel
@Html.TextBoxFor(x => x.SomeProperty) // client-side validation works fine
@Html.Partial("PersonalInfo") // client-side validation in the partial view does not work (see below)
我的部分看法 PersonalInfo.cshtml
:
@model PersonalInfoViewModel
@Html.TextBoxFor(x => x.FirstName) // client-side validation does not work
我注意到,当我将部分视图的模型更改为“主”视图模型时,它会起作用:
@model IndexViewModel
@Html.TextBoxFor(x => x.FirstName) // client-side validation works
所以我猜想在构建客户端验证时,正确的验证器不会被拾取,并且没有 data-val-*
属性被注入到 HTML 中。但我无法更改部分视图上的视图模型,因为它在具有不同“主”视图的多个不同页面上使用(尽管全部继承自 PersonalInfoViewModel)。
关于如何让我的客户端验证在这种情况下工作有什么想法吗?
更新
经过几个小时的挖掘 ASP.NET WebStack 源代码后,我发现问题似乎发生在 TextBoxFor
方法。那里有 ModelMetaData
是从模型创建的 - 并且在某个地方开始使用 IndexViewModel
代替 PersonalInfoViewModel
获取客户端验证的元数据:
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Html.GetUnobtrusiveValidationAttributes("FirstName", metadata); // no client-side validation attributes found
但是,如果我没有明确指定元数据,这会生成正确的客户端验证属性:
Html.GetUnobtrusiveValidationAttributes("FirstName");
不幸的是,到目前为止,我还没有找到一种方法来利用这些知识来为我所用。
解决方案
我无法找到一个很好的解决方案来解决我的问题,并且不想再使用 ASP.NET WebStack 源代码,所以我采用了一个丑陋的解决方法:
我“手动”注入缺失的 data-val-*
渲染输入字段时的属性,如下所示:
@Html.TextBoxFor(x => x.FirstName, Html.GetUnobtrusiveValidationAttributes("FirstName"))
自从 GetUnobtrusiveValidationAttributes
(称为独立)构建正确的 HTML 属性,我只需将它们添加到 TextBox 中即可。绝对不漂亮,但它有效,我可以继续我的工作。如果有人有更好的解决方案,我会很高兴听到。