Utilizando Asp.Net Validator com controles HTML    

Nas postagens deste Blog vou falar muito de Asp.Net, principalmente com uso de Ajax. Vou falar bastante de Jquery e outras tecnologias Client Side. Com isso, vou ter o habito de não usar Asp.Net Server Controls.

Quando se usa muito Java Script, é normal que se pare de usar Server Control progressivamente, pois assim fica mais fácil acessar IDs dos controles com JQuery, por exemplo. Naturalmente, com o Asp.Net 4, muitos desses problemas de IDs são solucionados com a nova propriedade ClientIDMode, que controla como o servidor gerará os IDs, porém, se estamos usando muitos códigos no lado do cliente e estamos comunicando com o servidor via Ajax, o melhor é poupar processamento desnecessário do Asp.Net, usando menos controles Server Side, renderizando assim cada vez mais rápida uma página no navegador do usuário.

Contudo, quando paramos de usar controles do Asp.Net, outros problemas surgem no processo de desenvolvimento, por exemplo o uso dos Validators.

Como funciona um Validator?

Não vou entrar no detalhe de como funciona um Validator, apenas o básico para contextualizar este post.

Adicionamos Validator a Página como abaixo:

 

Em um Validator como o acima, o Asp.Net identifica o controle a ser validado (txtNome) utilizando o método FindControl, passando como parâmetro o valor informando na propriedade ControlToValidate. Para um controle se encontrado por este método, ele deve estar na coleção de controles da página, portanto, se o seu controle não for ServerControl, ele não será encontrado, afinal um simples controle HTML não é adicionado à coleção de controles da página.

Além de utilizar o método FindControl, o Asp.Net também utiliza o método ControlPropertiesValid, que tem a função de, além de saber se o controle é retornado pelo FindControl, saber se as propriedades básicas do Validator estão preenchidas, como a própria propriedade ControlToValidate.

Desta forma, os Validators do Asp.Net, da forma que são atualmente, não serviriam para validar controles de HTML simples, devido a estes dois métodos citados acima funcionarem apenas com ServerControls.

Temos que admitir que os controles de validação do WebForm são de grande ajuda, principalmente se estamos acostumados a utilizar o controle ValidatorCallout do AjaxToolkit, e seria muito interessante que fosse possível utilizar essas facilidades com HTML simples, e assim unir o melhor dos dois mundos (Client e Serve Side).

Quando um Validator é renderizado no HTML, é criado uma variável no JavaScript, com as propriedade que armazenam o ID do controle que deve ser validado e qual função chamar, mais ou menos assim:

var MainContent_reqNome = document.all ? document.all["MainContent_reqNome"] : document.getElementById("MainContent_reqNome");
MainContent_reqNome.controltovalidate = "MainContent_txtNome";
MainContent_reqNome.errormessage = "Preencha o Nome";
MainContent_reqNome.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";
MainContent_reqNome.initialvalue = "";

 

Perceba que ele retorna na propriedade controltovalidate da variável JavaScript o valor da propriedade ClientID do controle a ser validado, esse ID pode ser alterado, como dito acima, pela propriedade ClientIDMode

Se testarmos um Validator com um controle HTML, veremos que o ASP.Net retornará a famosa tela amarela de erro, por não conseguir encontrar o controle e, logo, não ter o valor da propriedade ClientID , como abaixo:

Repare que o controle txtNome agora é um simple INPUT do tipo TEXT, ao executarmos recebemos como resposta a seguinte tela:

Ou seja, como o próprio erro diz, não foi possível encontrar o controle com o ID txtNome, pelos motivos explicados acima.

Solução

Para solucionarmos o problema acima, a única coisa que precisamos fazer é alterar os dois métodos citados acima, para que eles consigam “validar” controles Client Side, além de criar uma propriedade para que seja possível identificar se a validação deve ser feita em um controle ServerSide ou ClientSide.

Para alterar este método, devemos herdar das classes dos Validators e realizar um override dos dois métodos. Abaixo segue um exemplo da alteração para o RequiredValidator, mas a alteração para todos é idêntica, inclusive, a solução para os demais pode ser o simples Contrl+V e Control+C desta, só mudando a classe base, lógico.

Segue o código:

using System.Web.UI;
using System.Web;
namespace Validators
{
    public class RequiredFieldValidator : System.Web.UI.WebControls.RequiredFieldValidator
    {
        /// <summary>
        /// Caso esta propriedade seja True, o controle validará simples controles HTML.
        /// </summary>
        public bool ValidateHTMLControl
        {            get;            set;        }
 
        protected override bool ControlPropertiesValid()
        {
            //Verifico se é um controle HTML
            if (!ValidateHTMLControl)
            {
                return base.ControlPropertiesValid();
            }
            else<
            {
                string controlToValidate = this.ControlToValidate;
                if (controlToValidate.Length == 0)
                {
                    throw new HttpException("A propriedade ControlToValidate é obrigatória.");
                }
                return true;
            }
        }

        public override Control FindControl(string id)
        {
            Control control = this.FindControl(id, 0);

            if (ValidateHTMLControl)
            {
                if (control == null)
                {

                    control = new Control();
                    control.ID = id;

                }
            }
            return control;
        }
    }
}

Para validar um controle HTML é necessário definir a propriedade criada como True:

 Perceba que não precisei criar uma nova tagPrefix (como cc1), isso porque alterei o controle que o Asp.Net deve utilizar como asp:RequriedFieldValidator no Web.Config.

Agora qualquer chamada no meu site para este Validator vai chamar o RequiredFieldValidator customizado, que já tem a inteligência de saber diferenciar se deve validar um ServerControl ou um ClientControl, ou seja, mantém a compatibilidade com outras páginas já criadas. A configuração é o seguinte:

 

Perceba que estou realizando o mapeamento de um controle para outro, e essa estratégia pode ser utilizada para qualquer controle Asp.Net, como um GridView, se você quiser substituir todas as referências de um controle no site para outro controle, sem ter a necessidade de mudar o HTML de cada página, adicionando um prefixo cc1, por exemplo, que aponte para o seu controle.

Atenção

Como alteramos o Validator para funcionar com HTML comum, quando estivermos validando um controle HTML, a validação do lado do Server não funcionará, visto que não terá referência no lado servidor para este controle, o que pode levantar erro. Portanto, essa abordagem só é interessante quando estamos usando Ajax para comunicação com o Server na página, sem PostBack.

Conclusão

Como cada vez mais as páginas estão usando tecnologias ClientSide, muitas vezes precisamos conseguir continuar utilizando controles já comuns em outras páginas, para padrões visuais por exemplo, ou mesmo porque não conseguimos aprender ainda outras formas de validações ClientSide, como os próprios plugins do JQuery. Então devemos saber que é possível customizar controles padrões do Asp.Net para mantermos nossa aplicação funcionando, e aos poucos irmos introduzindo novidades tecnológicas do mercado.

 

Espero que este artigo possa ajudas as pessoas que ainda utilizam WebForms, e não pensam em mudar para o padrão MVC do Asp.Net.

Se você gostou ou não deste post, comente, me deixe saber sua opinião!

Abraços,

Frederico

 

8. agosto 2010 07:33 by Frederico | Comments (0) | Permalink

Comments

Comments are closed

Sobre mim

Minha Imagem

Meu nome é Frederico Batista Emídio, trabalho com desenvolvimento de sistemas profissionalmente a oito anos, porém, já faço sites pessoais a pelo menos dez anos.

Para saber mais clique aqui.

Páginas

Calendário

<<  novembro 2017  >>
seteququsedo
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

Visualizar posts em um Calendário
Sigua @fredemidio

MCP Asp.NET