1. Handlers and Session State
Session state works automatically in the context of System.Web.UI.Page. However, custom handlers need to turn on the ability to use session state deliberately.
The .NET architecture uses an interesting idiom known as marker interfaces. Marker interfaces are empty interfaces (without any methods or properties defined). Their sole purpose is to signal the runtime
about various aspects of the application. For example, the ASP.NET
runtime often uses them to turn on and off various features. When the
runtime detects a marker interface as part of an object's class
hierarchy, the runtime can bring into play certain features.
For a handler to use session state, it must have the System.Web.SessionState.IRequiresSessionState
interface in its inheritance list. That way the runtime will know to
load and store session state at the beginning and end of each request.
Example 1 shows a handler with session state enabled.
Example 1. Example HTTP handler that accesses session state
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.SessionState;
public class HandlerWithSessionState : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext ctx)
{
string strData = (string)ctx.Session["SomeSessionData"];
if (String.IsNullOrEmpty(strData))
{
strData = "This goes in session state";
ctx.Session["SomeSessionData"] = strData;
}
ctx.Response.Write("This was in session state: " + strData);
}
public bool IsReusable {
get
{
return true;
}
}
}
2. Generic Handlers (ASHX Files)
Just as ASPX files can be compiled on the fly ("just in time"), so can handlers. Generic
handlers have an extension of ASHX. They're equivalent to custom
handlers written in C# or Visual Basic in that they contain classes that
fully implement IHttpHandler. They're convenient in the same way ASPX files are convenient. You simply surf to them and they're compiled automatically.
The following example illustrates the CustomFormHandler implemented as a "generic handler."
Writing a generic handler
Add
a "generic" handler to the Web site. In Solution Explorer, right-click
the CustomHandler Web site node and click Add New Item. Select Generic
Handler from the templates. Name the handler CustomFormHandler.ashx.
Visual Studio generates a handler that includes a stubbed-out ProcessRequest method and a completed IsReusable
property. Open the handler's code-beside file (named
CustomFormHandler.ashx.cs) and write a function to emit the
form-handling code (you can borrow it from the last exercise). Call the
method from inside ProcessRequest. Replace the stubbed-out method and property with real implementations.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace CustomHandlers
{
public class CustomFormHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
ManageForm(context);
}
public void ManageForm(HttpContext context)
{
context.Response.Write("<html><body><form>");
context.Response.Write(
"<h2>Hello there. What's cool about .NET?</h2>");
context.Response.Write("<select name='Feature'>");
context.Response.Write("<option> Strong typing</option>");
context.Response.Write("<option> Managed code</option>");
context.Response.Write("<option> Language agnosticism</option>");
context.Response.Write("<option> Better security model</option>");
context.Response.Write(
"<option> Threading and async delegates</option>");
context.Response.Write("<option> XCOPY deployment</option>");
context.Response.Write(
"<option> Reasonable HTTP handling framework</option>");
context.Response.Write("</select>");
context.Response.Write("</br>");
context.Response.Write(
"<input type=submit name='Lookup' value='Lookup'></input>");
context.Response.Write("</br>");
if (context.Request.Params["Feature"] != null)
{
context.Response.Write("Hi, you picked: ");
context.Response.Write(context.Request.Params["Feature"]);
context.Response.Write(" as your favorite feature.</br>");
}
context.Response.Write("</form></body></html>");
}
public bool IsReusable
{
get {return true; }
}
}
}
Browse to the CustomFormHandler.ashx file. It should work in just the same way as the handler implemented in the CustomFormHandler class that you wrote in the first example.
The advantage of using the
generic handler is twofold. First, it's usually much more convenient to
generate a simple handler than it is to create a whole new assembly to
handle the request. Second, you don't need to configure either
web.config or IIS (when it comes time to deploy). That is, ASP.NET and
IIS already understand what to do when encountering resource requests
with the extension of .ashx. Installing ASP.NET places those when
mapping to IIS.
However, ASHX files have the
same limitations as ASPX and ASCX files in terms of their place in an
ASP.NET project. Simple generic handlers go with the project. That is,
for the handler to work, it must accompany the whole project.
Alternatively, custom handlers deployed as separate assemblies you can
deploy and share throughout the enterprise as global assemblies (that
is, strongly named assemblies placed in the global assembly cache).