Pergunta

Estou tentando integrar o NHibernate.Validator com validações do lado do cliente ASP.NET MVC, e o único problema que encontrei é que simplesmente não consigo converter a mensagem não interpolada em uma mensagem legível por humanos.Achei que seria uma tarefa fácil, mas acabou sendo a parte mais difícil da validação do lado do cliente.O principal problema é que, por não ser do lado do servidor, na verdade só preciso dos atributos de validação que estão sendo usados ​​e não tenho uma instância ou qualquer outra coisa em mãos.

Aqui estão alguns trechos do que já estou tentando:

// Get the the default Message Interpolator from the Engine
IMessageInterpolator interp = _engine.Interpolator;
if (interp == null)
{
  // It is null?? Oh, try to create a new one
  interp = new NHibernate.Validator.Interpolator.DefaultMessageInterpolator();
}

// We need an instance of the object that needs to be validated, se we have to create one
object instance = Activator.CreateInstance(Metadata.ContainerType);

// we enumerate all attributes of the property. For example we have found a PatternAttribute
var a = attr as PatternAttribute;

// it seems that the default message interpolator doesn't work, unless initialized
if (interp is NHibernate.Validator.Interpolator.DefaultMessageInterpolator)
{
  (interp as NHibernate.Validator.Interpolator.DefaultMessageInterpolator).Initialize(a);
}

// but even after it is initialized the following will throw a NullReferenceException, although all of the parameters are specified, and they are not null (except for the properties of the instance, which are all null, but this can't be changed)
var message = interp.Interpolate(new InterpolationInfo(Metadata.ContainerType, instance, PropertyName, a, interp, a.Message));

Eu sei que o código acima é um código bastante complexo para uma pergunta aparentemente simples, mas ainda estou sem solução.Existe alguma maneira de obter a string interpolada do NHValidator?

Foi útil?

Solução

Ok, sei que esta é uma pergunta antiga, mas me deparei com isso ao tentar fazer a mesma coisa e isso me ajudou a começar - então pensei em fornecer uma resposta.

Acho que o código da pergunta estava no caminho certo, mas há alguns problemas.O interpolador não foi completamente inicializado com o ResourceManager e Culture detalhes, e não parece permitir o fato de que você só pode ter um DefaultMessageInterpolator por atributo de validação.Além disso, você não precisa de uma instância do objeto que está validando para obter uma mensagem interpolada.

No código da pergunta, onde você está inicializando o interpolador com o valor do atributo, você também precisa inicializar o interpolador com detalhes do ResourceManager ser usado.

Isso pode ser feito usando o sobrecarregado Initialize método ativado DefaultMessageInterpolator que tem a seguinte assinatura:

    public void Initialize(ResourceManager messageBundle, 
                           ResourceManager defaultMessageBundle, 
                           CultureInfo culture)

O primeiro parâmetro é um ResourceManager definido pelo usuário caso você queira usar seu próprio arquivo de recursos para mensagens de erro, você pode passar um nulo se quiser apenas usar o ResouceManager padrão, o segundo parâmetro é o ResourceManager padrão - você pode passar

  new ResourceManager( 
      NHibernate.Validator.Cfg.Environment.BaseNameOfMessageResource,
      Assembly.GetExecutingAssembly());

para isso, o último parâmetro é a cultura a ser usada, (NHibernate.Validator vem com arquivos de recursos com mensagens de validação em vários idiomas) - se você passar um nulo para isso ele apenas usará CultureInfo.CurrentCulture

Por último, você só pode ter um DefaultMessageInterpolator por atributo, então você precisará criar um novo DefaultMessageInterpolator para cada atributo de validação.Você poderia fazer uso do DefaultMessageInterpolatorAggregator para lidar com isso, ou apenas crie o seu próprio.

Espero que isso ajude alguém.

Outras dicas

Obrigado por sua ajuda a todos - eu votaria positivamente se pudesse.Eu só queria acrescentar que, além da primeira chamada Initialize no DefaultMessageInterpolator que Stank ilustra, também tive que fazer uma segunda chamada Initialize diferente para inicializá-la completamente (eu estava recebendo algumas exceções de referência nula usando apenas a primeira chamada).Meu código é o seguinte:

string interpolatedMessage = "";
DefaultMessageInterpolator interpolator = new DefaultMessageInterpolator();

interpolator.Initialize(null,
    new ResourceManager(
        NHibernate.Validator.Cfg.Environment.BaseNameOfMessageResource,
        Assembly.Load("NHibernate.Validator")),
        CultureInfo.CurrentCulture);

interpolator.Initialize(attribute as Attribute);

if (attribute is IValidator && attribute is IRuleArgs)
{
    IValidator validator = attribute as IValidator;
    IRuleArgs ruleArgs = attribute as IRuleArgs;

    InterpolationInfo interpolationInfo = new InterpolationInfo(
        validatableType, 
        null, 
        propertyName, 
        validator,
        interpolator, 
        ruleArgs.Message);

    interpolatedMessage = interpolator.Interpolate(interpolationInfo);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top