ASP.NET MVC + FluentValidation + PartialView > não validação do lado do cliente
-
21-12-2019 - |
Pergunta
Eu uso FluentValidation para validar a minha ASP.NET MVC 5.1 viewmodels (usando o padrão discreto validação do lado do cliente).Eu register/criar o meu validadores através do Ninject (sem atributos no viewmodels):
FluentValidationModelValidatorProvider.Configure(x => x.ValidatorFactory = new NinjectValidatorFactory(_kernel));
AssemblyScanner.FindValidatorsInAssembly(Assembly.GetExecutingAssembly()).ForEach(match => _kernel.Bind(match.InterfaceType).To(match.ValidatorType));
Eu tenho uma visão parcial que é frequentemente utilizado em todo o aplicativo.Esta visão parcial tem o seu próprio viewmodel.O "principal" viewmodel (um para toda a exibição) apenas herda este "parcial" viewmodel.
public class IndexViewModel : PersonalInfoViewModel { ... }
O mesmo padrão é usado no validadores:
public class IndexValidator : PersonalInfoValidator { ... }
Isso funciona bem, e a validação do lado do servidor funciona tão bem como a validação do lado do cliente sobre o "principal" modo de exibição.Mas a validação do lado do cliente na vista parcial não é acionado (não data-val-*
atributos em campos de entrada lá).
Meu "main" view 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)
Minha vista parcial PersonalInfo.cshtml
:
@model PersonalInfoViewModel
@Html.TextBoxFor(x => x.FirstName) // client-side validation does not work
Eu notei que ele funciona quando eu mudar o modelo para a vista parcial para o "principal" viewmodel:
@model IndexViewModel
@Html.TextBoxFor(x => x.FirstName) // client-side validation works
Então eu acho que em algum lugar ao edifício a validação do lado do cliente a correta validador não ter pego e não data-val-*
atributos são injetados em HTML.Mas eu não posso mudou o viewmodel no vista parcial, porque é usado em várias páginas diferentes com diferentes "principais" pontos de vista (todos herdam de PersonalInfoViewModel embora).
Quaisquer ideias sobre como obter o meu validação do lado do cliente que trabalham neste caso?
Atualização
Depois de algumas horas de escavação através da ASP.NET WebStack de origem, descobri que o problema parece ocorrer no TextBoxFor
o método.Lá o ModelMetaData
é criado a partir do modelo - e lá, em algum lugar, começa a usar IndexViewModel
em vez de PersonalInfoViewModel
para obter os metadados para a validação do lado do cliente:
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Html.GetUnobtrusiveValidationAttributes("FirstName", metadata); // no client-side validation attributes found
Mas isso gera a correta validação do lado do cliente atributos se eu não especificar os metadados explicitamente:
Html.GetUnobtrusiveValidationAttributes("FirstName");
Infelizmente, eu não encontrei uma maneira de usar esse conhecimento para minha vantagem até agora.
Solução
Eu não era capaz de encontrar uma boa solução para o meu problema, e não queria brincar com o ASP.NET WebStack fonte de mais, então eu estabeleci-me com uma gambiarra:
Eu "manualmente" injetar a falta data-val-*
atributos ao renderizar os campos de entrada, como este:
@Html.TextBoxFor(x => x.FirstName, Html.GetUnobtrusiveValidationAttributes("FirstName"))
Desde GetUnobtrusiveValidationAttributes
(chamado de stand-alone) cria o correto atributos de HTML eu simplesmente levá-los e adicione-o à caixa de Texto.Definitivamente não é bonito, mas funciona e eu posso ir com o meu trabalho.Se alguém tiver uma solução melhor, eu ficaria muito feliz em ouvi-lo.