Asp.Net Validator Assíncrono    

Neste post passado falei como usar Validator com controles HTMLs puros, para facilitar algumas coisas quando se usa Ajax.

Hoje vou falar novamente sobre Validators, mas agora criando um customizado para necessidades que muitas vezes podemos achar no desenvolvimento de sites com Ajax: Validações Assíncronas.

Imagine um formulário de cadastro, totalmente com Ajax, e você gostaria de validar informações de negócio, onde muitas vezes é necessário fazer algum tipo de consulta em banco de dados, etc.

Vamos supor: Você quer saber, num formulário de cadastro de usuário, se o usuário digitado já existe na base de dados, e mostrar o erro no momento que o usuário digitar o usuário e trocar o foco do controle. Veja bem, eu sei que é possível fazer isso com simples Ajax e os eventos onblur do JavaScript, mas a idéia deste post é mostrar como criar novos controles Asp.Net Validator, e aproveitar funcionalidades como o Validator Callout.

Como funciona um Validator?

No post citado acima, expliquei rapidamente como funciona um Validator, agora vou explicar um pouco mais.

Todo Validator herda da classe System.Web.UI.WebControls.BaseValidator, nessa classe existe um método chamado AddAttributesToRender, o qual é responsável por renderizar os atributes que os códigos do lado do cliente usarão para validar as informações de um campo. Sempre que um Validator é implementado, é necessário renderizar atributos específicos de acordo com a função do Validator.

Estes atributos são necessários porque os Validator precisam renderizar as propriedades definidas no Server Side para o navegador do Cliente. Em geral, os Validators realizam suas validações ainda no JavaScript, por isso, o JavaScript precisa conhecer os controles que serão validados, as mensagens de erros, etc. Para isso, o Asp.Net utiliza o método RegisterExpandoAttribute , que pode ser encontrado tanto Page.ClientScript como no ScriptManager. No nosso caso, como estaremos usando este validators sempre com Ajax, vamos utilizar o método RegisterExpandoAttribute do ScriptManager.

Obs.: Para ficar mais correto, poderíamos utilizar um Padrão de Projeto conhecido como Adapter, onde ficaria encapsulado a utilização do método RegisterExpandoAttribute do Page.ClientScript ou do ScritptManager de forma transparente, mas isso vai além do intuito deste post, e para ficar mais simples, estou utilizando diretamente o do ScriptManeger.

E para que serve o método RegisterExpandoAttribute? Este método renderiza propriedades em objetos JavaScripts. Se for ver como o Validator do post anterior foi renderizado, veremos:

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 = "";

No exemplo acima, MainContent_reqNome é objeto JavaScript que representa o Validator, e controltovalidate, errormessage, evaluationfunction e initialvalue são os ExpandoAttribute.

Criando o AsyncValidator

Para criar Validator Assíncrono, iremos definir duas propriedades no lado do servidor para conseguirmos informações básicas do que o Usuário quer validar. A maioria das demais propriedades de um validator, como ControlToValidate, já estão implementadas na classe base BaseValidator.

	/// 
        /// Método estático na página que fará a validação.
        /// Este método deve estar decorado com o atributo WebMethod
        /// Sua assinatura deve ser:
        /// 
        /// public static bool NomeDoMetodo(string valor){}
        /// 
        /// 
        public string ServerValidationMethod
        {
            get
            {
                if (this.ViewState["ServerValidationMethod"] == null)
                    return "";

                return this.ViewState["ServerValidationMethod"].ToString();
            }
            set { this.ViewState["ServerValidationMethod"] = value; }
        }

        /// 
        /// Caso se deseje alterar o valor do campo definido na propriedade ControlToValidate, define-se um método no javascript com a seguinte assinatura function (sender,args).
        /// O parâmetro args contém a propriedade Value, que contem o valor do campo, que pode ser alterado.
        /// Neste caso, o valor assumido para ser enviado para o server é o valor alterado.
        /// 
        public string CustomValueFunction
        {
            get
            {
                if (this.ViewState["CustomValueFunction"] == null)
                    return "";

                return this.ViewState["CustomValueFunction"].ToString();
            }
            set { this.ViewState["CustomValueFunction"] = value; }
        }

 

O código acima define duas propriedades. Acredito que a propriedade que merece um comentário extra é a ServerValidationMethod. Essa propriedade armazena o nome de um PageMethod que é o responsável por fazer a validação no lado do Server. Por padrão ele recebe a informação que está no campo a ser validado, porém, essa informação pode ser alterada antes de ser enviada ao servidor, pelo método JavaScript definido na propriedade CustomValueFunction.

