HTTP handlerIntroduction
Introduction
In part.1, we learned about the HTTP request processing process and other operating principles. We know that there are two available interfaces in the HTTP pipeline: ihttphandler and ihttpmodule. However, in part.1, I did not detail how to program them, but I simply put them down. Many concepts and principles have been introduced before. In this article, we will use several examples to understand ihttphandler and see the practical use of these principles.
IhttphandlerOverview
Like me, many ASP. NET developers have ASP backgrounds, so that we are developingProgramUsually, we are thinking on "Page-level", that is to say, what kind of function should we have on this page, whether it is a questionnaire survey or a database query. I seldom think about it at the "Request level" and wonder if there is any way to manipulate an HTTP request by encoding.
In fact, the Framework provides a series of interfaces and classes that allow you to program HTTP requests. One of the main interfaces implementing this operation is ihttphandler (the other is ihttpmodule ).
We should remember that we mentioned ISAPI in section 1, which transfers different requests to different handlers Based on the filename suffix. But a closer look will show that almost half of the files are handed over to aspnet_isapi.dll for processing. Obviously, aspnet_isapi.dll cannot be processed in the same way for each type of files. So who should handle different files? To solve this problem, we need to open the Web. config file under the c: \ windows \ microsoft. Net \ framework \ v2.0.50727 \ config \ directory on the machine.
Note:I read a lot of information, which is said to be on the machine. config, but in fact the machine under v2.0.50727. the httphandlers node in config is like this:
Find the httphandlers node and you can see the following:Code(Omitted ):
...... // omitted
...... // omitted
We can see that different file types are mapped to different handler for processing in the
Note:System. Web. UI. pagehandlerfactory is an ihttphandlerfactory instead of a single httphandler. What ihttphandlerfactory uses will be described later.
The above lists the default handler used by. NET Framework to process HTTP requests. If we want to manipulate an HTTP request programmatically, we need to implement the ihttphandler interface to customize our own needs.
Ihttphandler is defined as follows:
Public interface ihttphandler {
Void processrequest (httpcontext context );
Bool isreusable {Get ;}
}
From the above we can see that ihttphandler requires implementation of a method and an attribute. Processrequest indicates that the main code for processing the request should be placed here.
The isreusable attribute is interpreted as follows on msdn: gets a value indicating whether other requests can use the ihttphandler instance. That is to say, can subsequent HTTP requests continue to use instances of classes that implement this interface? In general, I set it to true.
The class form for implementing this interface should be as follows:
Public class customhandler: ihttphandler {
Public void processrequest (httpcontext context ){
// Request processing code
}
Public bool isreusable {
Get {return true ;}
}
}
To use this custom httphandler, We need to register it in Web. config under the application directory.
<System. Web>
<Httphandlers>
<Add Path = "*. jpg" verb = "*" type = "mynamespace. myclass, mydllname"/>
</Httphandlers>
</System. Web>
It should be found that this is almost identical to the Web. config in the c: \ windows \ Microsoft. NET \ framework \ v2.0.50727 \ config \ directory. Here, path refers to the name of the requested file. You can use wildcards to expand the scope, or you can specify that this handler is only used to process a specific file (for example, filename. aspx) request. Verb indicates the method used to request this file. It can be post or get, and * indicates all access methods. The Type attribute is separated by "," into two parts. The first part is the class name that implements the interface, and the second part is the name of the compiled Assembly located in the bin directory.
Note:If you create a new project and create handlertest under the project. CS, and then let the site reference this project, then the compiled solution will be automatically generated. add the DLL file to the bin directory.
Note:Mydll only writes the Set Name, and does not add the. dll.
Use httphandler to implement image anti-leech Protection
With so much preparation knowledge, it is much easier to achieve the current goal:
Note:This example and the following example are from the book "maximizing ASP. NET real world, object-oriented development:
Step 1: Create the customhandler. CS file. The Code is as follows:
Using system;
Using system. Web;
Namespace customhandler {
Public class jpghandler: ihttphandler {
Public void processrequest (httpcontext context ){
// Obtain the physical path of the file server
String filename = context. server. mappath (context. Request. filepath );
// If urlreferrer is empty, a default anti-leeching image is displayed.
If (context. Request. urlreferrer. Host = NULL ){
Context. response. contenttype = "image/JPEG ";
Context. response. writefile ("/error.jpg ");
} Else {
// If urlreferrer does not contain the host domain name of your website, a default anti-leeching image is displayed.
If (context. Request. urlreferrer. Host. indexof ("yourdomain.com")> 0 ){
Context. response. contenttype = "image/JPEG ";
Context. response. writefile (filename );
} Else {
Context. response. contenttype = "image/JPEG ";
Context. response. writefile ("/error.jpg ");
}
}
}
Public bool isreusable {
Get {return true ;}
}
}
}
Step 2Compile this file
CSC/T: Library/R: system. Web. dll customhandler. CS
Step 3Copy the compiled customhandler. DLL to the bin directory of the site.
Step 4Register the handler in Web. config.
<System. Web>
<Httphandlers>
<Add Path = "*. jpg" verb = "*" type = "customhandler. jpghandler, customhandler"/>
</Httphandlers>
</System. Web>
OK. You can test it by step. I will not go into details here.
Use ihttphandler to implement image Verification Code
You can also implement ihttphandler in A. ashx file, instead of using this early compilation method.
Step 1Open vs2005, "add new project", and "General handler ". After a new file is created, vs automatically adds the following code to the file:
<% @ Webhandler Language = "C #" class = "handler" %>
Using system;
Using system. Web;
Public class handler: ihttphandler {
Public void processrequest (httpcontext context ){
Context. response. contenttype = "text/plain ";
Context. response. Write ("Hello World ");
}
Public bool isreusable {
Get {
Return false;
}
}
}
Step 2Rewrite the Code as follows:
<% @ Webhandler Language = "C #" class = "handler" %>
Using system;
Using system. drawing;
Using system. Drawing. imaging;
Using system. text;
Using system. Web;
Using system. Web. sessionstate;
Public class handler: ihttphandler, irequiressessionstate {
Public void processrequest (httpcontext context ){
Context. response. contenttype = "image/GIF ";
// Create a bitmap object and draw
Bitmap basemap = new Bitmap (200, 60 );
Graphics graph = graphics. fromimage (basemap );
Graph. fillrectangle (New solidbrush (color. White), 0, 0,200, 60 );
Font font = new font (fontfamily. genericserif, 48, fontstyle. Bold, graphicsunit. pixel );
Random r = new random ();
String letters = "abcdefghijklmnpqrstuvwxyz ";
String letter;
Stringbuilder S = new stringbuilder ();
// Add random five letters
For (INT x = 0; x <5; X ++ ){
Letter = letters. substring (R. Next (0, letters. Length-1), 1 );
S. append (letter );
Graph. drawstring (letter, Font, new solidbrush (color. Black), x * 38, R. Next (0, 15 ));
}
// Obfuscation background
Pen linepen = new pen (New solidbrush (color. Black), 2 );
For (INT x = 0; x <6; X ++)
Graph. drawline (linepen, new point (R. next (1, 0,199), R. next (0, 59), new point (R. next (1, 0,199), R. next (0, 59 )));
// Save the image to the output stream
Basemap. Save (context. response. outputstream, imageformat. GIF );
Context. session ["checkcode"] = S. tostring (); // If the irequiressessionstate is not implemented, an error occurs and an image cannot be generated.
Context. response. End ();
}
Public bool isreusable {
Get {return true ;}
}
}
Note that the handler class not only needs to implement the ihttphandler interface (this is obvious), but also needs to implement the irequiressessionstate interface to use sessionstate in this handler class. For this interface, the msdn explanation is as follows: specifies that the target HTTP handler requires read and write access to session-State values. this is a marker interface and has no methods. (translated as: Specifies the read and write access to the sessionstate value of the current HTTP handler. This is a tag interface and there is no way ).
In fact, the irequiressessionstate interface is defined as follows:
Public interface irequiressessionstate {}
It can be seen that this interface does not have any methods or attributes to be implemented, as long as you remember:If you want to use sessionstate in httphandler, you must implement this interface, that is, add this interface in the Class header.
Step 3Create an imagecode. ASPX page and write it in the HTML code:
OK. Open imagecode. aspx in the browser and you can see the following:
Use httphandler to create a custom suffix RSS source
RSS can now be said to be everywhere, and the implementation of RSS is usually in. write an XML file in the codebehind file of aspx and load it to the outputstream of response. The RSS source is usually RSS. aspx format. Through the ISAPI knowledge learned in chapter 1, combined with the knowledge about httphandler learned in this chapter, it is easy to think that we can customize one. RSS is used as a suffix file to implement RSS sources, such as article. RSS. Now we will implement it step by step:
Note:For more information about RSS, see create and use RSS sources on my compiled website. This article no longer explains what RSS is and how to create an RSS sourceArticleOnly the creation process is provided.
Step 1Create a database example
Create Table rsssample
(
Sampleid int identity (1, 1) not null,
Title varchar (100) not null constraint uq_title unique,
Author varchar (50) not null,
Pubdate datetime not null default getdate (),
[Description] varchar (500) not null,
Link varchar (150) not null
Constraint pk_rsssample primary key (sampleid)
)
-- Insert sample data
Insert into rsssample (title, author, [description], link)
Values ('heading 1', 'author 1', 'abstr 1', 'HTTP: // 127.0.0.1 /#')
-- Omitted ....
Step 2Create a site and create the rssfeedslib. CS file under the app_code directory.
Using system;
Using system. Data;
Using system. Data. sqlclient;
Using system. IO;
Using system. Web;
Using system. xml;
Using system. text;
Namespace rssfeadslib {
Public class rssgenerator {
Public static string getrss (){
Memorystream MS = new memorystream ();
Xmltextwriter writer = new xmltextwriter (MS, null );
Sqlconnection conn = new sqlconnection ("Data Source =.; initial catalog = sample; user id = sa; Password = sa"); // modify it to your database connection
Sqlcommand cmd = new sqlcommand ("select * From rsssample order by pubdate DESC", Conn );
Conn. open ();
Sqldatareader reader = cmd. executereader ();
Writer. writestartelement ("RSS ");
Writer. writeattributestring ("version", "2.0 ");
Writer. writestartelement ("channel ");
// Static write of nodes under the channel
Writer. writeelementstring ("title", "tracefact. Net Technical article ");
Writer. writeelementstring ("Link", "http://www.tracefact.net ");
Writer. writeelementstring ("Description", "dedicated to Asp.net ...");
Writer. writeelementstring ("Copyright", "Copyright (c) 2007 ");
Writer. writeelementstring ("generator", "my RSS generator ");
// The item node reads data from the database
While (reader. Read ()){
Writer. writestartelement ("item ");
Writer. writeelementstring ("author", reader. getstring (reader. getordinal ("author ")));
Writer. writeelementstring ("title", reader. getstring (reader. getordinal ("title ")));
Writer. writeelementstring ("Link", reader. getstring (reader. getordinal ("Link ")));
Writer. writeelementstring ("Description", reader. getstring (reader. getordinal ("Description ")));
Writer. writeelementstring ("pubdate", reader. getdatetime (reader. getordinal ("pubdate"). tostring (@ "DDD, DD Mmm yyyy 12:00:00 TT "));
Writer. writeendelement ();
}
Writer. writeendelement ();
Writer. writeendelement ();
Reader. Close ();
Conn. Close ();
Writer. basestream. Flush ();
Writer. Flush ();
Ms. Flush ();
// Change the stream type to string and return the result
Byte [] DATA = new byte [Ms. Length];
Ms. Seek (0, seekorigin. Begin );
Ms. Read (data, 0, Data. Length );
Ms. Close ();
Return utf8encoding. utf8.getstring (data );
}
}
}
Step 3Create rsshandler that can process the. RSS suffix
In this rssfeedslib namespace, we add another class to process HTTP requests for. RSS extension files.
Public class rsshandler: ihttphandler {
Public bool isreusable
{
Get {return false ;}
}
Public void processrequest (httpcontext context ){
Context. response. contenttype = "text/XML ";
String STR = rssgenerator. getrss ();
Context. response. Write (STR );
}
}
Step 4Configure in Web. config
<Httphandlers>
<Add Path = "*. RSS" type = "rssfeadslib. rsshandler" verb = "get"/>
</Httphandlers>
Note:Because this class and namespace are in app_code, you do not need to manually compile rssfeadslib. CS and then put the compiled. dll application assembly in the bin directory. The reason for this will be explained in ASP. NET architecture and security mechanism part.5-page lifecycle and compilation model.
Step 5Set ISAPI in IIS.
Remember how to set ISAPI in IIS to map files to the handler in part.1:
- Open IIS, select the site used in this example, right-click and select "properties ".
- Select the "main directory" tab and click "Configure.
- Click "add" and set "executable file" to "C: \ WINDOWS \ Microsoft. net \ framework \ v2.0.50727 \ aspnet_isapi.dll ", set" extension "to". RSS, click OK ".
- Note: Do not check the "check whether a file exists" check box, so that you do not need to create a file, as long as you enter any in the address bar. the name of the file ending with the RSS suffix will be processed by the handler created above, regardless of whether the file exists or whether the requested file is article. RSS or sample. RSS.
After these settings, iis now knows how to process requests for. RSS extension files.
Step 6Test example
At this time, open a page, such as the blank default. aspx, and then change the file to: article in the address bar. RSS (changed to ABC. the same is true for RSS. If you press enter, you can see the following picture.
IhttphandlerfactoryOverview
Now, if we have such a requirement, we not only want to handle it. RSS suffix, but also want to be able to process. atom extension name. If the class for processing atom is named atomhandler, then our web. how to Set Config? I think it should be like this:
<Httphandlers>
<Add Path = "*. RSS" type = "rssfeadslib. rsshandler" verb = "get"/>
<Add Path = "*. Atom" type = "rssfeadslib. atomhandler" verb = "get"/>
</Httphandlers>
If we have many httphandler requests mapped with different extension names, then our web. config will become very lengthy, or we can know exactly which handler to use only when the program is running. At this time, we can consider implementing ihttphandlerfactory to complete this process.
Ihttphandlerfactory is defined as follows:
Public interface ihttphandlerfactory {
Ihttphandler gethandler (httpcontext context, string requesttype, string URL, string pathtranslated );
Void releasehandler (ihttphandler handler );
}
It can be seen that two methods are required: gethandler () and releasehandler ().
- Gethandler () returns an instance of the class that implements the ihttphandler interface.
- Releasehandler (), so that the factory can reuse an existing handler instance.
For the above. Atom and. RSS problems, we can implement the ihttphandlerfactory interface as follows:
Class handlerfactory: ihttphandlerfactory {
Public ihttphandler gethandler (httpcontext context, string requesttype, string URL, string pathtranslated ){
String Path = context. Request. physicalpath;
If (path. getextension (PATH) = ". RSS "){
Return new rsshandler ();
}
If (path. getextension (PATH) = ". Atom "){
Return new atomhandler ();
}
Return NULL;
}
Public void releasehandler (ihttphandler handler ){
}
}
In this case, set the following settings under the <system. Web> node in Web. config:
<Httphandlers>
<Add Path = "*. RSS, *. Atom" type = "rssfeadslib. handlerfactory" verb = "get"/>
</Httphandlers>
However, this does not simplify ISAPI settings in IIS. You still need to manually set. RSS and. Atom respectively.
Summary
In this article, we first discuss how aspnet_isapi.dll distributes requests to different suffix files to corresponding handlers and how to view the framework's default handler.
Then, we use three instances: image anti-Leech, image verification code, and custom suffix requests to explain in detail how ihttphandler is implemented and how to use it.
Finally, I will give you an overview of the ihttphandlerfactory interface.