1. Introdução básica aos scripts de servidor
Primeiro, vamos revisar os métodos básicos de execução das páginas do servidor Web:
1. O cliente envia uma solicitação ao servidor digitando o endereço na barra de endereços do navegador
2. Depois que o servidor recebe a solicitação, ele envia para A página correspondente do lado do servidor (ou seja, um script) é executada O script gera uma resposta do cliente e a envia de volta ao cliente
3. O navegador do cliente recebe a resposta do servidor, analisa a. HTML, e apresenta a página gráfica da web ao usuário. Para
a interação entre o servidor e o cliente, os seguintes métodos principais são geralmente usados:
1. Formulário: Este é o método mais importante que é usado para obter a entrada do usuário. O envio do Form envia os dados ao servidor para processamento
2.QueryString
: Ao adicionar parâmetros após o Url, os parâmetros são transmitidos ao servidor. Este método é na verdade igual ao método Get.
um método especial, geralmente usado para confirmar a identidade do usuário
. 2. Introdução ao ASP.Net
Linguagens de script de servidor tradicionais, como ASP, JSP, etc., escrevem scripts de servidor da mesma maneira. em HTML, e a plataforma do servidor executa esses códigos para gerar HTML para scripts e páginas semelhantes. O ciclo de vida do Servlet é na verdade muito simples, ou seja, todo o código é executado do início ao fim, claro, Servlet escrito em. Java pode escrever códigos mais complexos, mas do ponto de vista estrutural não é diferente de JSP.
O surgimento do ASP.Net quebrou essa tradição; o ASP.Net adotou a tecnologia CodeBehind e controles do lado do servidor, adicionou o conceito de eventos do lado do servidor, mudou o modelo de escrita da linguagem de script e tornou-se mais próximo da programação em Windows, tornando a programação da Web mais fácil. , intuitivo, mas temos que ver que o ASP.Net em si não altera o modelo básico de programação Web, apenas encapsula alguns detalhes e fornece algumas funções fáceis de usar, tornando o código mais fácil de escrever e manter; extensão, complicando a forma de execução do lado do servidor. Este é o tópico principal que discutiremos hoje: o ciclo de vida da página da Web ASP.Net.
3. Modo de processamento de solicitação do ASP.Net
Dizemos que a página da Web do ASP.Net não se separa do modo de programação da Web, portanto ainda funciona no modo de solicitação->receber solicitação->processar solicitação->enviar resposta. com o cliente irá acionar uma nova solicitação, portanto o ciclo de vida de uma página da Web é baseado em uma solicitação.
Quando o IIS recebe uma solicitação do cliente, ele entrega a solicitação ao processo aspnet_wp para processamento. Este processo verificará se o domínio do aplicativo solicitado existe, ele criará um e, em seguida, criará um tempo de execução HTTP (. HttpRuntime ) para lidar com solicitações, esse tempo de execução "fornece um conjunto de serviços de tempo de execução ASP.NET para o aplicativo atual" (do MSDN).
Quando o HttpRuntime processa solicitações, ele manterá uma série de instâncias de aplicativos, ou seja, instâncias da classe Global do aplicativo (global.asax). Essas instâncias serão armazenadas em um pool de aplicativos quando não houver solicitações (na verdade, o pool de aplicativos é mantido). por outra classe, HttpRuntime é apenas uma chamada simples). Cada vez que uma solicitação é recebida, HttpRuntime obterá uma instância ociosa para processar a solicitação. Esta instância não processará outras solicitações antes que a solicitação seja concluída. volte para o pool, "Uma instância é usada para lidar com várias solicitações durante seu tempo de vida, mas só pode lidar com uma solicitação por vez." (Extraído do MSDN)
Quando a instância do aplicativo manipular a solicitação, ela criará uma instância de a classe da página de solicitação e executa seu método ProcessRequest para processar a solicitação. Este método é o início do ciclo de vida da página da Web.
4. Página Aspx e CodeBehind
Antes de nos aprofundarmos no ciclo de vida da página, vamos primeiro discutir alguns dos relacionamentos entre Aspx e CodeBehind.
<%@ Page language="c#" Codebehind="WebForm.aspx.cs" Inherits="MyNamespace.WebForm" %>
Acredito que amigos que usaram a tecnologia CodeBehind devem estar bem familiarizados com esta frase no início do ASPX. Analise-o um por um:
Page language="c#" Escusado será dizer que
Codebehind="WebForm.aspx.cs" Esta frase indica o arquivo de código vinculado
Inherits="MyNamespace.WebForm" Esta frase é muito importante Ela representa o nome da classe. herdada pela página, que é a classe no arquivo de código do CodeBehind. Esta classe deve ser derivada de System.Web.WebControls.Page.
Do exposto podemos analisar que na verdade, a classe no CodeBehind é a base da página. (ASPX). Classes, neste ponto, alguns amigos podem querer perguntar. Ao escrever ASPX, você incorpora código ou controles de servidor em HTML exatamente de acordo com o método ASP. ?
Na verdade, esse problema não é complicado. Amigos que usam programação ASP.Net podem ir até o disco do sistema: WINDOWSMicrosoft.NETFramework<número da versão>Temporary ASP.NET Files e colocá-lo abaixo de Todos os arquivos temporários do ASP. Aplicativos .Net que existem nesta máquina O nome do subdiretório é o nome do aplicativo e, em seguida, desce dois níveis (para garantir a exclusividade, o ASP.Net gera automaticamente dois níveis de subdiretórios, e o subdiretório O nome é. aleatório), e então descobriremos que existem muitas bibliotecas de links semelhantes a: "yfy1gjhc.dll", "xeunj5u3.dll" e fontes como arquivos "komee-bp.0.cs" e "9falckav.0.cs" , na verdade, este é o resultado da compilação dinâmica do ASPX pelo ASP.Net. Quando abrimos esses arquivos de origem, podemos encontrar:
public
class WebForm_aspx: MyNamespace.WebForm, System.Web.SessionState.IRequiresSessionState.
, ASPX É uma subclasse da classe de ligação de código. Seu nome é o nome do arquivo ASPX mais o sufixo "_aspx". Ao estudar esses códigos, podemos descobrir que na verdade todos os controles de servidor definidos em aspx são gerados nesses códigos. então, quando esses códigos são gerados dinamicamente, o código originalmente incorporado no ASPX é escrito no local correspondente.
Quando uma página é visitada pela primeira vez, o tempo de execução HTTP usará um gerador de código para analisar o arquivo ASPX e gerar o código-fonte e compilá-lo. Em seguida, as visitas subsequentes chamarão diretamente a dll compilada. é muito lento.
Tendo explicado esse problema, vamos examinar outro problema. Quando usamos vinculação de código, arrastamos um controle na página de design e depois alternamos para a visualização de código, você pode usar o controle diretamente em Page_Load. Como o controle é gerado na subclasse, por que ele pode ser usado na classe pai? Que tal usá-lo diretamente?
Na verdade,podemos
descobrir que sempre que usamos o VS.Net para arrastar um controle para a página, uma instrução semelhante a esta é sempre adicionada ao arquivo de ligação do código:
protected System.Web.WebControls.Button Button1;
O campo é Declare-o como protegido e o nome é consistente com o ID do controle em ASPX. Se você pensar bem, esse problema será resolvido. Mencionamos anteriormente que o código-fonte do ASPX é gerado e compilado dinamicamente pelo gerador. O gerador irá gerar o código para gerar dinamicamente cada controle do servidor. Ao gerar, ele verificará se a classe pai declarou esse controle. irá adicionar um código semelhante ao seguinte:
this.DataGrid1 = __ctrl;
Este __ctrl é a variável que gera o controle. Neste momento, ele atribui a referência do controle à variável correspondente na classe pai, por isso em. a classe pai A declaração deve ser protegida (na verdade também pode ser pública), pois é necessário garantir que as subclasses possam chamá-la.
Então, quando Page_Load for executado, como a declaração da classe pai recebeu um valor pelo código de inicialização na subclasse, podemos usar este campo para acessar o controle correspondente. Sabendo disso, não cometeremos a vinculação de código usando o controle. no construtor no arquivo especificado causa um erro de exceção de referência nula. Como o construtor é executado primeiro, a inicialização da subclasse ainda não foi iniciada, portanto, os campos na classe pai têm valores nulos. Quanto à subclasse, discutiremos mais tarde. quando uma classe é inicializada.
5. Ciclo de vida da página
Voltando ao conteúdo mencionado no terceiro título, falamos sobre a instância do HttpApplication recebendo a solicitação e criando uma instância da classe da página. Na verdade, esta instância é uma instância da classe ASPX compilada dinamicamente. No título anterior aprendemos que ASPX é na verdade uma subclasse da classe na ligação de código, portanto herda todos os métodos protegidos.
Agora vamos dar uma olhada no código da classe CodeBehind gerada automaticamente pelo VS.Net para iniciar nossa discussão sobre o ciclo de vida da página:
#region O Web Form Designer gerou
substituição de código protegido void OnInit(EventArgs e)
{
//
// CODEGEN: Esta chamada é exigida pelo designer de Web Forms do ASP.NET.
//
InitializeComponent();
base.OnInit(e);
}
/// <resumo>
/// O Designer suporta métodos necessários - não use o editor de código para modificar
/// O conteúdo deste método.
/// </summary>
private void InitializeComponent()
{
this.DataGrid1.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.DataGrid1_ItemDataBound)
;
}
#endregion
Este é o código para Page gerado usando VS.Net. Vamos dar uma olhada nele, um é OnInit e o outro é InitializeComponent. início da inicialização da página. Em InitializeComponent vemos a declaração de evento do controle e a declaração Load da página.
A seguir está uma descrição extraída do MSDN e uma tabela de sequência de métodos de ciclo de vida de página e acionamento de eventos:
"Cada vez que uma página ASP.NET é solicitada, o servidor carrega uma página ASP.NET e descarrega a página quando a solicitação é concluída. A página e os controles de servidor que ela contém são responsáveis por executar a solicitação e renderizar o HTML ao cliente. Embora a comunicação entre o cliente e o servidor seja sem estado e intermitente, ela deve ser percebida pelo cliente como um processo contínuo.
"Essa ilusão de continuidade é implementada pela estrutura da página ASP.NET, pela página e seus controles. Após um postback, o comportamento do controle deve parecer começar de onde a última solicitação da Web terminou. As estruturas podem tornar o gerenciamento do estado de execução relativamente fácil, mas para obter efeitos de continuidade, os desenvolvedores de controle devem conhecer a ordem de execução dos controles. Os desenvolvedores de controle precisam entender quais informações podem ser usadas e quais dados podem ser retidos pelo controle em cada estágio do ciclo de vida do controle. estado no qual um controle é renderizado. Por exemplo, um controle não pode chamar seu pai até que a árvore de controle na página seja preenchida." A tabela a seguir fornece uma visão geral de alto nível dos estágios do ciclo de vida do controle. Clique na tabela. link."
de estágio | precisa executar uma ação | para substituir o método ou evento de inicialização |
inicializar | as configurações necessárias no ciclo de vida de uma solicitação da Web recebida. Consulte Tratamento de eventos herdados. | O evento Init (método OnInit) |
carrega o estado da visualização. | Ao final desta fase, a propriedade ViewState do controle será preenchida automaticamente. Para detalhes, consulte a introdução em Mantendo o Estado no Controle. Um controle pode substituir a implementação padrão do método LoadViewState para restaurá-lo para um estado personalizado. | O método LoadViewState |
manipula os dados de postback | , processa os dados do formulário de entrada e atualiza as propriedades de acordo. Consulte Tratamento de dados de postback. Observação Somente controles que tratam de dados de postback participam desta fase. | O método LoadPostData (se IPostBackDataHandler estiver implementado) |
carrega e | executa operações comuns a todas as solicitações, como configurar uma consulta ao banco de dados. Neste ponto, os controles do servidor na árvore foram criados e inicializados, o estado foi restaurado e os controles do formulário refletem os dados do cliente. Consulte Tratamento de eventos herdados. | Evento Load (método OnLoad) |
Enviar notificações de alteração de postback | Gera um evento de alteração em resposta a uma mudança de estado entre os postbacks atuais e anteriores. Consulte Tratamento de dados de postback. Observação Somente controles que geram eventos de alteração de postback participam dessa fase. | O método RaisePostDataChangedEvent (se IPostBackDataHandler for implementado) |
manipula eventos de postback. | Ele manipula eventos de cliente que causam postbacks e gera os eventos apropriados no servidor. Consulte Capturando eventos de postback. Observação Somente controles que tratam de eventos de postback participam dessa fase. | O método RaisePostBackEvent (se IPostBackEventHandler for implementado) |
pré- | renderiza quaisquer atualizações antes de renderizar a saída. As alterações no estado de um controle durante a fase de pré-renderização podem ser salvas, enquanto as alterações feitas durante a fase de renderização são perdidas. Consulte Tratamento de eventos herdados. | O evento PreRender (método OnPreRender) |
salva o estado | após esta fase, persistindo automaticamente a propriedade ViewState do controle em um objeto string. Este objeto string é enviado ao cliente e de volta como uma variável oculta. Para melhorar a eficiência, os controles podem substituir o método SaveViewState para modificar a propriedade ViewState. Consulte Mantendo o estado nos controles. | O método SaveViewState |
renderiza | a saída apresentada ao cliente. Consulte Renderizando controles de servidor ASP.NET. | O método Render |
trata | de todas as operações finais de limpeza antes de destruir o controle. Referências a recursos caros, como links de bancos de dados, devem ser divulgadas nesta fase. Consulte métodos em controles de servidor ASP.NET. | O método Dispose |
descarrega | todas as operações de limpeza finais antes de destruir o controle. Os autores de controle normalmente realizam a limpeza em Dispose sem manipular esse evento. | Evento UnLoad (no método UnLoad) |
Nesta tabela, podemos ver claramente os métodos chamados e o tempo de disparo de uma página desde o carregamento até o descarregamento.
Depois de olhar a tabela acima, amigos atentos podem perguntar, já que OnInit é o início do ciclo de vida da página, e falamos sobre controles sendo criados em subclasses na aula anterior, aqui na verdade usamos o método InitializeComponent Campos declarados na classe pai já pode ser usado, então isso significa que a subclasse foi inicializada antes disso?
No terceiro título, mencionamos que o ProcessRequest da classe page é o início do ciclo de declaração da página no verdadeiro sentido. Este método é chamado por HttpApplication (o método de chamada é mais complicado e terei a oportunidade de escrever um. artigo separado para explicá-lo). Uma página O processamento da solicitação começa a partir deste método. Ao descompilar a biblioteca de classes .Net para visualizar o código-fonte, encontramos a classe base de System.Web.WebControls.Page: System.Web. WebControls.TemplateControl (é a página e o controle de usuário. Um método virtual "FrameworkInitialize" é definido na classe base) e, em seguida, esse método é chamado primeiro no ProcessRequest da página. Encontramos vestígios desse método no código-fonte ASPX. gerado pelo gerador. Todos os controles estão em Ele é inicializado neste método e a árvore de controle da página é gerada neste momento.
O próximo passo é simples, vamos analisar gradativamente cada item do ciclo de vida da página:
1. Inicialização
A inicialização corresponde ao evento Init e ao método OnInit da Página.
Se você quiser reescrever, o MSDN recomenda sobrecarregar o método OnInti em vez de adicionar um proxy para o evento Init. Há uma diferença entre os dois. o último só pode ser usado na classe pai. Executado após OnInit (na verdade chamado em OnInit).
2. Carregando o estado da visualização
Este é um método mais importante. Sabemos que cada solicitação é realmente processada por uma instância de classe de página diferente. Para garantir o estado entre duas solicitações, o ASP.Net usa ViewState.
O método LoadViewState obtém o último estado de ViewState e usa recursão para percorrer toda a árvore de acordo com a estrutura da árvore de controle na página para restaurar o estado correspondente a cada controle.
3. Processamento de dados de postback
Este método é usado para verificar se o status dos dados de controle enviados de volta pelo cliente foi alterado. Protótipo do método:
public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)
postDataKey é a palavra-chave que identifica o controle (ou seja, a chave em postCollection é uma coleção que contém dados de postback). o retorno Se os dados enviados foram alterados, em caso afirmativo, ele retorna True, "LoadPostData retorna true se o estado do controle mudar devido ao postback; caso contrário, retorna false. A estrutura da página rastreia todos os controles que retornam true e chama RaisePostDataChangedEvent nesses controles . "(Extraído do MSDN)
Este método é definido em System.Web.WebControls.Control e também é o método que todos os controles personalizados que precisam manipular eventos precisam manipular. Para a página que estamos discutindo hoje, você pode deixá-la. sozinho.
4. O carregamento
corresponde ao evento Load e ao método OnLoad. Acredito que a maioria dos amigos estará familiarizada com este evento. O método Page_Load na página gerada pelo VS.Net é o método para responder ao evento Load. será acionado, o método Page_Load também será executado. Acredito que este também seja o primeiro passo para a maioria das pessoas entender o ASP.Net.
O método Page_Load responde ao evento Load, que é definido na classe System.Web.WebControl.Control (esta classe é o ancestral de Page e de todos os controles de servidor) e é acionado no método OnLoad.
Muitas pessoas podem ter encontrado algo assim. Eles escreveram uma classe PageBase e depois verificaram as informações do usuário em Page_Load. Acontece que não importa se a verificação foi bem-sucedida ou não, o Page_Load da página da subclasse sempre será executado primeiro. desta vez, algumas informações podem ser deixadas. Como risco de segurança, o usuário pode executar o método Page_Load na subclasse sem ser autenticado.
A razão para este problema é muito simples, porque o método Page_Load é adicionado ao evento Load em OnInit, e o método OnInit da subclasse primeiro adiciona o evento Load e depois chama base.OnInit, o que faz com que a subclasse Page_Load seja adicionada primeiro , então executado primeiro.
Também é muito simples resolver este problema. Existem dois métodos:
1) Sobrecarregar o método OnLoad no PageBase, depois autenticar o usuário no OnLoad e depois chamar base.OnLoad, pois o evento Load é acionado no OnLoad, para que possamos. garanta a autenticação do usuário antes de disparar o evento Load.
2) Primeiro chame base.OnInit no método OnInit da subclasse para garantir que a classe pai execute Page_Load primeiro.
5. Envie notificação de alteração de postback
Este método corresponde ao processamento de dados de postback na etapa 3. Se os dados de postback forem processados. , True é retornado. A estrutura da página chamará esse método para acionar eventos de alteração de dados, portanto, o evento de alteração de dados de postback do controle personalizado precisa ser acionado neste método.
Da mesma forma, este método não é muito útil para Page. É claro que você também pode definir eventos de alteração de dados com base em Page.
6. Tratar eventos de postback
Este método é onde a maioria dos eventos de controle de servidor são acionados. Quando a solicitação contém informações sobre gatilhos de eventos de controle (eventos de controles de servidor são outro tópico, escreverei outro artigo para discutir em um futuro próximo), o controle de página. O método RaisePostBackEvent do controle correspondente será chamado para acionar o evento do lado do servidor.
Aí vem outra pergunta comum:
os internautas costumam perguntar por que os dados enviados não foram alterados após a modificação.
Na maioria dos casos, eles não entendem o processo de acionamento dos eventos do servidor. Podemos ver que o evento do servidor é acionado após o carregamento da página. , ou seja, a página executará primeiro o Page_Load e, em seguida, executará o evento de clique do botão (aqui está o botão como exemplo). Muitos amigos vinculam os dados no Page_Load e, em seguida, processam as alterações no evento do botão. é um problema com isso, Page_Load é sempre executado antes do evento do botão, o que significa que antes que os dados tenham tempo de mudar, o código de ligação de dados em Page_Load é executado primeiro e os dados originais são atribuídos ao controle, depois quando o. O evento de botão é executado. O que realmente é obtido são os dados originais, portanto a atualização obviamente não terá efeito.
Também é muito simples mudar esse problema. Uma abordagem mais razoável é escrever o código de ligação de dados em um método, vamos supor que seja BindData:
private void BindData().
{
// Vincula dados
}
Em seguida, modifique PageLoad:
private void Page_Load( object sender,EventArgs e)
{
if(!IsPostBack)
{
BindData(); //Vincula dados quando a página é acessada pela primeira vez}
}
Finalmente no evento do botão:
private Button1_Click( object sender,EventArgs e )
{
//Atualiza dataBindData();//Religa dados
}
7.
O processamento da solicitação final de pré-renderização será convertido em uma resposta enviada de volta ao servidor. A etapa de pré-renderização consiste em realizar as alterações de estado feitas antes da renderização final, pois antes de renderizar um controle, devemos. gerar HTML com base em suas propriedades, como o atributo Style, que é o exemplo mais típico. Antes da pré-renderização, podemos alterar o estilo de um controle. informações de estilo como o estágio de renderização.
8. Salve o estado.
Este estágio é para o estado de carregamento. Mencionamos muitas vezes que diferentes instâncias estão processando entre solicitações, portanto, precisamos salvar o estado desta página e controlar. .
9.
Neste ponto, o processamento da solicitação da página basicamente chegou ao fim. No método Render, a árvore de controle de toda a página será recursiva, o método Render será chamado em sequência e o código HTML correspondente será escrito. no fluxo de resposta final.
10. O descarte
é na verdade o método Dispose. Nesse estágio, os recursos ocupados, como conexões de banco de dados, serão liberados.
11.
No final do descarregamento, a página executará o método OnUnLoad para acionar o evento UnLoad, que trata do processamento final antes que o objeto da página seja destruído. Na verdade, o ASP.Net fornece esse evento apenas para considerações de design. de recursos é concluído no método Dispose Portanto, este método se tornou inútil.
Apresentamos brevemente o ciclo de vida da página e demos uma explicação menos aprofundada sobre o processamento de eventos do lado do servidor. Hoje, quero principalmente que todos entendam o ciclo de execução da página. Escreverei um pouco mais sobre os eventos e o tempo de vida. de controles de servidor no futuro artigo para discutir.
Esses conteúdos são algumas das minhas experiências de pesquisa de páginas quando estava aprendendo ASP.Net. Os detalhes específicos não são discutidos em detalhes. Consulte o MSDN para obter mais informações, mas citei alguns erros comuns e os motivos. , Espero que possa trazer inspiração para todos.