Para fazer estas informações definidas no servidor ficarem disponíveis no cliente, sobrescrevemos o método citado acima (AddAttributesToRender), e renderizamos as duas proriedades e algumas outras:

protected override void AddAttributesToRender(HtmlTextWriter writer)
        {
            
            base.AddAttributesToRender(writer);
            ScriptManager.RegisterExpandoAttribute(this, this.ClientID, "evaluationfunction", "AsyncValidatorEvaluateIsValid", false);
            ScriptManager.RegisterExpandoAttribute(this, this.ClientID, "isvalidating", "0", false);
            ScriptManager.RegisterExpandoAttribute(this, this.ClientID, "myclientid", this.ClientID, false);
            ScriptManager.RegisterExpandoAttribute(this, this.ClientID, "resultado", "true", false);
            ScriptManager.RegisterExpandoAttribute(this, this.ClientID, "servervalidationmethod", ServerValidationMethod, false);
            ScriptManager.RegisterExpandoAttribute(this, this.ClientID, "customvaluefunction", CustomValueFunction, false);
            ScriptManager.RegisterExpandoAttribute(this, this.ClientID, "ultimovalor", "", false);
            
        }

A maioria dos atributos renderizados são de uso do JavaScript que utilizaremos para fazer a validação, mostrado abaixo. Apenas um merece uma especial atenção: evaluationfunction.

O atributo evaluationfunction é necessário para todos os Validators do Asp.Net WebForm, este atributo armazena o nome do método JavaScript que realiza a validação no lado do cliente. Os scripts ClientSide do WebForm chamam sempre o método definido neste atributo ao executar a validação ao clicar em um botão de submit.. Em um RequiredFieldValidator por exemplo, este atributo contém o nome do método RequiredFieldValidatorEvaluateIsValid, este é o método que verifica se um controle é preenchido ou não.

No nosso caso, como o exemplo mostra, o nosso método responsável por validar o campo, ou seja, chamar o PageMethod criado pelo usuário do Validator responsável pela validação de fato será o AsyncValidatorEvaluateIsValid.

Nosso código JavaScript deve ficar da seguinte forma:

 function AsyncValidatorEvaluateIsValid(val,resultado,userContext,methodName) {
    
    var value = ValidatorGetValue(val.controltovalidate);
    
    //Possíveis valores para isvalidating:
    //0 : Não está validando e deve ir ao server fazer a validação
    //1 : Está na validação, esperando resposta do server, não deve ser executado nada
    //2 : Retornou da validação, deve ser retornado o valor armazenado no retorno
    
    if(val.isvalidating==1){
        return true;
    }
    
    if(val.isvalidating==2){
        val.isvalidating=0;
        return val.resultado; 
    }
    
      
    if(val.customvaluefunction.length>0){
        var args = { Value:value};  
        eval(val.customvaluefunction + "(val, args);");
        value = args.Value;
    }
       

    if(val.servervalidationmethod.length==0) return true;

    val.isvalidating = 1;
    
    eval('PageMethods.'+val.servervalidationmethod+'(value,function (valorRetorno,userContext,methodName){'+
    'val.resultado = valorRetorno;val.isvalid = valorRetorno;val.isvalidating = 2;val.evaluationfunction(val);'+
    '});');
       
     return true;
 
}

O código acima tem toda a lógica necessária para conseguir chamar o PageMethod definido na propriedade do Validator, aguardar o retorno, e informar se o validator foi válido ou não. A lógica não é das melhores, mas ajuda a exemplificar como deve funcionar um validator.

É importante informar que pelo fato de estarmos utilizando um PageMethod, precisamos adicionar um ScriptManager na página e habilitar a utilização de PageMethods, com a propriedade EnablePageMethods definida como true. Naturalmente, esta é só uma das formas de se validar informações assíncronas, foi a escolhida aqui por ser a mais simples.

Apenas com os códigos acima já podemos dizer que o Validator está pronto, mas você pode me perguntar: “Mas se eu quiser distribuir meu Validator, vou ter que distribuir um JavaScript junto?”. A resposta é :”Só se você quiser”.

Para quem não sabe, no .Net é possível colocar arquivos Embedded em DLLs. Para isso, basta colocarmos a propriedade Build Action do arquivo JavaScript como Embedded Resource, desta forma, ao compilar a DLL, o JavaScript será incluído dentro da DLL.

