Durante a semana passada nos foi solicitado o desenvolvimento de uma versão mais Light de um determinado site. Tal site tem realmente um grande apelo visual, em 1024 linhas, com diversas imagens, flashs e outros componentes que tornam a navegação no site mais fácil e intuitiva. No entanto, um certo grupo de usuários que utilizam computadores mais antigos, com 800 linhas de resolução e normalmente um link de internet mais fraco. Por tal motivo, foi solicitada a versão Light.
Como o site utiliza MasterPages, e o cliente solicitou alteração dos itens estruturais, mas o miolo do site poderia permanecer exatamente igual, a "simples" idéia que surgiu foi alterar dinamicamente a MasterPage, de acordo com a resolução do usuário ou caso ele solicitasse acessar a versão Light.
No entanto, a alteração dinâmica da MasterPage somente pode ser feita nos métodos de inicialização da página que fossem executados antes do método Page_Init (No caso, poderia ser no método Page_PreInit), o qual somente é executado automaticamente (na inicialização) nos arquivos ASPX. Isso significa que não é possível colocar em uma masterpage esta alteração dinâmica de masterpage, mesmo em casos onde há masterpages aninhadas, e portanto, seria necessário alterar todas as páginas ASPX novamente.
Pesquisando sobre HTTPMODULES, no entanto, encontramos uma alternativa.
Um HTTPMODULE, de forma resumida, é uma classe .DLL que pode conter métodos diversos. Esses métodos podem ser associados a eventos de inicialização de páginas. O que fizemos então foi criar um HTTPMODULE que é acionado no evento Pre_Init de uma página e, portanto, é executado antes do método Init. Este método é executado para todas as páginas. E essa, aparentemente, é uma característica do HTTPMODULE.
A classe também deve possuir algumas peculiaridades, como herdar IHttpModule entre outros. Abaixo, no exemplo, ficará mais claro:
Para que a classe seja executada como HTTPMODULE, basta adicioná-la no WEB.CONFIG, em <System.Web> <httpModules>.
Segue abaixo o exemplo:
//----------------------ABAIXO, INÍCIO DA CLASSE-----------------------//
using System;
using System.Web;
using System.Web.UI;
public class MasterPageModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
}
void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
Page page = HttpContext.Current.CurrentHandler as Page;
if (page != null)
{
// abaixo, o método "page_alterarMasterPage" é associado ao evento PreInit
// e será executado logo após o método Page_PreInit
page.PreInit += new EventHandler(page_alterarMasterPage);
}
}
void page_alterarMasterPage(object sender, EventArgs e)
{
Page page = sender as Page;
//o if abaixo adiciona PageMaster apenas para os arquivos .ASPX que originalmente possuiam uma masterpage default
//isso evita que páginas que devem ser executadas sem masterpage, recebam uma masterpage dinamica indevidamente.
if ((page != null) && (page.MasterPageFile != null) && (page.MasterPageFile != ""))
{
if (HttpContext.Current.Session["masterpage"] != null)
{
// abaixo, a masterpage é configurada com base no nome armazenado na Session do usuário
page.MasterPageFile = HttpContext.Current.Session.Contents["masterpage"].ToString();
}
}
}
public void Dispose()
{
}
}
//------------------------ TERMINO DA CLASSE --------------------------//
OBS: a classe deve ser compilada (transformada em .dll) e colocada na pasta Bin. Para tanto, você pode utilizar uma ferramenta do Visual Studio ou compilar pelo Prompt de Comando, através do seguinte comando (deve ser executado na pasta onde está o arquivo .cs):
csc /t:library MasterPageModule.cs
Em seguida, copie o arquivo .cs e o .dll para a pasta bin (o arquivo .cs não será executado na pasta bin. somente o arquivo .dll será).
Abaixo, a linha que deve ser adicionada no WEB.CONFIG, em <System.Web> <httpModules>..
<add name="MyMasterPageModule" type="MasterPageModule"/>
onde name é o nome do módulo e type é o nome da classe atrelada ao módulo.
Abs, e até a próxima.
Fernando D'Angelo