Neste artigo iremos abordar como funciona o ciclo de vida de uma página ASP.NET, desde o momento da sua requisição até o término do carregamento da página no cliente. Para fim de testes dos códigos presentes neste artigo, utilizaremos a IDE Visual Studio 2013 e faremos o uso da Linguagem C#. Não será necessário nenhum banco de dados, já que todas as informações serão geradas no próprio Code Behind.

Para um bom desenvolvedor conhecer a fundo o ciclo de vida é essencial para que o mesmo possa criar uma interface ou controle leve e otimizado, fazendo com que o usuário final tenha uma boa experiência com o sistema.

Página ASP.NET

Uma página ASP.NET é composta por duas partes: elementos visuais e lógica de programação. Na primeira parte é possível inserir controles, textos e elementos HTML, enquanto que a segunda parte é composta por eventos e métodos que manipulam os dados que serão exibidos na página. Para que o código contido na segunda parte, também chamada de Code Behind, seja executado, o compilador ASP.NET gera um arquivo com extensão .dll com conjuntos de instruções a serem executadas.

Muitos de nós desenvolvedores sempre temos dúvidas quanto a sequência de eventos que ocorrem durante o carregamento de uma página ASP.NET, em qual momento devemos fazer a vinculação de determinada informação, a chamada de um controle que tem dependência de uma outra informação contida no carregamento da página e outras necessidades.

Quando uma página ASP.NET é requisitada, existem uma sequência de etapas necessárias a serem executadas para que o servidor possa enviar a página processada para o cliente. Durante o carregamento da página existem vários eventos como: inicialização, criação de instâncias de controles, restauração e manutenção de estado, execução de eventos da página, processamento de códigos e, por último, a renderização dos controles presentes na página.

O processamento de uma página é feito na seguinte ordem: o usuário solicita a mesma através de um método HTTP GET, a página é processada com marcações para o navegador exibi-la igualmente a uma página HTML. O usuário insere e seleciona informações contidas na página que foi requisitada e em seguida clica em um botão para submeter as informações inseridas ao servidor, através de um método HTTP POST. No servidor, a página é processada novamente com as lógicas de programação feitas pelo programador e por final renderiza de volta para o navegador com a informação de sucesso para o usuário. Este ciclo se repete a cada vez que o usuário executa o método HTTP GET e HTTP POST. Cada ciclo é conhecido como Round Trip.

Nota: HTTP GET basicamente é um método que utiliza a URI (mais conhecida como URL) para solicitar dados ao servidor.

O HTTP POST basicamente é um método utilizado para submeter informações ao servidor.

Portanto, para cada solicitação da página, a mesma é instanciada novamente, perdendo assim todas as informações que o usuário tenha informado. Para manter essas informações é necessário que façamos o uso de mecanismos de estado como: Session, ViewState, Cache, etc.

É importante saber também que cada controle ASP.NET tem seu próprio ciclo de vida, que por sua vez é bastante semelhante ao ciclo da página, o que torna mais fácil fazer a manutenção dos dados no momento correto.

Etapas do Ciclo de Vida

Em linhas gerais, existem sete etapas envolvidas no ciclo de vida de uma página ASP.NET, que são as mesmas apresentadas na Figura 1.

Sequência de etapas no ciclo de
vida de uma página ASP.NET

Figura 1. Sequência de etapas no ciclo de vida de uma página ASP.NET

  • Page Request: Essa etapa ocorre antes mesmo de ser iniciado o ciclo de vida da página, que é quando o usuário faz a chamada da página. Neste momento, o servidor ASP.NET verifica se a página precisa ser analisada ou se pode ser utilizada uma versão que foi armazenada em cache.
  • Start: A partir desta etapa é que se inicia de fato o ciclo de vida da página, sendo assim, neste momento algumas propriedades são definidas, como Request e Response. Se a requisição é um Postback ou uma nova requisição a página e a definição da propriedade UICulture.
  • Postback é uma requisição da página onde são enviados dados ao servidor e o mesmo é encarregado em fazer toda lógica de programação contida e devolver um resultado para o navegador.
  • Initialization: Neste momento os controles que irão compor a página ficam disponíveis e recebem seus respectivos UniqueID. Nessa etapa existe uma ressalva: caso a requisição seja um Postback, os dados e valores das propriedades ainda não foram carregados/restaurados com os valores contidos na ViewState.
  • Load: Durante a etapa de Load, ou seja, carregamento da página, os valores das propriedades e dados do ViewState são carregados, caso a requisição seja um Postback.
  • Postback event handling: Neste ponto os eventos dos controles são executados. Algumas validações são feitas, ponto onde a propriedade IsValid verifica os validadores individuais da página.
  • Rendering: Antes de inicializar a renderização dos controles e objetos da página, o ViewState é salvo. Após isso cada elemento da pagina é renderizado.
  • Unload: Assim que a página for processada esta etapa é chamada, nesse momento as propriedades da página, como Response e Request, são descarregados.

