Estrutura interna do ASP.NET 2.0

Visual Studio 2005

por Jayesh Patel, Bryan Acker, Robert McGovern

Agosto de 2004

Aplica-se a: Microsoft ASP.NET 2.0

Resumo: Embora 100 por cento compatível com o ASP.NET 1.1, o ASP.NET 2.0 traz uma variedade de alterações internas ao ASP.NET. Entre elas, estão incluídas alterações ao modelo de código, à compilação, ao ciclo de vida da página e muito mais. Este artigo descreve essas alterações. (21 páginas impressas).

Nesta página

Introdução Introdução
Modelo de código Modelo de código
Compilação Compilação
Compilação total em tempo de execução (O diretório de códigos) Compilação total em tempo de execução (O diretório de códigos)
Ciclo de vida da página Ciclo de vida da página
Extensibilidade Extensibilidade
Técnicas de cache avançadas Técnicas de cache avançadas
Desempenho Desempenho
Conclusão Conclusão
Sobre os autores Sobre os autores

Introdução

Para os desenvolvedores profissionais de ASP.NET, as grandes questões sobre o ASP.NET 2.0 se relacionam ao que foi alterado internamente. Novos recursos são agradáveis e interessantes de se aprender, mas alterações à estrutura do núcleo do ASP.NET falam mais alto para os desenvolvedores que realmente desejam se aperfeiçoar na tecnologia. Neste white paper, abrangeremos como a estrutura interna do ASP.NET 2.0 foi alterada desde a versão 1.x.

Os tópicos tratados neste artigo serão úteis aos desenvolvedores que se preocupam com o desempenho e os arquitetos técnicos que procuram fazer um ajuste fino dos aplicativos. Especificamente, examinaremos as principais áreas do modelo de código, da compilação, do ciclo de vida da página, da extensibilidade, do desempenho e do cache.

Muitos exemplos neste documento requerem uma familiaridade considerável com a sintaxe do ASP.NET, Visual Basic .NET e/ou C# . Onde aplicável, documentos de referência são fornecidos para uma discussão aprofundada em assuntos específicos.

Modelo de código

Talvez a alteração mais óbvia no funcionamento interno do ASP.NET 2.0 esteja relacionada à forma como uma página da Web do ASP.NET é criada. Nesta seção, examinaremos as alterações ao modelo de código code-behind e como essas alterações causam um impacto no desenvolvimento do ASP.NET.

Modelos de codificação do ASP.NET 1.x

No ASP.NET 1.x, os desenvolvedores tinham duas opções principais para desenvolver um Web Form. Primeiro, o desenvolvedor poderia seguir o modelo ASP tradicional e escrever o código diretamente na página ASPX. Esse processo, conhecido como código embutido, funciona muito bem para comandos simples. No entanto, para códigos mais complexos, escrever código embutido resulta em dificuldades para se ler as páginas da Web que mesclam apresentação (HTML) com funcionalidade (código). No ASP.NET, a prática de codificação padrão foi alterada para ajudar na solução desse problema. A lógica comercial e o código de manipulação de eventos poderiam ser escritos em um arquivo separado, somente de código, conhecido como arquivo de code-behind. O modelo code-behind vincula um arquivo somente de código ao arquivo ASPX que contém marcas de apresentação. Ao separar o código da apresentação, as equipes de desenvolvimento poderiam trabalhar mais rapidamente permitindo que os projetistas trabalhem no arquivo de apresentação enquanto os desenvolvedores trabalham no arquivo de código.

Figura 1. Modelo de codificação do ASP.NET 1.x

As dificuldades principais com o modelo de code-behind estavam relacionadas à forma como o arquivo code-behind tinha de ser sincronizado com a página ASPX. Embora a página ASPX tivesse a herança do arquivo code-behind sob o ponto de vista de programação, os dois arquivos estavam realmente unidos por uma relação mais complexa.

Para obter informações mais detalhadas sobre o modelo code-behind no ASP.NET 1.x, consulte o artigo da MSDN Library, Web Forms Code Model (em inglês).

Complexidade da herança

O paradigma de design do ASP.NET foi que os desenvolvedores tinham que usar o Microsoft Visual Studio .NET para arrastar e soltar controles nas páginas ASPX. O Visual Studio geraria então, automaticamente, o código de suporte apropriado no arquivo code-behind. Se controles fossem adicionados à página ASPX, um código novo teria que ser adicionado ao arquivo code-behind. Em outras palavras, apesar de a relação de herança apontar para o outro sentido, a página ASPX realmente direcionou o design do arquivo code-behind.

Complexidade da compilação

O segundo problema de sincronização residia na maneira como os arquivos eram compilados. Todos os arquivos code-behind, junto com qualquer classe de suporte, eram compilados em um módulo (assembly) e armazenados no diretório /bin do aplicativo da Web. A etapa de compilação ocorria antes da implantação do aplicativo. Por outro lado, a página ASPX era compilada em tempo de execução na primeira solicitação da página. O tempo de execução do ASP.NET realmente compilava a página ASPX em seu próprio módulo (assembly) temporário.

O problema com esse processo é que a página ASPX pode ser alterada sem atualizar o módulo (assembly) code-behind. Isto é, um desenvolvedor pode decidir modificar uma propriedade ou alterar o tipo de um controle em uma página ASPX após a implantação, e o arquivo code-behind não seria atualizado e nem o módulo (assembly) do aplicativo seria recompilado. Quando isso acontecia, o aplicativo sofria erros inesperados por causa da não correspondência entre os arquivos code-behind e suas páginas ASPX associadas.

Modelos de codificação do ASP.NET 2.0

