ASP.NET Tutorial/Development/HTTP Handlers
Содержание
Creating a Custom HTTP Handler
Create a class that implements the IHttpHandler interface.
Place this class in the App_Code directory.
using System;
using System.Web;
namespace HttpExtensions
{
public class SimpleHandler : IHttpHandler
{
public void ProcessRequest(System.Web.HttpContext context)
{
HttpResponse response = context.Response;
response.Write("<html><body><h1>Rendered by the SimpleHandler") ;
response.Write("</h1></body></html>") ;
}
public bool IsReusable
{
get {return true;}
}
}
}
Configuring a Custom HTTP Handler
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.ru/.NetConfiguration/v2.0">
<system.web>
<httpHandlers>
<add verb="*" path="source.simple" type="SourceHandler"/>
<add verb="*" path="test.simple" type="SimpleHandler" />
</httpHandlers>
</system.web>
</configuration>
Creating a Generic Handler
When you create a Generic Handler, you create a file that ends with the extension .ashx. Whenever you request the .ashx file, the Generic Handler executes.
A Generic Handler is like an ASP.NET page that contains a single method that renders content to the browser.
You can"t add any controls declaratively to a Generic Handler.
A Generic Handler doesn"t support events such as the Page Load or Page PreRender events.
File: ImageTextHandler.ashx
<%@ WebHandler Language="C#" Class="ImageTextHandler" %>
using System;
using System.Web;
using System.Drawing;
using System.Drawing.Imaging;
public class ImageTextHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string text = context.Request.QueryString["text"];
string font = context.Request.QueryString["font"];
string size = context.Request.QueryString["size"];
Font fntText = new Font(font, float.Parse(size));
Bitmap bmp = new Bitmap(10, 10);
Graphics g = Graphics.FromImage(bmp);
SizeF bmpSize = g.MeasureString(text, fntText);
int width = (int)Math.Ceiling(bmpSize.Width);
int height = (int)Math.Ceiling(bmpSize.Height);
bmp = new Bitmap(bmp, width, height);
g.Dispose();
g = Graphics.FromImage(bmp);
g.Clear(Color.White);
g.DrawString(text, fntText, Brushes.Black, new PointF(0, 0));
g.Dispose();
bmp.Save(context.Response.OutputStream, ImageFormat.Gif);
}
public bool IsReusable
{
get
{
return true;
}
}
}
You specify the image that you want to return from the handler by making a request that looks like this:
/ImageTextHandler.ashx?text=Hello&font=Arial&size=30
The IsReusable property indicates whether the same handler can be reused over multiple requests.
The following page uses the ImageTextHandler.ashx file.
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Show ImageTextHandler</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<img src="ImageTextHandler.ashx?text=Some Text&font=WebDings&size=42" />
<br />
<img src="ImageTextHandler.ashx?text=Some Text&font=Comic Sans MS&size=42" />
<br />
<img src="ImageTextHandler.ashx?text=Some Text&font=Courier New&size=42" />
</div>
</form>
</body>
</html>
Creating HTTP Handlers
An HTTP Handler is a .NET class that executes whenever you make a request for a file at a certain path.
Each type of resource that you can request from an ASP.NET application has a corresponding handler.
You can create a Generic Handler, or you can implement the IHttpHandler interface.
HelloWorld HttpHandler (VB)
File: HelloWorldHttpHandler.ashx
<%@ WebHandler Language="VB" Class="HelloWorldHandler" %>
imports System
imports System.Web
public Class HelloWorldHandler
Implements IHttpHandler
Sub ProcessRequest(context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim Request As HttpRequest = context.Request
Dim Response As HttpResponse = context.Response
Response.Write("<html>")
Response.Write("<body>")
Response.Write(" <h1> Hello " + Request.QueryString("Name") + "</h1>")
Response.Write("</body>")
Response.Write("</html>")
End Sub
Public ReadOnly Property IsReusable As Boolean Implements IHttpHandler.IsReusable
Get
return true
End Get
End Property
End Class
Implementing the IHttpHandler Interface
File: App_Code\ImageHandler.cs
using System;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Web.Configuration;
namespace MyNamespace
{
public class ImageHandler : IHttpHandler
{
const string connectionStringName = "Images";
public void ProcessRequest(HttpContext context)
{
context.Response.Buffer = false;
string fileName = VirtualPathUtility.GetFileName(context.Request.Path);
string conString = WebConfigurationManager.ConnectionStrings [connectionStringName].ConnectionString;
SqlConnection con = new SqlConnection(conString);
SqlCommand cmd = new SqlCommand("SELECT Image FROM Images WHERE FileName=@FileName", con);
cmd.Parameters.AddWithValue("@fileName", fileName);
using (con)
{
con.Open();
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior. SequentialAccess);
if (reader.Read())
{
int bufferSize = 8040;
byte[] chunk = new byte[bufferSize];
long retCount;
long startIndex = 0;
retCount = reader.GetBytes(0, startIndex, chunk, 0, bufferSize);
while (retCount == bufferSize)
{
context.Response.BinaryWrite(chunk);
startIndex += bufferSize;
retCount = reader.GetBytes(0, startIndex, chunk, 0, bufferSize);
}
byte[] actualChunk = new Byte[retCount - 1];
Buffer.BlockCopy(chunk, 0, actualChunk, 0, (int)retCount - 1);
context.Response.BinaryWrite(actualChunk);
}
}
}
public bool IsReusable
{
get { return true; }
}
}
}
Register the class in the web configuration file.
File: Web.Config
<configuration>
<connectionStrings>
<add name="Images"
connectionString="Data Source=.\SQLExpress;Integrated
Security=True;AttachDBFileName=|DataDirectory|ImagesDB.mdf;
User Instance=True"/>
</connectionStrings>
<system.web>
<httpHandlers>
<add path="*.gif" verb="*"
type="MyNamespace.ImageHandler" validate="false" />
<add path="*.jpeg" verb="*"
type="MyNamespace.ImageHandler" validate="false" />
<add path="*.jpg" verb="*"
type="MyNamespace.ImageHandler" validate="false" />
</httpHandlers>
</system.web>
</configuration>
Displaying images with the ImageHandler.
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void btnAdd_Click(object sender, EventArgs e)
{
if (upFile.HasFile)
{
srcImages.Insert();
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Image Upload</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label
id="lblFile"
Text="Image File:"
AssociatedControlID="upFile"
Runat="server" />
<asp:FileUpload
id="upFile"
Runat="server" />
<asp:Button
id="btnAdd"
Text="Add Image"
OnClick="btnAdd_Click"
Runat="server" />
<hr />
<asp:GridView
id="grdImages"
DataSourceID="srcImages"
AutoGenerateColumns="false"
ShowHeader="false"
GridLines="None"
Runat="server">
<Columns>
<asp:ImageField
DataImageUrlField="FileName"
DataAlternateTextField="FileName" />
</Columns>
</asp:GridView>
<asp:SqlDataSource
id="srcImages"
ConnectionString="<%$ ConnectionStrings:Images %>"
SelectCommand="SELECT FileName FROM Images"
InsertCommand="INSERT Images (FileName,Image) VALUES (@FileName,@FileBytes)"
Runat="server">
<InsertParameters>
<asp:ControlParameter Name="FileName" ControlID="upFile" PropertyName="FileName" />
<asp:ControlParameter Name="FileBytes" ControlID="upFile" PropertyName="FileBytes" />
</InsertParameters>
</asp:SqlDataSource>
</div>
</form>
</body>
</html>
Log user in HttpModule
using System;
using System.Web;
using System.Diagnostics;
public class LogUserModule : IHttpModule
{
public void Init(HttpApplication httpApp)
{
httpApp.AuthenticateRequest += new EventHandler(OnAuthentication);
}
private void OnAuthentication(object sender, EventArgs a)
{
string name = HttpContext.Current.User.Identity.Name;
EventLog log = new EventLog();
log.Source = "Log User Module";
log.WriteEntry(name + " was authenticated.");
}
public void Dispose(){ }
}
RSS Handler
File: App_Code\RSSHandler.cs
using System;
using System.Web;
using System.Net;
using System.IO;
namespace MyNamespace
{
public class RSSHandler : IHttpAsyncHandler
{
private HttpContext _context;
private WebRequest _request;
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
_context = context;
_request = WebRequest.Create ("http://msdn.microsoft.ru/asp.net/rss.xml");
return _request.BeginGetResponse(cb, extraData);
}
public void EndProcessRequest(IAsyncResult result)
{
string rss = String.Empty;
WebResponse response = _request.EndGetResponse(result);
using (response)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
rss = reader.ReadToEnd();
}
_context.Response.Write(rss);
}
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
throw new Exception("The ProcessRequest method is not implemented.");
}
}
}
Register it in your web configuration file.
File: Web.Config
<configuration>
<system.web>
<httpHandlers>
<add path="*.rss" verb="*" type="MyNamespace.RSSHandler"/>
</httpHandlers>
</system.web>
</configuration>
If you have a news reader, such as SharpReader, then you can enter a path like the following in the reader"s address bar:
http://localhost:2026/YourApp/news.rss
File: ShowRSSHandler.aspx
<%@ Page Language="C#" %>
<%@ Import Namespace="System.IO" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void Page_Load()
{
string pagePath = Request.Url.OriginalString;
string rssPath = Path.ChangeExtension(pagePath, ".rss");
srcRSS.DataFile = rssPath;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Show RSS Handler</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView
id="grdRSS"
DataSourceID="srcRSS"
AutoGenerateColumns="false"
Runat="server">
<Columns>
<asp:TemplateField HeaderText="Articles">
<ItemTemplate>
<asp:HyperLink
id="lnkRSS"
Text="<%# XPath("title") %>"
NavigateUrl="<%# XPath("link") %>"
Runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:XmlDataSource
id="srcRSS"
XPath="//item"
Runat="server" />
</div>
</form>
</body>
</html>
Source viewer Http Handler
using System;
using System.Web;
using System.IO;
public class SourceHandler : IHttpHandler{
public void ProcessRequest(System.Web.HttpContext context)
{
HttpResponse response = context.Response;
HttpRequest request = context.Request;
HttpServerUtility server = context.Server;
response.Write("<html><body>");
string file = request.QueryString["file"];
try
{
response.Write("<b>Listing " + file + "</b><br>");
StreamReader r = File.OpenText(server.MapPath(Path.rubine("./", file)));
string line = "";
while (line != null)
{
line = r.ReadLine();
if (line != null)
{
response.Write(server.HtmlEncode(line) + "<br>");
}
}
r.Close();
}
catch (ApplicationException err)
{
response.Write(err.Message);
}
response.Write("</html></body>");
}
public bool IsReusable
{
get { return true; }
}
}