Eventos do Ciclo de Vida

Além das etapas envolvidas no ciclo de vida de uma página ASP.NET, existem também eventos que podem ser manipulados de acordo com suas necessidades. O ASP.NET utiliza eventos com nomes particulares e para que isso seja possível é necessário definir o atributo AutoEventWireup como True na diretiva @Page. Neste momento, os eventos da página automaticamente são associados aos métodos, como Page_Load e Page_Init. A seguir iremos definir os eventos utilizados pelos controles do ASP.NET:

  1. PreInit: Este evento ocorre antes da inicialização da página e é utilizado para verificar se a requisição da página é um postback ou se foi chamada pela primeira vez, com a propriedade IsPostBack. Também podem ser definidos o Theme e a MasterPage de forma dinâmica, além de criar ou recriar outros controles. É importante ressaltar que se a requisição for do tipo PostBack, os valores dos controles ainda não foram recuperados da ViewState. Na Listagem 1 temos um exemplo desse evento.
    Listagem 1. Exemplo de evento PreInit da página ASP.NET
    
    protected override void OnPreInit(EventArgs e)
    {
        base.OnPreInit(e);
    }
  2. Init: Neste momento é possível inicializar as propriedades dos controles. Neste evento os controles já foram inicializados juntamente com seus skins, que são um conjunto de informações de formatação que podem ser utilizadas em um determinado controle, como alinhamento, qual CSS será utilizado, paginação e demais formatações. Na Listagem 2 temos um exemplo desse evento.
    Listagem 2. Exemplo de evento OnInit da página ASP.NET
    
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
    }
  3. InitComplete: Ocorre no final do estágio de inicialização da página, porém, o estado da página ainda não foi populado. É utilizado quando existe a necessidade de todas as inicializações os controles estejam finalizados. Temos um exemplo de seu código na Listagem 3.
    Listagem 3. Exemplo de evento InitComplete da página ASP.NET
    
    protected override void OnInitComplete(EventArgs e)
    {
        base.OnInitComplete(e);
    }
  4. PreLoad: Utilizado sempre que necessário fazer o processamento de algum controle antes do Load. Durante este evento é feita uma segunda tentativa para carregar os dados do Postback antes que o evento OnLoadComplete seja executado. Confira na Listagem 4 um exemplo desse código.
    Listagem 4. Exemplo de evento PreLoad da página ASP.NET
    
    protected override void OnPreLoad(EventArgs e)
    {
        base.OnPreLoad(e);
    }
  5. Load: É neste momento onde todos os elementos da página são carregados. Ttambém neste evento é possível definir as propriedades dos controles e estabelecer conexões com banco de dados. Na Listagem 5 temos um exemplo de sua codificação.
    Listagem 5. Exemplo de evento Load da página ASP.NET
    
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
    }
  6. Eventos de controle: Aqui se encontram todos os eventos dos controles existentes na página, como, por exemplo, o evento SelectedIndexChanged do controle DropDownList, como mostra o código da Listagem 6.
    Listagem 6. Exemplo de evento SelectedIndexChanged do controle DropDownList
    
    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        //Digite aqui a lógica necessária para manipulação dos dados de acordo com
        //o índice selecionando no controle DropDownList
    }
  7. LoadComplete: Ocorre após os dados do Postback e dados de estado sejam carregados, lembrando que este só é executado após todas as chamadas de Load de todos os controles da página. Este evento é utilizado quando há a necessidade que todos os controles sejam carregados. Confira um exemplo de seu código na Listagem 7.
    Listagem 7. Exemplo de evento LoadComplete da página ASP.NET
    
    protected override void OnLoadComplete(EventArgs e)
    {
        base.OnLoadComplete(e);
    }
  8. PreRender: Evento utilizado para fazer manutenções finais nos controles e na página antes que os mesmos sejam carregados. Este é o último evento executado antes do estado da página ser salvo e seu código é apresentado na Listagem 8.
    Listagem 8. Exemplo de evento PreRender da página ASP.NET
    
    protected override void OnPreRender(EventArgs e)
    {
        //Este evento ocorre individualmente em todos os controles e em seguida na página
        base.OnPreRender(e);
    }
  9. SaveStateComplete: Ocorre após o estado da página ter sido salvo. Este evento é utilizado apenas para manutenções de estado de exibição, pois neste momento não é possível fazer nenhuma alteração nos controles, já que este é o último evento executado antes da página ser enviada para o navegador. Sua codificação é apresentada na Listagem 9.
    Listagem 9. Exemplo de evento SaveStateComplete da página ASP.NET
    
    protected override void OnSaveStateComplete(EventArgs e)
    {
        base.OnSaveStateComplete(e);
    }
  10. UnLoad: Utilizado para manutenções finais nos controles como, por exemplo, finalizar conexões com banco de dados. Todos os controles chamam este evento e em seguida a página chama este evento também. É importante ressaltar que neste momento nenhuma alteração no fluxo da resposta é possível ser feita. Veja um exemplo de sua codificação na Listagem 10.
    Listagem 10. Exemplo de evento UnLoad da página ASP.NET
    
    protected override void OnUnload(EventArgs e)
    {
        //Assim como o Load, este evento é chamado individualmente por todos os
        //controles e em seguida pela página
        base.OnUnload(e);
    }