O ASP.NET 2.0 continua a oferecer ambos os modelos de codificação, de código embutido e code-behind. Em termos do modelo de código embutido, muito pouco foi alterado exceto a forma como o Microsoft Visual Studio 2005 oferece suporte ao desenvolvimento de arquivo único. Para obter mais detalhes sobre as alterações no Visual Studio 2005 e como ele manipula o código embutido, consulte este artigo.

O ASP.NET 2.0 aborda as questões sobre herança e compilação do modelo code-behind modificando a natureza do arquivo code-behind. No ASP.NET 2.0, o arquivo code-behind não é mais uma implementação completa da classe System.Web.UI.Page. Em vez disso, o arquivo code-behind é uma nova construção chamada classe parcial. A classe parcial contém todo o código definido pelo usuário, mas omite todo o código de ligação e conectividade que foi gerado automaticamente pelo Visual Studio .NET no ASP.NET 1.x. Quando uma página ASPX com um novo arquivo code-beghind é solicitada, o tempo de execução do ASP.NET 2.0 combinará, na verdade, a página ASPX e a classe parcial em uma única classe, em vez de duas classes distintas.

Figura 2. O modelo code-behind no ASP.NET 2.0

A classe parcial usa uma nova palavra-chave (Expands no Visual Basic ou Partial no C#) para indicar que o código na classe deve ser mesclado com uma outra classe em tempo de execução. Da mesma forma, a página ASPX usa uma nova diretiva chamada compilewith para indicar sua associação com o arquivo code-behind.

Comparando arquivos code-behind

Se você estiver familiarizado com os arquivos code-behind tradicionais do ASP.NET 1.x, já sabe que o Visual Studio insere código de inicialização e declarações de controle gerados automaticamente. Esse código gerado automaticamente é resultado direto da sincronização bidirecional entre o arquivo code-behind e o arquivo ASPX. Uma típica página ASPX com um rótulo teria um arquivo code-behind correspondente consistindo em muitas linhas de texto, gerado automaticamente.

Listagem 1. Um arquivo code-behind no ASP.NET 1.x

namespace WebApplication1
{
  public class WebForm1 : System.Web.UI.Page
  {
    protected System.Web.UI.WebControls.Label Label1;
    private void Page_Load(object sender, 
      System.EventArgs e) {    }
    #region Web Form Designer generated code
      override protected void OnInit(EventArgs e)
      {
        InitializeComponent();
        base.OnInit(e);
      }
      private void InitializeComponent()
      {    
        this.Load += new System.EventHandler(this.Page_Load);
      }
      #endregion
  }
}

Apesar de estarmos falando da mesma página (ProdutosPorCategoria.aspx), percebe-se facilmente que, se pretendemos colocar esta informação em cache, deverão existir múltiplas versões baseadas no parâmetro CatID. Devemos instruir estas versões por meio do atributo VaryByParam. Vale lembrar que os atributos VaryByParam e Duration são obrigatórios (ver Tabela 1. abaixo).

Em comparação, a mesma página do ASP.NET no ASP.NET 2.0 gera um arquivo code-behind que é muito mais limpo.

Listagem 2. Um arquivo code-behind no ASP.NET 2.0

namespace ASP {
public partial class Webform1_aspx
{
}
}

O desenvolvedor pode acessar Label1 automaticamente e adicionar eventos, conforme necessário. Por exemplo, um evento Page_Load pode ser adicionado para inicializar o rótulo.

Listagem 3. Adicionando eventos ao novo arquivo code-behind

namespace ASP {
public partial class Webform1_aspx
{
  void Page_Load(object sender, EventArgs e)
  {
    Label1.Text = "Hello ASP.NET 2.0";
  }
}
}

A sintaxe do evento pode ser gerada pelo Visual Studio .NET. O arquivo code-behind resultante é muito menor e livre de qualquer código gerado automaticamente. O tempo de execução do ASP.NET liga automaticamente os eventos code-behind aos controles do ASPX. Em outras palavras, o tempo de execução do ASP.NET agora executa, automaticamente, a geração do código que era executada pelo Visual Studio.

Complexidade da herança

O novo modelo de arquivo code-behind reduz bastante a complexidade da herança. Como a página ASPX não herda diretamente do arquivo code-behind, esse arquivo não precisa mais definir e oferecer suporte a todos os controles definidos na página ASPX. Da mesma forma, o arquivo code-behind pode acessar automaticamente qualquer controle da página ASPX sem necessitar do código de declaração que era necessário no ASP.NET 1.x. Tudo isso é possível porque o tempo de execução do ASP.NET insere automaticamente a declaração necessária e o código de ligação de eventos no arquivo compilado final. Como o tempo de execução assume essa responsabilidade, nem o desenvolvedor de código nem o desenvolvedor da Web precisa se preocupar com isso.

Durante o tempo de design, a ligação é mantida pelo Visual Studio 2005. O ambiente do Visual Studio tira proveito da parte de compilação do tempo de execução do ASP.NET para assegurar que o desenvolvedor de código e o desenvolvedor da Web possam trabalhar em sincronia.

Complexidade da compilação

Como o novo arquivo code-behind está ligado à página ASPX e compilado em uma classe completa única em tempo de execução, a complexidade da compilação é eliminada. Isto é, o arquivo code-behind é automaticamente sincronizado com a página ASPX. Mesmo com o novo modelo de compilação, é ainda possível ter código sem sincronia, mas o problema pode ser rapidamente localizado, pois a exceção resultante é muito mais explícita.

Compilação

Graças ao modelo de página introduzido no ASP.NET 1.x, o processo de compilação de uma página da Web do ASP.NET sempre foi dividido em duas fases. Na primeira, os arquivos code-behind e qualquer outra classe de suporte são compilados em um módulo (assembly) e, em seguida, os arquivos ASPX individuais são compilados em tempo de execução. Embora esse modelo tenha muitas vantagens, ele tem alguns inconvenientes. O ASP.NET 2.0 oferece várias alternativas ao modelo básico, fornecendo uma faixa mais ampla de opções de compilação, dependendo de suas necessidades específicas.

Compilação no ASP.NET 1.x

O modelo de compilação principal do ASP.NET 1.x resultou em um módulo (assembly) de aplicativo (contendo todos os arquivos code-behind compilados e outro código-fonte) e um módulo temporário criado para cada página ASPX solicitada. Em alguns casos, as otimizações do compilador, como o processamento em lotes, podem fazer com que as páginas ASPX temporárias sejam compiladas no mesmo módulo (assembly). Em qualquer um dos casos, cada página ASPX é compilada em um módulo (assembly) temporário para que possa ser carregada no tempo de execução do ASP.NET.

Figura 3. Compilação no ASP.NET 1.x

Embora esse modelo tenha vantagens, ele também tem duas desvantagens principais. Primeiro, as páginas ASPX devem ser implantadas no site em um formato legível pelo usuário. Se os desenvolvedores usaram o modelo de código embutido, isso significa que alguma ou toda a lógica comercial deverá também ser implantada em um servidor de produção. Embora o IIS e o ASP.NET estejam configurados para não expor as páginas ASPX não processadas, um invasor mais esperto ainda poderia acessar os arquivos através de alguma proeza capaz de abrir o acesso ao servidor Web. Segundo, na primeira vez que qualquer pessoa solicitar uma página da Web, a resposta será mais lenta do que normal, pois o tempo de execução do ASP.NET terá que compilar a página ASPX.

O único controle que um desenvolvedor tem sobre esse processo é compilar ou não em lotes as páginas ASPX. No ASP.NET 1.x, é possível configurar a compilação em lotes no arquivo web.config modificando a marca <compilation>.

Listagem 4. Configurando a compilação em lotes

<compilation>  
  batch="true|false"
  batchTimeout="number of seconds"            
  maxBatchSize="maximum number of pages per batched compilation"
  maxBatchGeneratedFileSize="maximum combined size (in KB) of the 
   generated source file per batched compilation"          
</compilation>

A compilação em lotes faz uma permuta, de tempo de inicialização por tempo de carga reduzido, na primeira solicitação de uma página da Web. O outro benefício da compilação em lotes é que todos os arquivos ASPX são compilados em um módulo (assembly) temporário único em vez de um módulo temporário por página.

Compilação no ASP.NET 2.0

O ASP.NET 2.0 oferece quatro diferentes modelos de compilação para um aplicativo da Web:

  • Normal (ASP.NET 1.x) — Em um aplicativo da Web ASP.NET normal, os arquivos code-behind eram compilados em um módulo (assembly) e armazenados no diretório /bin. As páginas da Web (ASPX) eram compiladas sob solicitação. Esse modelo funcionava bem para a maioria dos sites. No entanto, o processo de compilação tornava a primeira solicitação de qualquer página ASP.NET mais lenta do que as solicitações subseqüentes. O ASP.NET 2.0 continua a oferecer suporte a esse modelo de compilação.

  • Compilação em lotes — No ASP.NET 2.0, é possível compilar em lotes qualquer aplicativo com uma única solicitação de URL. Da mesma forma que com o ASP.NET 1.x, a compilação em lotes remove o retardo na solicitação da primeira página, mas aumenta o tempo de ciclo na inicialização. Além disso, a compilação em lotes ainda requer que os arquivos code-behind sejam compilados antes da implantação.

  • Pré-compilação da implantação — Um novo recurso do ASP.NET 2.0 permite a compilação total de seu projeto antes da implantação. Na compilação total, todos os arquivos code-behind, páginas ASPX, HTML, recursos gráficos e outros códigos back-end são compilados em um ou mais módulos (assemblies) executáveis, dependendo do tamanho do aplicativo e das configurações de compilação. Os módulos (assemblies) contêm todo o código compilado do site, e os arquivos de recursos e de configuração são copiados sem modificação. Esse método de compilação fornece o melhor desempenho e segurança, com a desvantagem de tirar toda a sua capacidade de modificar o site após a implantação. Se você estiver trabalhando com sites altamente visíveis ou seguros, essa opção é a melhor escolha para a implantação final. No entanto, se estiver criando um pequeno site que é executado em sua intranet local, e o site for freqüentemente alterado, a pré-compilação total poderá ser um exagero.

  • Compilação total em tempo de execução — Do lado oposto ao da pré-compilação da implantação, o ASP.NET 2.0 fornece um novo mecanismo para compilar o aplicativo inteiro em tempo de execução. Isto é, você pode colocar seus arquivos code-behind não compilados e qualquer outro código associado no novo diretório de códigos e deixar que o ASP.NET 2.0 crie e mantenha referências para o módulo (assembly) que será gerado a partir desses arquivos em tempo de execução. Essa opção fornece a maior flexibilidade para alterar o conteúdo do site, com a desvantagem do armazenamento de código não compilado no servidor.

A escolha da melhor opção de compilação dependerá de suas necessidades e circunstâncias exatas, mas o modelo de compilação permanece flexível. Mesmo que você escolha fazer uso do diretório de códigos para armazenar seus arquivos code-behind, poderá ainda implantar seu aplicativo usando o método de compilação total.

Compilação em lotes

As configurações de compilação em lotes web.config ainda funcionam no ASP.NET 2.0. As vantagens da compilação em lotes são que as páginas ficam imediatamente disponíveis para o primeiro usuário e que qualquer erro nas páginas ASPX será detectado durante a compilação em lotes. No entanto, a compilação em lotes não adiciona um retardo na inicialização do aplicativo, que deverá ser embutido no arquivo web.config.

Pré-compilação da implantação

A pré-compilação da implantação permite criar um ou mais módulos (assemblies) que são uma versão executável de seu site. Os módulos resultantes contêm o código compilado do site. As páginas HTML, os recursos, os arquivos de configuração e as páginas ASPX são copiados separadamente.

A pré-compilação da implantação requer o uso de um utilitário de linha de comando chamado aspnet_compiler.exe. Esse utilitário cria um diretório de implantação de destino que contém um diretório /bin com módulos (assemblies) e arquivos stub para as várias páginas ASPX. O utilitário pode também ser usado para fazer uma pré-compilação in-loco, similar ao comportamento de se chamar a "página mágica". Os arquivos stub compartilham os nomes de suas páginas ASPX , mas contêm código simples chamado no módulo (assembly) compilado. Em outras palavras, as páginas ASPX são simplesmente envólucros vazios em vez de páginas totalmente funcionais.

Ao fazer a pré-compilação do site para implantação, você ganha maior segurança, pois nenhuma parte de seu código pode ser acessada sem descompilar o módulo (assembly). Para obter mais proteção, você pode ofuscar o módulo (assembly) resultante e tornar seu aplicativo da Web ainda mais seguro. As desvantagens principais da pré-compilação da implantação são que você tem que executar essas etapas antes da implantação e você não poderá alterar seu site depois de tê-lo implantado. Se quiser fazer alterações, terá que recompilar o site e implantá-lo novamente.

Para a maioria dos principais aplicativos da Web, a opção da pré-compilação da implantação será o mecanismo preferido de implantação, pois reduz a quantidade de código não processado implantado no servidor Web e oferece a melhor segurança. O processo melhorado pode ser embutido no ciclo normal de desenvolvimento/teste/implantação sem qualquer perda significativa de produtividade.

Compilação total em tempo de execução (O diretório de códigos)

Em todos os três métodos de compilação descritos até agora, é necessário compilar todos os arquivos de código (code-behind e classes de suporte) antes da implantação. No ASP.NET 2.0, você tem o diretório de códigos.

O diretório de códigos é um diretório especial que mantém as classes não compiladas. Em tempo de execução, o tempo de execução do ASP.NET compila o conteúdo desse diretório em um módulo (assembly) que é automaticamente referenciado pelas páginas ASPX no aplicativo. Em outras palavras, ao usar o diretório de códigos, você pode evitar a necessidade de criar e referenciar módulos (assemblies) distintos em seu código de suporte. A vantagem do diretório de códigos é que você pode implantar sem precisar compilar totalmente seu projeto, reduzindo desse modo possíveis incompatibilidades. A inconveniência é que você está potencialmente expondo código sem compilação em seu servidor.

Essa opção funciona melhor para os aplicativos ASP.NET que não necessitam de grandes quantidades de código de suporte (tanto na forma de arquivos code-behind quanto de objetos externos). Para um aplicativo simples, a capacidade de rapidamente implantar e testar o sistema fornece várias vantagens sobre os métodos mais robustos de compilação.

Ciclo de vida da página

O ASP.NET 2.0 oferece duas alterações principais no ciclo de vida de uma página do ASP.NET. Primeiro, o ASP.NET 2.0 exibe novos eventos para dar suporte a novos recursos, incluindo páginas mestras, personalização e o suporte a dispositivos móveis integrados. Segundo, o ASP.NET 2.0 introduz a postagem em várias páginas para os formulários da Web.

Novos eventos

O ASP.NET 2.0 fornece uma pilha de métodos de ciclo de vida da página mais granular em comparação com o ASP.NET 1.x. Os métodos adicionados fornecem um maior nível de controle ao desenvolvedor da Web. Esses eventos podem ser acessados por meio do objeto Page em qualquer página do ASP.NET.

A Tabela 1 mostra a lista abrangente de métodos. A coluna Método exibe o nome do método do evento real e a coluna Ativo indica se o evento está sempre ativo ou apenas ativo durante as ações de PostBack. Por exemplo, o novo método TestDeviceFilter pode ser usado para determinar qual filtro de dispositivo está instalado. Essa informação será usada para decidir como a página será exibida. Por outro lado, o novo método LoadControlState somente é disparado durante uma nova postagem. Esse método pode ser substituído (junto com SaveControlState) para criar esquemas de serialização alternativos para salvar e restaurar o estado de controle durante uma nova postagem.

Tabela 1.Métodos de ciclo de vida da página

Método

Ativo

Constructor

Sempre

Construct

Sempre

TestDeviceFilter

Sempre

AddParsedSubObject

Sempre

DeterminePostBackMode

Sempre

OnPreInit

Sempre

LoadPersonalizationData

Sempre

InitializeThemes

Sempre

OnInit

Sempre

ApplyControlSkin

Sempre

ApplyPersonalization

Sempre

OnInitComplete

Sempre

LoadPageStateFromPersistenceMedium

PostBack

LoadControlState

PostBack

LoadViewState

PostBack

ProcessPostData1

PostBack

OnPreLoad

Sempre

OnLoad

Sempre

ProcessPostData2

PostBack

RaiseChangedEvents

PostBack

RaisePostBackEvent

PostBack

OnLoadComplete

Sempre

OnPreRender

Sempre

OnPreRenderComplete

Sempre

SavePersonalizationData

Sempre

SaveControlState

Sempre

SaveViewState

Sempre

SavePageStateToPersistenceMedium

Sempre

Render

Sempre

OnUnload

Sempre

Tabela 1. Descrição dos atributos da diretiva de OutputCache

Observando os detalhes de nível inferior do ciclo de vida da página, podemos ver onde muitos dos recursos que estão disponíveis no ASP.NET 2.0, como temas e personalizações, seriam naturalmente implementados. Por exemplo, um tema seria processado no evento IntializeThemes enquanto os dados de personalização seriam carregados em LoadPersonalizationData e posteriormente aplicados no método ApplyPersonalization. Observe que a ordem dos métodos é extremamente importante em relação a quais elementos da interface do usuário determinarão a aparência final de seus aplicativos da Web.

Postagem em várias páginas

A outra alteração principal no ciclo de vida da página envolve eventos de nova postagem e Web Forms. No ASP.NET 1.x, os Web Forms postam novamente de modo automático em sua página host. Isto é, quando um usuário envia um formulário, os dados do formulário são sempre enviados de volta para a página que contém o formulário original. Essa decisão de projeto permite o armazenamento fácil do estado de controle, mas limita a capacidade do desenvolvedor de executar operações mais complexas.

No ASP.NET 2.0, os controles de Web Form têm uma nova propriedade que permite ao desenvolvedor decidir o local para onde os dados do formulário deverão ser enviados em uma ação de envio. Na maioria dos casos, o mecanismo de nova postagem será desejado e, por isso, ele ainda é o padrão. No entanto, se o desenvolvedor desejar postar dados em um formulário diferente, isso agora é possível.

Figura 4. Postar novamente e postagem em várias páginas

Você pode, por exemplo, criar um assistente de várias páginas formado por vários formulários diferentes. Cada formulário envia para a próxima página na seqüência, até que o usuário atinja uma página de resumo na qual poderá ocorrer a validação final. Os dados da última página podem ser acessados no contexto atual por meio do objeto PreviousPage. O objeto PreviousPage armazena os dados validados da página anterior para uso na página atual. Graças a esse objeto, a postagem em várias páginas não sacrifica a persistência do controle. Se seu usuário precisar fazer backup de um formulário na seqüência, os dados da página poderão ser imediatamente acessados e o usuário não terá de inserir todos os dados novamente.

Extensibilidade

O ASP.NET foi originalmente projetado como uma estrutura aberta. Isto é, muitos dos módulos e componentes que constituem o ASP.NET podem ser estendidos, modificados ou substituídos para atender a suas necessidades. No ASP.NET 2.0, a natureza extensível da estrutura é claramente ilustrada pelos novos HTTPHandlers e HTTPModules que são, agora, uma parte padrão da estrutura.

O pipeline de solicitação

No ASP.NET, as solicitações são passadas do servidor Web através de um filtro ISAPI para o tempo de execução real do ASP.NET.

Figura 5. O pipeline de solicitação

Quando o IIS recebe uma solicitação, a extensão é mapeada para um filtro ISAPI de acordo com as configurações do IIS. As extensões .aspx, .asmx, .asd e outras são mapeadas para o arquivo aspnet_isapi.dll, que é simplesmente um filtro ISAPI que inicia o tempo de execução do ASP.NET. Tendo uma solicitação atingido o tempo de execução do ASP.NET, ele é iniciado no objeto HTTPApplication, que atua como o host para o aplicativo da Web do ASP.NET. O objeto HTTPApplication:

  1. Lê os arquivos de configuração do nível da máquina e dos aplicativos.

  2. Passa a solicitação através de uma ou várias instâncias de HTTPModule. Cada HTTPModule fornece um serviço, como manutenção da sessão, autenticação ou manutenção do perfil. Esses módulos passam a solicitação de volta para o HTTPApplication.

  3. Passa a solicitação para um HTTPHandler com base no verbo e no caminho. O verbo corresponde ao verbo HTTP usado na solicitação (GET, POST, FTP, etc.) e o caminho corresponde a uma URL dentro do aplicativo. Dependendo de como os manipuladores estão configurados, a solicitação pode ser processada como uma página do ASP.NET (System.Web.UI.Page é uma implementação do IHTTPHandler) ou a solicitação pode disparar uma outra ação como a compilação em lotes de todas as páginas da Web (precompilation.asd dispara o PrecompHandler).

No ASP.NET 2.0, esse modelo fica intacto; no entanto, vários novos módulos e manipuladores foram adicionados para fornecer serviços adicionais. Da mesma forma que com o ASP.NET 1.x, você pode estender, substituir ou reconfigurar qualquer classe de módulo ou manipulador a fim de fornecer sua própria funcionalidade personalizada.

Novos módulos

Naturalmente, novos HTTPModules foram adicionados para dar suporte aos novos serviços oferecidos no ASP.NET 2.0. Especificamente, um aplicativo ASP.NET com configurações de módulo padrão incluirá novos módulos para:

  • Identificação da sessão — O mecanismo de identificação de sessão foi separado do módulo ASP.NET 1.x Session a fim de fornecer maior controle sobre os cookies, sobre a recriação de URLs e outras formas de geração de identificação de sessão.

  • Gerenciamento de funções — Um novo módulo foi adicionado para fornecer serviços baseados na função para dar suporte aos novos mecanismos de identificação do usuário. Esse módulo ajuda a vincular os aplicativos ASP.NET à segurança baseada em funções embutida na estrutura .NET.

  • Identificação anônima — Os novos recursos de personalização dão suporte a usuários anônimos. Esse módulo ajuda a manter o controle dos recursos que um usuário anônimo pode acessar e como esses recursos são mantidos entre solicitações.

  • Perfil — O módulo de perfil vincula ao novo serviço de perfil e ajuda a fornecer um armazenamento de dados persistente específico do usuário.

  • Contadores de páginas — O ASP.NET 2.0 incorpora um novo módulo para a vinculação aos contadores de páginas e melhoria da análise estatística do tráfego na Web.

Além desses novos módulos, o comportamento de alguns módulos antigos foi alterado: por exemplo, o módulo de cache de saída agora dá suporte às novas técnicas de cache descritas neste white paper.

Novos manipuladores

Além dos novos módulos, o ASP.NET 2.0 introduz novos manipuladores para dar suporte às ferramentas de configuração dos aplicativos e outros novos recursos, como a solicitação de compilação em lotes. O mais importante dos novos manipuladores inclui a família ".axd" que processa solicitações de administração do site. Esses manipuladores iniciam as ferramentas de administração internas que permitem que os desenvolvedores configurem os usuários do ASP.NET, além de outras configurações. Os manipuladores administrativos incluem:

  • Administração da Web — O WebAdminHandler é a página principal do site administrativo. Esse manipulador fornece o ponto inicial para a administração dos aplicativos da Web do ASP.NET 2.0.

  • Rastreamento — O TraceHandler do ASP.NET 1.x foi aperfeiçoado e é o único manipulador "axd" que estava disponível no ASP.NET 1.x.

  • Recursos da Web — Os recursos da Web podem ser agora configurados após a implantação graças à nova ferramenta administrativa e ao WebResourcesHandler.

  • Imagens em cache — O CachedImageServiceHandler fornece suporte para os componentes gráficos de cache.

  • Contadores — O SiteCountersHandler funciona com o módulo de contadores de páginas para fornecer estatísticas de acesso de um aplicativo ASP.NET 2.0.

  • Pré-compilação — Como mencionado anteriormente, o PrecompHandler pode ser usado para compilar em lotes todas as páginas ASPX em um aplicativo ASP.NET.

  • Exportação de Web Part — O WebPartExportHandler fornece suporte para armazenamento e transferência de layouts de Web Parts. As Web Parts são um novo mecanismo de personalização da aparência e do conteúdo de um aplicativo da Web no estilo de portal.

Como sempre, o HTTPForbiddenHandler está vinculado a qualquer tipo de arquivo que não deve ser nunca retornado. No ASP.NET 2.0, a lista de tipos de arquivo proibidos foi expandida para incluir páginas mestras, arquivos de capas e outros novos componentes de desenvolvedor.

Técnicas de cache avançadas

Uma maneira de melhorar o desempenho de qualquer aplicativo da Web é armazenar em cache o conteúdo estático. O conteúdo armazenado em cache é sempre retornado de forma mais rápida do que o conteúdo recentemente processado. No entanto, a contrapartida é que o conteúdo em cache pode se tornar obsoleto. O ASP.NET 1.x dá suporte a várias espécies de cache, incluindo:

  • Nível de página — Cada página pode ser armazenada em cache como um todo ou com base em parâmetros usados para acessar a página. A página em cache expira após um tempo determinado.

  • Fragmento de página — Se a página foi criada com controles de usuário (arquivos .ascx), então esses controles podem ser armazenados em cache independentemente do restante do conteúdo da página.

  • Cache programático — O desenvolvedor poderia também armazenar objetos em cache, graças à API de cache. A API de cache oferece a grande vantagem de fornecer um meio de criar diferentes tipos de dependências de quando o cache deve ser liberado.

No ASP.NET 2.0, o mecanismo de cache no nível de página foi estendido para dar suporte às dependências de banco de dados. Com uma dependência de cache do banco de dados, uma página em cache pode ser vinculada a uma tabela específica em um banco de dados do SQL Server. Quando a tabela é alterada, o cache expira automaticamente. Além disso, um desenvolvedor pode agora usar a substituição pós-cache para substituir parte do conteúdo em cache por conteúdo atualizado. A substituição pós-cache permite que um aplicativo use cache no nível de página mesmo que parte da página deva ser gerada dinamicamente.

Invalidação de cache do banco de dados

Para a maioria dos sites controlados por dados, armazenar em cache pode ser um tópico problemático, especialmente quando uma situação exigir a necessidade do uso de cache e de dados atualizados. No ASP.NET 1.x, as páginas podiam ser armazenadas em cache por um período de tempo e organizadas por parâmetros de entrada (seqüência de consulta ou parâmetros POST):

Listagem 5. Diretiva de cache de saída do ASP.NET 1.x

<%@ outputcache duration="3600" varybyparam="ProdID" %>

Por exemplo, o código na Listagem 5 armazena uma página em cache por uma hora com base na variável ProdID. O problema do exemplo acima é o que fazer se dados comerciais relevantes forem atualizados em outro lugar. Por exemplo, considere uma página de catálogo de produtos armazenada em cache pela identificação do produto. Se as informações sobre esse produto (quantidade disponível ou preço, por exemplo) forem atualizadas em um site administrativo, dados incorretos serão armazenados em cache e exibidos para os clientes. Com a versão anterior do ASP.NET, a solução para esse problema exigiria a remoção manual da página do cache usando Response.RemoveOutputCacheItem ou esperar até que o tempo de duration expirasse, permitindo que o sistema atualizasse a página automaticamente.

O ASP.NET 2.0 aborda esse problema fornecendo suporte para as dependências de cache do banco de dados. Notificações no nível de página estão disponíveis ao trabalhar com o SQL Server 7 e 2000, e o Microsoft SQL Server 2005 oferecerá notificações em um nível ainda mais granular. Por exemplo, o código a seguir armazena em cache uma página de produto por até 1 hora, mas adiciona uma segunda dependência em uma tabela do banco de dados.

Listagem 6. Exemplo de cache do banco de dados no ASP.NET 2.0

<%@ outputcache duration="3600" 
  varybyparam="ProdID" 
  sqldependency="MyDatabase:Products" %>

Usando o novo atributo sqldependency, a página em cache expirará se qualquer alteração for feita à tabela de produtos. O atributo sqldependency deve fazer referência a uma datasource que é configurada no arquivo web.config. A datasource identifica a conexão do banco dados e os parâmetros necessários para fazer com que a notificação de dependência funcione.

Dependências de cache personalizadas

O ASP.NET 2.0 é fornecido com uma implementação de CacheDependency, a classe SQLCacheDependency, que dá suporte ao Microsoft SQL Server. A implementação de uma nova dependência de cache seria um processo complicado, mas é possível devido à natureza extensível do ASP.NET 2.0. Em outras palavras, você poderia criar sua própria classe CacheDependency para fornecer funcionalidade similar a outros sistemas de banco de dados, como o Oracle ou o Sybase.

Substituição pós-cache

Para os casos em que alguns elementos da página são dinâmicos, mas a maior parte de uma página iria se beneficiar do cache, o ASP.NET 2.0 fornece um recurso conhecido como substituição pós-cache. A substituição pós-cache é usada para informar ao tempo de execução do ASP.NET que um elemento específico, presente em uma página em cache, deve ser reavaliado antes que a página seja apresentada ao usuário.

Há duas formas de usar esse recurso:

  • Chamar o novo método Response.writeSubstitution, passando uma referência para a função de retorno de chamada de substituição.

  • Adicionar um controle <asp:substitution> à pagina da Web e definir o atributo methodname para o nome da função de retorno de chamada.

  • Para qualquer uma das opções uma diretiva @OutputCache, especificando a duração e o local da dependência, deve ser adicionada à página.

Implementando a substituição pós-cache

Controles que reconhecem a substituição pós-cache podem ser criados para que você possa tirar proveito desse recurso. Um exemplo de tal controle é o AdRotator. A Listagem 7 ilustra uma página que:

  • Recupera dados da tabela de autores do banco de dados Pubs.

  • Vincula os dados a um controle GridView.

  • Exibe anúncios de um AdRotator.

  • Exibe o horário em que a página foi criada em um controle de rótulo.

Um controle <asp:substitution> (linhas em negrito na listagem) foi também adicionado ao exemplo. Esse controle tem seu atributo methodname definido como uncachedUpdate (um método que retorna uma saída de seqüência de caracteres — nesse caso, a hora atual). O controle de substituição retornará a hora certa, independentemente do que foi armazenado em cache.

Listagem 7. Código-fonte do PostCache.ASPX

<%@ Page language="c#" Codebehind="PostCache.ASPX.cs" 
  AutoEventWireup="true" Inherits="WebApplication1.PostCache" %>
<%@ outputcache duration="30" varybyparam="none" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
  <HEAD>
    <title>WebForm1</title>
  </HEAD>
  <body MS_POSITIONING="GridLayout">
    <form id="Form1" method="post" runat="server">
      <DIV style="DISPLAY: inline;
        Z-INDEX: 101; LEFT: 32px; WIDTH: 160px;
        POSITION: absolute; TOP: 24px; HEIGHT: 8px"
        align="right" ms_positioning="FlowLayout">
          this page was created at:
      </DIV>
      <asp:Label id="CreatedTime"
        style="Z-INDEX: 102; LEFT: 200px; POSITION: absolute;
        TOP: 24px" runat="server" Width="120px" Height="16px">
      </asp:Label>
      <asp:substitution id="UpdatedTime" methodname="uncachedUpdate"
        style="Z-INDEX: 103; LEFT: 200px; POSITION: absolute;
        TOP: 48px" runat="server" Width="112px" Height="11px">
      </asp:substitution>
      <DIV style="DISPLAY: inline; Z-INDEX: 104; LEFT: 32px;
        WIDTH: 160px; POSITION: absolute; TOP: 48px;
        HEIGHT: 16px" align="right" ms_positioning="FlowLayout">
          and last updated at:
      </DIV>
      <asp:AdRotator id="Ads" style="Z-INDEX: 105; LEFT: 312px;
        POSITION: absolute; TOP: 16px" runat="server"
        Width="80px" Height="60px" AdvertisementFile="img/Ads.xml">
      </asp:AdRotator>
    </form>
  </body>
</HTML>

O arquivo code-behind desta página contém o evento necessário para dar suporte à substituição pós-cache no método uncachedUpdate. Observe que o método Page_Load relata a hora em que a página foi carregada, de modo que seja possível determinar quando o cache estiver ocorrendo.

Listagem 8. PostCache.ASPX.cs

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace WebApplication1 {
  public class PostCache : System.Web.UI.Page  {
    protected System.Web.UI.WebControls.Label CreatedTime;
    protected System.Web.UI.WebControls.Label UpdatedTime;
    protected System.Web.UI.WebControls.AdRotator Ads;

    private void InitializeComponent()  {
      this.Load += new System.EventHandler(this.Page_Load);
    }

    private void Page_Load(object sender, System.EventArgs e) {
      CreatedTime.Text = DateTime.Now.ToShortTimeString();  
    }

    protected String uncachedUpdate()  {
      return DateTime.Now.ToShortTimeString();
    }
  }
}

Substituição pós-cache em ação

A Figura 6 mostra a saída da página PostCache. Na primeira vez em que o aplicativo é executado, é possível verificar que os horários de "página criada" e "última atualização" são iguais.

Figura 6. Saída de PostCache.ASPX

Nas chamadas subseqüentes à mesma página, podemos verificar o efeito da substituição pós-cache. Embora a hora de criação da página e a imagem permaneçam as mesmas, a hora da última atualização é alterada.

Figura 7. Saída de PostCache na segunda solicitação

Tanto a hora de criação quanto a imagem adRotator permanecem constantes por causa da diretiva de cache. A página é armazenada em cache por 30 segundos. Terminado o tempo, tanto a hora de criação quanto o adRotator são atualizados na próxima solicitação. No entanto, o controle <asp:substitution>, que chama o método uncachedUpdate(), será atualizado todas as vezes que a página for solicitada, independentemente de ela ter sido armazenada em cache.

Com o uso adequado da substituição pós-cache, os desenvolvedores podem aumentar substancialmente o desempenho de seus aplicativos da Web atualizando apenas os aspectos dinâmicos de suas páginas. Em conjunto com a invalidação de cache do banco de dados e as atualizações de página assíncronas, os aplicativos da Web desenvolvidos com o ASP.NET 2.0 removerão muitas das limitações impostas pela arquitetura tradicional de solicitação e resposta da Web.

Desempenho

Com as alterações na infra-estrutura e os recursos adicionais do ASP.NET 2.0, uma pergunta que permanece é: qual a velocidade do ASP.NET 2.0? Embora as medições de desempenho não estejam disponíveis, pois o ASP.NET 2.0 ainda está em desenvolvimento, esforços significativos foram feitos para assegurar que o desempenho permanecesse consistente ou fosse melhorado em todos os aspectos da estrutura do ASP.NET 2.0.

Pipeline de solicitação aperfeiçoado

Uma área em que todos os desenvolvedores verão um desempenho aperfeiçoado é no pipeline de solicitação. Apesar da adição de muitos novos ganchos de evento, a pilha de solicitações básica do ASP.NET é até 30% mais rápida do que no ASP.NET 1.1. É possível avaliar esse desempenho aperfeiçoado criando-se uma página simples que exiba "Alô mundo". Como a página não tem nenhuma funcionalidade avançada, você estará testando diretamente os pipelines HTTPHandler e HTTPModule, além do plug-in ISAPI que conecta o ASP.NET 2.0 ao IIS. Independentemente de qual versão do IIS esteja usando, você verá um aumento no desempenho, pois este código foi otimizado para taxas de transferência mais rápidas.

Gerenciamento de memória aperfeiçoado com o IIS 6.0

Alguns dos aperfeiçoamentos de desempenho no ASP.NET 2.0 só são obtidos em conjunto com o IIS 6.0. Por exemplo, no IIS 6.0, o trabalho definido para o processo do operador foi reduzido em aproximadamente 50% para testes de carga usando 100 usuários simultâneos solicitando uma página com vários controles. Isso significa que, para um determinado servidor, o sistema operacional está usando cerca de metade dos recursos que eram necessários anteriormente.

Em um teste criado para simular uma página do ASP.NET relativamente complexa, a carga do sistema (uso de memória e CPU) diminuiu bastante quando comparada com a mesma página sendo executada no IIS 5.0. Essa melhoria de desempenho em particular foi obtida movendo os buffers de resposta da memória gerenciada para a memória nativa. Ao remover a necessidade de se fixar a memória gerenciada a uma resposta específica, o ASP.NET 2.0 elimina um gargalo nos recursos e gera respostas mais rápidas para cada solicitação.

Outras melhorias de desempenho tiram proveito da estreita integração do IIS 6.0 com o kernel do sistema operacional Windows. O IIS 6.0 executa algumas das funções de cache e de buffer no nível do kernel, o que proporciona uma melhoria no desempenho de todos os aplicativos da Web, incluindo o ASP.NET.

Outros aperfeiçoamentos

Como desenvolvedor, você deve esperar que o ASP.NET 2.0 seja executado tão rápido quanto, ou até mais rápido do que, o ASP.NET 1.x. Agora que a funcionalidade principal foi criada, melhorias adicionais de desempenho devem ser esperadas na versão final do ASP.NET 2.0.

Conclusão

O ASP.NET 2.0 contém muitos aperfeiçoamentos de arquitetura projetados para aumentar a produtividade do desenvolvedor. Não somente foi o modelo de código aperfeiçoado para reduzir conflitos, o processo de compilação também foi expandido para fornecer uma maior variedade de opções para a compilação e a implantação de aplicativos da Web. A extensibilidade da estrutura ASP.NET foi mais uma vez mostrada com os novos HTTPModules e HTTPHandlers, que dão suporte a muitos dos novos recursos encontrados no ASP.NET, incluindo personalização, páginas mestras e o site administrativo. O cache foi aperfeiçoado para permitir as dependências do banco de dados e a substituição pós-cache. Internamente, o ASP.NET 2.0 contém profundas melhorias em relação a seu antecessor; a nova implementação engloba uma variedade de aperfeiçoamentos direcionados ao desenvolvedor ao mesmo tempo em que segue as melhores práticas do setor. O ASP.NET 2.0 fornece uma plataforma de desenvolvimento da Web de classe mundial criada para tratar da complexidade do desenvolvimento de aplicativos empresariais da Web.

Livros relacionados

Sobre os autores

Jayesh Patel — Jay Patel é um desenvolvedor nas tecnologias .NET and Java. A pesquisa de Jay está concentrada na programação baseada em padrões e nas metodologias ágeis.

Bryan Acker — Bryan Acker é um escritor técnico da Infusion Development. Bryan tem uma ampla experiência em desenvolvimento e hospedagem na Web em ASP e ASP.NET.

Robert McGovern — Rob McGovern é um escritor, desenvolvedor e gerente de projetos sênior na Infusion Development. Rob trabalhou em vários projetos diferentes de ASP.NET, incluindo CodeNotes for ASP.NET e o guia de migração de JSP para ASP.NET.

A Infusion Development Corporation é um Microsoft Certified Solutions Provider que oferece desenvolvimento de software, treinamento e serviços de consultoria personalizados para empresas que fazem parte da Fortune 1000, com ênfase no setor de serviços financeiros. Com escritórios em Nova York e Toronto, a Infusion Development estabeleceu uma base de clientes internacional, incluindo algumas das maiores empresas do mundo nos setores de serviços financeiros, corretagem de valores mobiliários e desenvolvimento de software. Os funcionários da Infusion Development são também os autores e criadores da série de livros CodeNotes.

© 2004 Microsoft Corporation. Todos os direitos reservados. Termos de uso.

Mostrar: