ASP.NET Tutorial/Development/HTTP Handlers

Материал из .Net Framework эксперт
Перейти к: навигация, поиск

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; }
  }
}