Existem também eventos para vinculação de dados, porém estes só estão presentes em componentes que tenham a capacidade de vinculação como, por exemplo, o GridVew que exibe informações provenientes de uma outra fonte de dados. A seguir veremos estes eventos de vinculação:

  1. DataBinding: É neste momento onde se inicia a vinculação dos dados com o controle. Este evento é acionado antes mesmo do PreRender. Vejamos no exemplo de código da Listagem 11 como utilizar o evento DataBinding para popular um GridView com algumas informações provenientes de um DataTable.
    Listagem 11. Exemplo de evento DataBinding do GridView
    
    protected void GridView1_DataBinding(object sender, EventArgs e)
    {
        //Criando DataTable
        DataTable dt = new DataTable();
        dt.Columns.Add("matricula");
        dt.Columns.Add("nome");
        dt.Columns.Add("sexo");
        dt.Columns.Add("telefone");
        dt.Columns.Add("reservista");
     
        //Populando DataTable com informações que serão exibidas futuramente
        dt.Rows.Add("1", "Pedro", "M", "9999-9999", "");
        dt.Rows.Add("2", "Juliana", "F", "8888-8888", "");
        dt.Rows.Add("3", "Maria", "F", "9988-9988", "");
        dt.Rows.Add("4", "Igor", "M", "8181-9999", "");
     
        //Vinculando fonte de dados ao GridView
        ((GridView)sender).DataSource = dt;
    } 
  2. RowCreated ou ItemCreated: O primeiro é utilizado apenas para o controle GridView e o segundo para controle tipo DataList, DetailsView, Repeater e outros. Estes eventos são utilizados para o manuseio do conteúdo que não depende da vinculação de dados. Vejamos na Listagem 12 outro exemplo, agora para o evento RowCreated, afim de verificar se o sexo de um determinado funcionário é masculino e, sendo este, é adicionado o código presente na primeira célula do GridView a propriedade CommandArgument do LinkButton.
    CommandArgument é uma propriedade utilizada para armazenar argumentos que poderão ser utilizados durante os eventos Command dos respectivos controles.
    Listagem 12. Exemplo de evento RowCreated do GridView
    
    //Evento para manuseio do conteúdo, exceto dados, de um controle do tipo GridView
    protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
    {
        //Verifica se o tipo da linha é de dados
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            //Encontra o controle LinkButton presente na célula 4
            LinkButton LkbAdicionar = (LinkButton)e.Row.Cells[4].FindControl("LkbAdicionar");
           
            //Verifica se o conteúdo da célula 2 é o caracter "M"
            if (e.Row.Cells[2].Text.Equals("M"))
            {
                //Habilita o LinkButton
                LkbAdicionar.Enabled = false;
               
                //Adiciona o valor da célula 0 a propriedade CommandArgument do LinkButton
                LkbAdicionar.CommandArgument = e.Row.Cells[0].Text;
            }
            else
            {
                //Desabilita o LinkButton
                LkbAdicionar.Enabled = false;
            }
        }
    } 
  3. RowDataBound ou ItemDataBound: Estes dois eventos seguem a mesmas utilizações dos dois eventos listados anteriormente, sendo o RowDataBound utilizado para o GridView e o ItemDataBound para o DataList, Repeater e outros. Neste momento os dados já estão disponíveis. Vejamos na Listagem 13 o seguinte exemplo: após os dados ficarem disponíveis no controle, é feita uma verificação linha a linha do GridView e verificando se o sexo do funcionário; caso seja “M”, é feita a alteração do conteúdo da célula para “Masculino”, caso contrário, para “Feminino”.
    Listagem 13. Exemplo de evento RowDataBound do GridView
    
    protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        //Verifica se o tipo da linha é de dados
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            //Verifica se o conteúdo da celula 2 é "M", caso seja, é realizada alteração
            //para "Masculino", caso contrário, é feita alteração para "Feminino"
            if (e.Row.Cells[2].Text.Equals("M"))
            {
                e.Row.Cells[2].Text = "Masculino";
            }
            else
            {
                e.Row.Cells[2].Text = "Feminino";
            }
        }
    }
  4. DataBound: É aqui neste evento que se define a finalização da vinculação dos dados ao controle. Neste momento é possível acessar os dados para fazer vinculações em outros controles que dependam de informações deste outro. No exemplo da Listagem 14 fazemos uma verificação das informações presentes no controle GridView para poder vincular a outros dois controles, neste caso, Label.
    Listagem 14. Exemplo de evento DataBound do GridView
    
    protected void GridView1_DataBound(object sender, EventArgs e)
    {
        //Contadores de pessoas por sexo
        int quantidade_masc = 0;
        int quantidade_fem = 0;
     
        //Recuperando o controle GridView
        var gv = (GridView)sender;
     
        //Percorrendo cada linha do GridView
        foreach (GridViewRow row in gv.Rows)
        {
            //Verifica se o tipo da linha é de dados
            if (row.RowType == DataControlRowType.DataRow)
            {
                //Verifica se o conteúdo da celula 2 é "M", caso seja, ele incrementa
                //o contador de homens, caso contrário, ele incrementa o contador de mulheres
                if (row.Cells[2].Text.Equals("M"))
                {
                    //Incrementando o contador masculino
                    quantidade_masc++;
                }
                else
                {
                    //Incrementando o contador feminino
                    quantidade_fem++;
                }
            }
        }
     
        //Preenche outros componentes de acordo com a informação obtida com os dados
        //presentes no GridView
        Label1.Text = string.Format("Quantidade de homens: {0}", quantidade_masc);
        Label2.Text = string.Format("Quantidade de mulheres: {0}", quantidade_fem);
    } 