Para carregarmos este arquivo junto no momento do Load do Validator, apenas precisamos sobrescrever o método OnPreRender do Validator:

	protected override void OnPreRender(EventArgs e)
 {
    base.OnPreRender(e);
    ScriptManager.GetCurrent(this.Page).EnablePageMethods = true;
    Page.ClientScript.RegisterClientScriptResource(this.GetType(),
    "AssyncValidator.AsyncValidator.js");

 }

O uso do Validator é como o de qualquer outro, e pode ser usado com ValidatorCallout por exemplo.

Espero que este post possa ajudar você em validações com Web Forms e Ajax.

Até o próximo.

18. August 2010 00:50 by Frederico | Comments (11) | Permalink

Comments

Rafael
Ótimo post!
Isso, sem dúvida nenhuma, vai me ajudar muito.
Um grande abraço!
8/21/2010 6:47:14 AM #
Excellent goods from you, man. I've understand your stuff previous to and you are just extremely magnificent. I really like what you have acquired here, really like what you're stating and the way in which you say it. You make it enjoyable and you still take care of to keep it sensible. I can't wait to read much more from you. This is really a terrific web site.

my web site  Beats Monster - http://www.drdrexbeats.com/
11/29/2014 11:16:27 AM #
Heya i am for the first time here. I found this board and I find It truly useful & it helped me out a lot. I hope to give something back and help others like you helped me.

My web page Dr Dre Beats Headphones ( wp1018907.server-he.de - wp1018907.server-he.de/index.php )
11/29/2014 4:42:32 PM #
I was recommended this blog by my cousin. I am not sure whether this post is written by him as no one else know such detailed about my trouble. You're incredible! Thanks!

My site:  Christian Louboutin Boots - filmworkshop.ru/talk/viewtopic.php?pid=131795
11/30/2014 6:17:16 AM #
Hi there, I enjoy reading through your article. I like to write a little comment to support you.

my weblog ::  Louis Vuitton Outlet Store - http://louisvuitton-outletuk.smutneggs.com/
12/1/2014 4:38:49 PM #
I know this web site offers quality based content and extra information, is there any other website which offers such things in quality?

Look into my web page:  Louis Vuitton Outlet Store - http://nmschool.org/facebook/EReinoso
12/1/2014 7:33:30 PM #
Simply want to say your article is as surprising. The clarity in your post is just excellent and i could assume you're an expert on this subject. Fine with your permission let me to grab your feed to keep up to date with forthcoming post. Thanks a million and please carry on the enjoyable work.

Visit my web-site -  cialis coupons pharmacy - http://edmedtreatment.com/
12/13/2014 1:02:27 AM #
We have been fortunate to have a staff associated with enthusiastic, well-trained fitness professionals. Investing in telemedicine will never just be good for your profile. Kids can sit on their back on in the comfortable seat. They condemn us and those close to us to some life associated with tangible distress.

Here is my homepage ::  Pilar - www.maxmegastore.com/.../
12/23/2014 8:00:07 AM #
According to reviews, the system features a complete package of ingredients that is meant to transform thinning manes. Here are a few hair coloring tips for various skin types:. The arctic fox uses its long, fluffy tail to cover its face.

my site ... non permanent hair color ( webifiedgames.com - webifiedgames.com/index.php )
12/24/2014 2:22:36 PM #
I don't know if it's just me or if perhaps everyone else experiencing issues with your site. It appears like some of the written text within your content are running off the screen. Can somebody else please comment and let me know if this is happening to them too? This could be a issue with my browser because I've had this happen previously. Kudos

my website -  Fake Louis Vuitton Bags - http://louisvuitton-uk.nridaz.net/
12/28/2014 2:09:41 AM #
Santa claus may well be one of the most universal symbol in western culture. The Luminor Marina Computerized comes with metal, titanium or steel casing. Many people will not follow their intuition when it comes to creating. Co washing organic hair has already been enough in order to tame your own curls plus twists.

Visit my page:  zuma free online - http://cylogram.com/profile-522486/info/
12/28/2014 3:47:57 AM #

Add comment




biuquote
  • Comment
  • Preview
Loading



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

<<  December 2014  >>
MoTuWeThFrSaSu
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

Visualizar posts em um Calendário
Sigua @fredemidio

MCP Asp.NET