FAQ ASP.NET/C#
FAQ ASP.NET/C#Consultez toutes les FAQ
Nombre d'auteurs : 39, nombre de questions : 371, dernière mise à jour : 15 juin 2021
- Qu'est-ce qu'un gestionnaire HTTP (HttpHandler) ?
- Qu'est-ce qu'un module HTTP (HttpModule) ?
- Dois-je plutôt utiliser un HttpModule ou bien le Global.Asax ?
- Comment créer un HttpHandler ?
- Comment afficher une image stockée en binaire, par exemple depuis une base de données ?
- Comment créer un HttpModule ?
- Comment accéder aux évenéments d'un module http depuis un autre module ?
Toutes les requêtes faites à une application ASP.NET sont gérées par un composant spécialisé : le gestionnaire HTTP (HttpHandler).
Le plus connu est le gestionnaire de page, il traite les requêtes faites aux pages ASPX, crée la page, les objets, exécute le code et renvoi le html final.
Il est possible de créer son propre HttpHandler afin de traiter des requêtes particulières.
Ca peut être le cas par exemple pour afficher des images qui ont besoin d'un traitement préalable (chargement depuis une base de données, redimensionnement, etc ...)
Note : 1 requête est traitée par un et un seul HttpHandler
Un modulle HTTP permet de traiter les requêtes faites à une application ASP.NET.
Chaque requête passe par le pipeline de requête et est traitée par chaque HttpModule. Ces modules ont l'opportunité de s'abonner aux événements du cycle de vie de la requête.
Un module Http permet également d'avoir accès à la réponse sortante et de la modifier.
Les plus connus sont ceux utilisés par ASP.NET pour la génération de scripts clients ou de mise en cache.
On peut être amené à développer un module Http dans le cadre d'une réécriture d'url par exemple, ou dans le cadre d'une traduction automatique, etc ...
Un HttpModule est un bon complément au Global.Asax.
Un module Http accède aux mêmes événements et aux mêmes éléments que le Global.Asax.
Pourquoi alors utiliser un HttpModule plutôt que le Global.Asax ?
La première chose qui vient à l'esprit est la réutilisabilité.
J'ai par exemple développé un module d'url rewriting, je peux facilement l'utiliser dans une autre application, simplement en le déclarant comme il faut (voir Comment créer un HttpModule).
Par contre, le Global.Asax aura accès à d'autres événements qui ne sont pas pris en charge par un HttpModule, comme par exemple Session_Start et Session_End.
Il permet également d'instancier des objets globaux disponibles dans l'ensemble de l'application.
La première chose à faire est de créer une classe qui implémente IHttpHandler.
La propriété IsReusable permet d'indiquer si une autre demande peut utiliser l'instance IHttpHandler.
La méthode ProcessRequest sera utilisée pour écrire le flux de sortie HTTP, dans l'exemple qui suit, on affichera simplement un hello world :
using
System;
using
System.
Web;
namespace
MonNamespace
{
public
class
MonHandler :
IHttpHandler
{
public
void
ProcessRequest
(
System.
Web.
HttpContext context)
{
HttpResponse response =
context.
Response;
response.
Write
(
"<html><body>Hello world depuis mon handler</body></html>"
) ;
}
public
bool
IsReusable
{
get
{
return
true
;}
}
}
}
Pour l'utiliser, il faudra le déclarer dans le web.config à la section <httpHandlers> de <system.web> et le configurer de manière à ce qu'il réponde à une requête.
Par exemple, pour les requêtes qui contiendront hello.world :
<configuration>
<system.web>
<httpHandlers>
<add
verb
=
"*"
path
=
"hello.world"
type
=
"MonNamespace.MonHandler, MonAssembly"
/>
</httpHandlers>
<system.web>
</configuration>
Note, l'attribut verb permet de spécifier à quel type de requête le handler doit répondre (GET, POST, ou * (les deux))
On utilisera un handler qui s'occupera de renvoyer l'image.
Le handler répond à une requête pour lire l'image et s'occupe de la charger depuis la base de données. Ensuite, il renverra un contenu de type image qui pourra être affiché par la balise <img>.
Par exemple :
namespace
demoImg
{
public
class
HttpHandlerImage :
IHttpHandler
{
public
void
ProcessRequest
(
HttpContext context)
{
HttpRequest request =
context.
Request;
HttpServerUtility server =
context.
Server;
string
idimage =
request.
QueryString[
"idimage"
];
System.
Drawing.
Image img;
ImageFormat format;
// par ex : ImageFormat.Jpeg
string
contentType;
// par ex : "image/jpeg"
LireImageDepuisLaBD
(
idimage,
out
img,
out
format,
out
contentType);
if
(
img !=
null
)
{
context.
Response.
ContentType =
contentType;
img.
Save
(
context.
Response.
OutputStream,
format);
}
else
context.
Response.
StatusCode =
404
;
}
public
bool
IsReusable
{
get
{
return
true
;
}
}
}
}
Il faudra déclarer le handler dans le web.config :
<httpHandlers>
<add
verb
=
"*"
path
=
"displayimg"
type
=
"demoImg.HttpHandlerImage,demoImg"
/>
</httpHandlers>
On pourra appeler le handler en utilisant par exemple :
<img src
=
"displayimg?idimage=1234"
/>
La première chose à faire est de créer une classe qui implémente IHttpModule.
Il est obligatoire d'implémenter les méthodes Init et Dispose.
Init nous permet de nous abonner aux événements qui nous intéressent, par l'intermédiaire de l'objet HttpContext.
Dans l'exemple qui suit, je trace le début et la fin d'analyse des requêtes grâce aux événements BeginRequest et EndRequest.
public
class
MonHttpModule :
IHttpModule
{
public
void
Init
(
HttpApplication context)
{
context.
BeginRequest +=
context_BeginRequest;
context.
EndRequest +=
context_EndRequest;
}
void
context_BeginRequest
(
object
sender,
EventArgs e)
{
HttpApplication httpApplication =
(
HttpApplication) sender;
Debug.
WriteLine
(
string
.
Format
(
"Début de la requête pour {0} : {1}"
,
httpApplication.
Context.
Request.
Url.
ToString
(
),
DateTime.
Now.
ToLongTimeString
(
)));
}
void
context_EndRequest
(
object
sender,
EventArgs e)
{
HttpApplication httpApplication =
(
HttpApplication)sender;
Debug.
WriteLine
(
string
.
Format
(
"Fin de la requête pour {0} : {1}"
,
httpApplication.
Context.
Request.
Url.
ToString
(
),
DateTime.
Now.
ToLongTimeString
(
)));
}
public
void
Dispose
(
)
{
}
}
Pour que cette classe soit prise en compte par notre application, on va la définir dans le web.config à la section <system.web> :
<httpModules>
<add
name
=
"MonHttpModule"
type
=
"MonNamespace.MonHttpModule, MonAssembly"
/>
</httpModules>
L'objet d'application possède une propriété (Modules) contenant une collection avec tous les HttpModule de l'application.
On pourra accéder à un HttpModule en utilisant son nom. Ainsi, on pourra le référencer depuis un autre HttpModule et s'abonner à ses événements.
public
void
Init
(
HttpApplication context)
{
SessionStateModule sessionMod =
context.
Modules[
"Session"
];
sessionMod.
Start +=
OnSessionStart;
// ...
}