Os exemplos vistos neste artigo foram feitos apenas com o intuito didático, não refletindo a realidade do mercado de desenvolvimento de aplicações. Profissionalmente falando, utilizamos banco de dados para obter informações e manipulá-las de acordo com a regra de negócio da aplicação. Para eventos e métodos que temos a necessidade de sobrescrevê-los (utilizando a palavra reservada override), é importante lembrar-se de invocar a sua base respectiva para que sejam executadas todas as instruções pertencentes aos mesmos e após isso o trecho de código que o desenvolvedor tenha julgado necessário para este.

Na Figura 2 temos uma imagem mais detalhada, retirada do próprio site da Microsoft, com o funcionamento do ciclo de vida de uma página juntamente com os métodos e eventos dos controles. Lembrando que os Page Methods são os métodos do System.Web.Page, onde fazemos o override e chamamos a sua base. Page Events são os eventos da página e dos controles e Control Methods and Events são métodos que geralmente todos os controles possuem como, por exemplo, o evento Pre_Render do controle GridView.

Ciclo de vida de uma página
ASP.NET juntamente com seus controles

Figura 2. Ciclo de vida de uma página ASP.NET juntamente com seus controles. Fonte: https://msdn.microsoft.com/en-us/library/ms178472.aspx

Neste artigo vimos como ocorre o ciclo de vida de uma página ASP.NET, suas etapas e eventos envolvidos. Conhecendo a fundo estes eventos e etapas mostradas aqui, podemos criar controles mais otimizados e eficazes, visto que saberemos em qual momento é possível acessar e manipular os dados vinculados, fazer as devidas formatações, realizar tarefas antes que o controle seja renderizado na página e outros benefícios que deixarão sua aplicação mais otimizada e leve.

Espero que tenham gostado do artigo e que a informação tenha sido de grande valia.

Um forte abraço e nos encontramos no próximo artigo.