sexta-feira, 22 de maio de 2009

httpModules e httpHandlers (ashx)

Na última semana o ISEL esteve nas instalações da Simple Solutions a dar uma formação avançada em desenvolvimento Asp.Net. Um dos objectivos era perceber a sequência de geração de eventos no HTTP Pipeline, para a construção de páginas aspx. Identificámos os eventos que mais se adequam a cada situação e a forma correcta de os utilizar, diminuindo por exemplo, o efeito do ViewState.

Dois dos assuntos de que falámos foram os httpModules e httpHandlers. Deixo aqui uma pequena descrição da sua implementação e em que situações devem ser utilizados.

httpModules

A utilizar em situações que queiramos um controlo de entrada ou saída sobre todos os pedidos na aplicação. Exemplos: cifrar a query string, verificar permissões de acessos a recursos (pode entrar na página?).

Implementação:

Registar no Web.config
<system.web>
<httpModules>
<add type="Isel.Handler.RequestTimeModule" name="RequestTimeModule"/>
</httpModules>
</system.web>
Criar uma classe que implementa a interface IHttpModule
namespace Empresa.Aplicacao {
public class RequestTimeModule: IHttpModule {
No evento Init registar os eventos que querem utilizar
public void Init(HttpApplication context) {
context.BeginRequest += new EventHandler(context_BeginRequest);
context.EndRequest += new EventHandler(context_EndRequest);
}
Implementar o código nos eventos registados
void context_BeginRequest(object sender, EventArgs e) {
HttpContext.Current.Items["start"] = DateTime.Now;
}

void context_EndRequest(object sender, EventArgs e) {
if (HttpContext.Current.Response.ContentType == "text/html") {
HttpContext.Current.Response.Write("<p>" + (DateTime.Now -Convert.ToDateTime(HttpContext.Current.Items["start"])) + "</p>");
}
}

httpHandlers (ashx)

A utilizar sempre que quisermos gerar informação a partir da aplicação sem passar por todo o processamento de uma página. Exemplos: gerar imagens a partir da BD, exportação de informação para ficheiros Excel ou XML.

Implementação:

Não é necessário registar nada no Web.config porque o handler ashx já vem de raiz com a plataforma.

Criar uma classe que implementa a interface IHttpModule. No caso de ser necessário acesso à Session, implementar também IRequiresSessionState.
namespace Empresa.Aplicacao.Handler {
public class Exportar : IHttpHandler, IRequiresSessionState {
Definir o evento IsReusable
public bool IsReusable {
get { return true; }
}
Implementar o código no evento ProcessRequest
public void ProcessRequest(HttpContext context) {
try {
string userName = context.User.Identity.Name;
if (userName != null && userName != "") {

string titulo = "";
if (context.Session["ExportarTitulo"] != null && context.Session["ExportarTitulo"].ToString() != "")
titulo = context.Session["ExportarTitulo"].ToString();

if (context.Session["ExportarParametros"] != null & context.Session["ExportarSP"] != null && context.Session["ExportarSP"].ToString() != "") {

context.Response.ContentType = "application/vnd.ms-excel";
context.Response.AddHeader("content-disposition", "attachment;filename=" + titulo + ".xls");
context.Response.Charset = "utf-8";

Regras.Entidade obj = new Regras.Entidade(null, origemErro, userName);
DataSet dSet = obj.Selecciona(context.Session["ExportarSP"].ToString(),
(Regras.Parametro[])context.Session["ExportarParametros"]);

GridView gridLista = new GridView();
gridLista.DataSource = dSet.Tables[0];
gridLista.DataBind();

System.Web.UI.HtmlTextWriter html = new System.Web.UI.HtmlTextWriter(context.Response.Output);

gridLista.RenderControl(html);
}
}
}
catch (Exception ex) {
context.Response.Redirect(ConfigurationManager.AppSettings["NomeApp"] + "Erro.aspx?erro=" + ex.Message);
}
}
Podemos inclusive fazer o override ao comportamento de qualquer tipo de recurso numa aplicação Web.
<httpHandlers>
<add verb="*" path="*.jpg" type="Empresa.Aplicacao.Imagem"/>
</httpHandlers>
Neste caso todos os ficheiros JPEG pedidos à aplicação passam pelo ProcessRequest do tipo “Empresa.Aplicacao.Imagem”.

Sem comentários: