Extended CheckBoxList Control

A common task in programming is to retrieve all of the selected items or values from a CheckBoxList control. It is unfortunate that no native properties provide this already. However, extending the CheckBoxList to provide these is simple enough.

The extension I created provides four new properties:

  • SelectedValuesString – A comma-delimited string of the selected values.
  • SelectedValuesAsIntegers – An Integer List of the selected values.
  • SelectedValuesAsStrings – A string List of the selected values.
  • SelectedItemTextAsStrings – A string list of the text for the selected items.
public class ExtendedCheckBoxList : CheckBoxList
{
    public string SelectedValuesString
    {
        get
        {
            return String.Join(",",SelectedValuesAsStrings);
        }
    }

    public IEnumerable SelectedValuesAsIntegers
    {
        get
        {
            int temp;
            return this.Items.Cast<ListItem>()
                 .Where(i => i.Selected && int.TryParse(i.Value,out temp)).Select(i => int.Parse(i.Value));
        }
    }
    public IEnumerable SelectedValuesAsStrings
    {
        get
        {
            return this.Items.Cast<ListItem>().Where(i => i.Selected).Select(i=>i.Value);
        }
    }

    public IEnumerable SelectedItemTextAsStrings
    {
        get
        {
            return this.Items.Cast<ListItem>().Where(i => i.Selected).Select(i => i.Text);
        }
    }
}

Threading with Impersonation in an ASP.NET Project

Add to FacebookAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Yahoo BuzzAdd to Newsvine

Every once in a while, you might run into a need to do something that takes some time in a web app, but doesn’t require user interaction. Maybe you are processing an uploaded file (rescaling images, unzipping, etc). Maybe you are rewriting some statistical data based on new posts. Basically, something that takes minutes or hours – but isn’t that important to be interactive with the user.

You could set up a “job” in a database to be run the next time your timer runs (see https://lanitdev.wordpress.com/2010/03/16/running-a-scheduled-task/). If you don’t have a timer yet, though, that can be overkill if you don’t care that multiple jobs may run at once.

In my case, I needed to export a large volume of data to a zip file. I asked up front for an email address – and the user will receive a link to the completed zip in an email later. The job would only be performed by admins, and even then only about once a year – so there was no need to schedule the job – I could just fire it off when the user requested it.

Any easy way to do this is to use the .NET threading objects in System.Threading. Because I need to save a file, I also have one additional issue – Threads don’t automatically run under the same account that the site does, so I had to include code to impersonate a user that has write permissions.

Here’s a bit of code to get you started:

// param class to pass multiple values
private class ExportParams
        {
            public int UserID { get; set; }
            public string Email { get; set; }
            public string ImpersonateUser { get; set; }
            public string ImpersonateDomain { get; set; }
            public string ImpersonatePassword { get; set; }
        }

        protected void btnExport_Click(object sender, EventArgs e)
        {
//  .... code to get current app user, windows user to impersonate .....

            Thread t = new Thread(new ParameterizedThreadStart(DoExport));
            t.Start(new ExportParams(){
                UserID=CurrentUserID,
                Email=txtEmail.Text,
                ImpersonateUser = username,
                ImpersonateDomain = domain,
                ImpersonatePassword = password
            });
             // show user 'processing' message .....
         }

        private void DoExport(object param)
        {
            ExportParams ep = (ExportParams)param;

            using(var context = Security.Impersonate(ep.ImpersonateUser , ep.ImpersonateDomain,
             ep.ImpersonatePassword ))
          {
            // do the work here..............
          }
        }

Here’s the relevant part of the Security class that does the impersonation:

using System.Runtime.InteropServices;
using System.Security.Principal;
// .....
public class Security {
//.............
public const int LOGON_TYPE_INTERACTIVE = 2;
        public const int LOGON_TYPE_PROVIDER_DEFAULT = 0;
        // Using this api to get an accessToken of specific Windows User by its user name and password
        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        static public extern bool LogonUser(string userName, string domain, string passWord, int logonType, int logonProvider, ref IntPtr accessToken);

        public static WindowsImpersonationContext Impersonate()
        {
            return Impersonate("DEFAULT_USER","DEFAULT_DOMAIN","DEFAULT_PASSWORD");
        }
        public static WindowsImpersonationContext Impersonate(string username, string domain, string password)
        {
            IntPtr accessToken = IntPtr.Zero;
            //accessToken.Debug();
            var success = LogonUser(username, domain, password, LOGON_TYPE_INTERACTIVE, LOGON_TYPE_PROVIDER_DEFAULT, ref accessToken);

            //accessToken.Debug();
            if (!success)
                return null;

            WindowsIdentity identity = new WindowsIdentity(accessToken);

            return identity.Impersonate();
        }
// ..........
}

Using the Web.Config connection string with LINQ to SQL

When updating a project to use LINQ to SQL, I found an issue with deploying to multiple environments.  Each environment (development, staging, live) had its’ own database associated with this.  Since I had the .dbml in another assembly, it was only reading from the app.config in the assembly it resided in.  I was storing the database connection string in the web.config of the project so I thought it would be nice to just use that instead of the app.config.

The first thing I needed to do was to keep the .dbml file from reading from the app.config.  After opening up the .dbml file, I opened the properties window for the file.  In the properties window, there is a setting for “Connection”.  In the “Connection” dropdown I selected the “(None)” selection.  That keeps the .dbml file from accessing the app.config for the database connection string.



The "Connection" setting in the .dbml Properties

Now I needed to get my MainDataContext to use the Web.Config connection string.  For this I created a partial class for my MainDataContext and created a constructor that passed the connection string from the Web.Config.

public partial class MainDataContext
{
    public MainDataContext()
        : base(System.Configuration.ConfigurationManager.ConnectionStrings["Database.connection.string.from.web.config"].ToString(), mappingSource)
    {
        OnCreated();
    }
}

Now when I deploy to different environments the .dbml file is accessing the correct database instead of the same one from the app.config.

Handy ASP.NET Debug Extension Method

Add to FacebookAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Yahoo BuzzAdd to Newsvine

Most of the programmers I know (myself included) don’t bother with the built in Visual Studio debugging tools. They are slow and resource intensive. Usually, its more efficient to just do one or more Response.Write calls to see key data at key steps.

That can be a hassle, though. Most objects don’t print very well. You have to create a loop or write some LINQ/String.Join to write items in a collection.

Inspiration struck – couldn’t I write an extension method on object to write out a reasonable representation of pretty much anything? I could write out html tables for lists with columns for properties, etc.

Then I thought – I love the javascript debug console in firebug. I can drill down into individual items without being overwhelmed by all of the data at once. Why not have my debug information spit out javascript to write to the debug console? That also keeps it out of the way of the rest of the interface.

Here’s the code:

public static void Debug(this object value)
        {
            if (HttpContext.Current != null)
            {
                HttpContext.Current.Response.Debug(value);
            }

        }

        public static void Debug(this HttpResponse Response, params object[] args)
        {

            new HttpResponseWrapper(Response).Debug(args);
        }
        public static void Debug(this HttpResponseBase Response, params object[] args)
        {

            ((HttpResponseWrapper)Response).Debug(args);
        }
        public static void Debug(this HttpResponseWrapper Response, params object[] args)
        {

            if (Response != null && Response.ContentType == "text/html")
            {
                Response.Write("<script type='text/javascript'>");
                Response.Write("if(console&&console.debug){");

                Response.Write("console.debug(" +
                              args.SerializeToJSON() +
                               ");");
                Response.Write("}");
                Response.Write("</script>");
            }
        }

The various overloads allow:

myObject.Debug();
new {message="test",obj=myObject}.Debug();
Response.Debug("some message",myObject,myObject2);
//etc

The only other thing you’ll need is the awesome JSON.NET library for the .SerializeToJSON() call to work (which turns the .NET object into the form javascript can deal with). Get it here. FYI, the library does choke serializing some complex objects, so occasionally you’ll need to simplify before calling debug.

Extended DropDownList Control

Add to FacebookAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Yahoo BuzzAdd to Newsvine

It’s a very common situation.  A dropdownlist has a parent whose selected value determines what options will be bound to it.  But what happens when there are none?  And what happens if there’s only one option?  And why do I have to enter code to insert “Select an Item” to the list?  And why does it continue to display even when no item has been selected on its parent and it doesn’t have any values at all?  And why does it continue to display immediately after the parent’s value has been changed and the page is reloading?

Well, what if it wasn’t that way?  What if it accounted for all those things?  That would be really nice, and, in fact, it actually is quite nice.

This extended dropdownlist control has the following additional parameters:

  • ParentDropDownListID – Specifies the id field of the parent dropdownlist.
  • ParentItemUnpopulatedText – Specifies the text to display when the parent dropdownlist has yet to be populated.  The dropdownlist itself will be hidden and this text appears in its place, giving the user appropriate feedback.  The default is “n/a” since this dropdownlist really isn’t applicable until its parent is populated.  (This comes up in a series of three or parent/child dropdownlists.)
  • ParentItemNotSelectedText -Specifies the text to display when the parent dropdownlist has been populated but no item has yet been selected (The selected item is “Select an item”.)  So, for a state/city relationship it could say “Please select a state” or “n/a”–whatever you want.  But the dropdownlist itself is hidden, so the user can’t select it and wonder why there’s nothing in it to select.
  • ControlsToHideOnChange – This actually specifies children dropdownlists to hide whenever the selected item changes.  In a state/city relationship, if you change the state, the city dropdownlist will need to be repopulated.  However, sometimes the page takes a little while to load and the user may try to select a city before that gets repopulated.  To avoid the confusion, the city dropdownlist, whose ID is specified in this parameter, will be immediately hidden via JavaScript and a message will appear in its place indicating that the user needs to wait until it is repopulated.  You can actually specify multiple children to hide, so if you had county and city children, both would be hidden while the page reloads.  The text is specified in the ChildrenRepopulatingText.
  • ChildrenRepopulatingText – The text that replaces the child controls specified in ControlsToHideOnChange whenever the selected item for this control (the parent) changes.
  • HasSelectedItemText – true/false – defines whether or not a “Select Item” option should be added to the dropdownlist.  I will probably eliminate this and just add one based on whether or not the SelectItemText parameter is specified.
  • SelectItemText – Specifies the text to add as the first item (with a value of -1) to the dropdownlist.
  • NoItemsText – Specifies the message to display if there are no items in the dropdownlist, since an empty dropdownlist is annoying.  The actual dropdownlist will be hidden and this text will display.  So, this could be “There were no cities defined for the state you selected.”

Additionally, if there is only one item bound to the dropdownlist, the dropdownlist goes ahead and selects that item.  The dropdownlist itself is hidden, and the item text is displayed as a message.  It is just annoying when you have a dropdownlist with a single item, but you still have to select it because you have a “Select Item” option that is the initially selected item.

So, that’s the extended control as it is now.  Hopefully, it will save coding time and provide a better overall user experience.
NOTE: The control as it is written does use Jquery commands as well, so if you’re not referencing that, you’ll need to rewrite the JavaScript.


public class ExtendedDropDownList : DropDownList
{
    public bool HasSelectItemText
    {
        get
        {
            object o = ViewState["HasSelectItemText"];
            if (o == null)
                return false;
            else
                return (bool)o;
        }
        set
        {
            ViewState["HasSelectItemText"] = value;
        }
    }

    public string SelectItemText
    {
        get
        {
            object o = ViewState["SelectItemText"];
            if ((o == null) || ((string)o == ""))
                return "Select an Item";
            else
                return (string)o;
        }
        set
        {
            ViewState["SelectItemText"] = value;
        }
    }

    public string NoItemsText
    {
        get
        {
            object o = ViewState["NoItemsText"];
            if ((o == null) || ((string)o == ""))
                return "No items available to select";
            else
                return (string)o;
        }
        set
        {
             ViewState["NoItemsText"] = value;
        }
    }

    public string ParentDropDownListID
    {
        get
        {
            if (ViewState["ParentDropDownListID"] == null)
                ViewState["ParentDropDownListID"] = "";
            return (string)ViewState["ParentDropDownListID"];
        }
        set
        {
            ViewState["ParentDropDownListID"] = value;
        }
    }

    public string ParentItemNotSelectedText
    {
        get
        {
            if (ViewState["ParentItemNotSelectedText"] == null)
                ViewState["ParentItemNotSelectedText"] = "";
            return (string)ViewState["ParentItemNotSelectedText"];
        }
        set
        {
            ViewState["ParentItemNotSelectedText"] = value;
        }
    }

    public string ParentItemUnpopulatedText
    {
        get
        {
            if (ViewState["ParentItemUnpopulatedText"] == null)
                ViewState["ParentItemUnpopulatedText"] = "n/a";
            return (string)ViewState["ParentItemUnpopulatedText"];
        }
        set
        {
            ViewState["ParentItemUnpopulatedText"] = value;
        }
    }

    public string ControlsToHideOnChange
    {
        get
        {
            if (ViewState["ControlsToHideOnChange"] == null)
                ViewState["ControlsToHideOnChange"] = "";
            return (string)ViewState["ControlsToHideOnChange"];
        }
        set
        {
            ViewState["ControlsToHideOnChange"] = value;
        }
    }

    public string ChildrenRepopulatingText
    {
        get
        {
            if (ViewState["ChildrenRepopulatingText"] == null)
                ViewState["ChildrenRepopulatingText"] = "Repopulating Options...";
            return (string)ViewState["ChildrenRepopulatingText"];
        }
        set
        {
            ViewState["ChildrenRepopulatingText"] = value;
        }
    }

    public string[] ControlsToHide
    {
        get
        {
            return ControlsToHideOnChange.Split(',');
        }
    }

    public override void DataBind()
    {
        base.DataBind();

        int itemCount = this.Items.Count;
        if (HasSelectItemText && itemCount > 1)
            this.Items.Insert(0, new ListItem(SelectItemText, "-1"));
        if (itemCount == 0)
            this.SelectedIndex = -1;
        else
            this.SelectedIndex = 0;
    }

    protected override void CreateChildControls()
    {
        base.CreateChildControls();
        if (ControlsToHideOnChange != "")
        {
            ServerPage page = GetPage();
            foreach (string s in ControlsToHide)
            {
                this.Attributes["onchange"] = "$('#" + page.FindControl(s).ClientID + "').hide();" + "$('#" + page.FindControl(s).ClientID + "').parent().text('" + ChildrenRepopulatingText + "');" + this.Attributes["onchange"];
            }
        }
    }

    protected override void Render(System.Web.UI.HtmlTextWriter writer)
    {
        EnsureChildControls();

        DropDownList parent = (DropDownList)GetPage().FindControl(ParentDropDownListID);
        bool hasUnselectedParent = (ParentDropDownListID != "") && (parent != null) && (parent.Items.Count > 0) && (parent.SelectedValue == "-1");
        bool hasUnpopulatedParent = (ParentDropDownListID != "") && (parent != null) && (parent.Items.Count == 0);

        writer.WriteLine("<div>");

        if (hasUnselectedParent)
        {
            this.Items.Clear();
            writer.WriteLine("<span>" + ParentItemNotSelectedText + "</span>");
            this.Attributes.CssStyle["display"] = "none";
        }
        else if (hasUnpopulatedParent)
        {
            this.Items.Clear();
            writer.WriteLine("<span>" + ParentItemUnpopulatedText + "</span>");
            this.Attributes.CssStyle["display"] = "none";
        }
        else
        {
            if (this.Items.Count == 0)
            {
                writer.WriteLine("<span>" + NoItemsText + "</span>");
                this.CssClass = "hide";
            }
            else if (this.Items.Count == 1)
            {
                writer.WriteLine("<span>" + this.Items[0].Text + "</span>");
                this.CssClass = "hide";
            }
        }

        base.Render(writer);

        writer.WriteLine("</div>");
    }

    private Foliotek.Components.ServerPage GetPage()
    {
        System.Web.UI.Control control = this;
        while (control.GetType() != Type.GetType("Foliotek.Components.ServerPage"))
        {
            control = control.Parent;
        }
        return (Foliotek.Components.ServerPage)control;
    }
}

Accessible Custom AJAX and .NET

Add to FacebookAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Yahoo BuzzAdd to Newsvine

One general rule in making an accessible web application is that you shouldn’t change content of the page with javascript. This is because screen readers have a tough time monitoring the page and notifying the user of dynamic changes. Usually, the reason you would use Ajax is exactly that – do something on the server, and then update some small part of the page without causing the whole page to refresh. That means if you have an “ajaxy” page and you care about accessibility, you have to provide a non-ajax interface as a fallback for screen readers.

Ajax.NET, Microsoft’s library for Ajax, makes this fallback easy to implement. Microsoft has you define your AJAX properties in an abstraction layer – the page XAML – which means that the framework can decide to not render the AJAX code to certain browsers (and screen readers) that will not support it, and instead use the standard postback method.

The problem with Ajax.NET is that the communication can be bloated (mostly because of the abstraction layer, it sends more post values than you might need – like the encrypted viewstate value), which negates many of the benefits of an Ajax solution. I really wanted to roll my own ajax communications to make them as lightweight as possible.

My solution was to write the page in a standard .NET postback manner, and then use a user-defined property that would allow javascript to replace the postback in javascript/jQuery with an Ajax call.

Here’s my code:

$(function() {
            if (serverVars.uiVersion != "accessible") { // use js/ajax for checking/unchecking where possible
                var $todos = $("#chkToDo");
               $todos.removeAttr("onclick"); // remove postback
                $todos.click(
                    function() {
                        //some stuff altering the document, and an ajax call to report the change to the db
                    }
                );
            }

This works great, although you need to be careful about your server-side events. In my case, I had an OnCheckChanged event to handle the postback/accessible mode. Even though checking/unchecking the box no longer fired an autopostback – ASP.NET will still fire the checkchanged event if you postback later for some other reason (e.g. – a linkbutton elsewhere on the page) after the checked status had changed. So, if a user had changed the state of a checkbox, then clicked another link button on the page – instead of sending the user to the intended page,my app just refreshed the whole page(because my CheckChanged event redirected to reload the page – which caused it to skip the ‘click’ event of the linkbutton). Once I realized this was happening, it was easy enough to fix – I just needed to only run the event logic if the user was in accessibility mode. I spent a little time running in circles on that one though, at first I thought my client side document changes were causing a ViewState validation error on the server.

Avoid static variables in ASP.NET

Add to FacebookAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Yahoo BuzzAdd to Newsvine

Occasionally, I like to write static methods on classes. They are useful whenever the method loosely relates to to the class – but it doesn’t involve a specific instance of the class.

A good example of a static method in the .NET library is the int.Parse(string val) method. This method basically reads a string and tries to return an integer representation. The method logically fits with the int Class (I suppose a string could have a ToInt() instance method…but that would be overwhelming as you added ToFloat(), ToDecimal(), To…()) – but when you run it, there’s no reason to have an instance of int already. You run it to create a new instance of int.

Commonly, I follow similar logic in the business layer of my webapps. I write a static Add(param1,….,paramx) method that returns an instance of the class after it is persisted to the database. I could accomplish this other ways, but I think the resulting application code reads better like:

      User.Add(username,password);

Than:

      new User(username,password).Add();

or, worse:

      DataContext.Users.InsertOnSubmit(new User(username,password));
      DataContext.SubmitChanges();

The issue with static methods in your business logic is that you often need a common object to talk to the database through: a SqlConnection, a TableAdapter, A LINQ DataContext, etc. I could certainly create those objects locally inside each static method, but that’s time consuming and hard to maintain. I want instead to define a common property (in the business class or a parent class of it) that lazy-initializes and returns an instance of the object when I need it. The problem is that the property must also be static for a static method to have access to it.

The easiest way to accomplish this is something like:

      private static ModelDataContext dataContext=null;
      protected static ModelDataContext DataContext
      {
            get
            {
                 if(dataContext==null)
                     dataContext = new ModelDataContext();
                 return dataContext;
             }
       }

The tricky thing is that this will probably work in development and testing, until you get some load on your website. Then, you’ll start seeing all kinds of weird issues that may not even point to this code as the problem.

Why is this an issue? It’s all about how static variables are scoped inside a ASP.NET application. Most web programmers think of each page in their application as its own program. You have to manually share data between pages when you need to. So, they incorrectly assume that static variables are somehow tied to a web request or page in their application. This is totally wrong.

Really, your whole website is a single application, which spawns threads to deal with requests, and requests are dealt with by the code on the appropriate page. Think of a page in your webapp as a method inside of one big application, and not an application of its own – a method which is called by the url your visitor requests.

Why does this matter? Because static variables are not tied to any specific instance of any specific class, they must be created in the entire application’s scope. Effectively, ASP.NET static variables are the same as the global variables that all your programming teachers warned you about.

That means that, for the property above, every single request/page/user of your website will reuse the first created instance of DataContext created. That’s bad for several reasons. LINQ DataContexts cache some of the data and changes you make – you can quickly eat up memory if each instance isn’t disposed fairly quickly. TableAdapters hold open SQLConnections for reuse – so if you use enough classes of TableAdapters, you can have enough different static vars to tie up all of your db connections. Because requests can happen simultaneously, you can also end up with lots of locking/competing accesses to the variable. Etc.

What should you do about it? In my case, I take advantage of static properties that reference collections that are scoped to some appropriately short-lived object for my storage. For instance, System.Web.HttpContext.Current.Items:

      protected static ModelDataContext DataContext
      {
            get
            {
                 if(System.Web.HttpContext.Current.Items["ModelDataContext"]==null)
                     System.Web.HttpContext.Current.Items["ModelDataContext"] = new ModelDataContext();
                 return (ModelDataContext)System.Web.HttpContext.Current.Items["ModelDataContext"];
             }
       }

In this case, each instance of DataContext will automatically be disposed for each hit on the site – and DataContexts will never be shared between two users accessing the site simultaneously. You could also use collections like ViewState, Session, Cache, etc (and I’ve tried several of these). For my purposes, the HttpContext.Items collection scopes my objects for exactly where I want them to be accessible and exactly how long I want them to be alive.

Using Custom Properties Inside LINQ to SQL Queries

Add to FacebookAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Yahoo BuzzAdd to Newsvine

One thing that initially caused me some trouble with Linq to SQL was that properties
and functions defined on the object cannot be translated to SQL. For example, this code throws an
“The member ‘Table1.DisplayName’ has no supported translation to SQL.” exception when executed.

public string DisplayName
   {
      get
      {
         return this.NameFirst + " " + this.NameLast;
      }
}

public static IQueryable<Table1> GetAll()
{
   return (from t in DataContext.Table1s
             select t).OrderBy(t => t.DisplayName);
}

One simple solution is to just define your sort option each time it needs used.

public static IQueryable<Table1> GetAll()
{
   return (from t in DataContext.Table1s
             select t).OrderBy(t => t.NameFirst + " " + t.NameLast);
}

This option is pretty tedious to write and maintain, especially if you’re going to be using the function often.

Another option is to define a System.Linq.Expression, which is a lambda expression that can be converted to SQL.

static Expression<Func<Table1, string>> DisplayNameExpr = t => t.NameFirst + " " + t.NameLast;

public static IQueryable<Table1> GetAll()
{
   return (from t in DataContext.Table1s
             select t).OrderBy(Table1.DisplayNameExpr);
}

Note that if you do choose this way, the “DisplayName” is essentially defined in two different places. To solve this problem, use the expression to define the property.

{
   get
   {
      var nameFunc = DisplayNameExpr.Compile(); // compile the expression into a Function
      return nameFunc(this); // call the function using the current object
   }
}

Note this method can also be used to define functions that accept arguments,  so the following code also works as expected.

static Expression<Func<Table1, bool>> HasReq(int numReq)
{
   return (t => (t.IntItem + t.AnotherInt) > numReq);
}

public static IQueryable<Table1> GetWithReq(int req)
{
   return (from t in DataContext.Table1s
             select t).Where(Table1.HasReq(req));
}

Some Good Uses for the ASP.NET .ASHX/”Generic Handler”

Add to FacebookAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Yahoo BuzzAdd to Newsvine

I’ve been developing ASP.NET applications since 2002.  Up until recently, I’d overlooked a pretty useful part of the ASP.NET Framework : Generic Handlers.

Generic Handlers are basically HTTP Handlers that can process requests to exactly one url (Http Handlers are classes that need to be registered in the web.config for what urls they run on, and often manipulate requests/responses that go to/come from .aspx pages). They are “closer to the wire” than .ASPX WebForms or .ASMX WebServices.  They are built with only two requirements, implement:

public void ProcessRequest(HttpContext context);

(this contains the logic for when this page is requested) and, implement:

public bool IsReusable;

(this tells ASP.NET whether it can use one instance to serve multiple requests).

Generic Handlers are similar to web forms – they are reachable by a standard get/post to the url they are located in.  ASP.NET starts you off with context object (passed into the ProcessRequest() function you implement), which you then use to communicate with the request (form and query vals, etc) and the response object (to write info to the browser).  You can decide in what capacity you want that context to have access to the session:read/write, readonly, or none. Unlike web forms, generic handlers skip some of the niceties: the designer/xaml/servercontrol model, themes, viewstate, etc. Thus, generic handlers can be much more efficient for many tasks that make no use of those features.

Here’s a few common tasks where a generic handler would be more suitable than a web form:

  • Writing out the contents of files stored in the db/elsewhere for download
  • Writing out manipulated images, generated graphics, etc
  • Writing out generated PDFs/CSVs etc
  • Writing out data without the webservice overhead
    • xml for other systems or sites
    • html for simple AJAX get requests to replace page content
    • JSON for more advanced ajax data communication
  • Callback urls for data sent from other sites through a http post
  • Building a “REST API”
  • A url that outputs status info about the website, for use by a content switch or other monitoring system
  • Writing out dynamic JS/CSS based on server variables, browser capabilities, etc

Basically, anywhere I found myself before creating an ASPX page, but clearing everything on the .ASPX and using Response.Write()/Response.BinaryWrite() to talk to the browser or another system from the code behind, I should have been using a .ASHX handler instead and saving my webserver some work.

Here is a sample GenericHandler to get you started. It writes out a simple js file that gives you some useful globals you can use in other js files. Its meant to just be an example of the types of things you can do with generic handlers, and doesn’t necessarily produce what you might want in your own dynamic JS file.


    public class SiteJSGlobals : System.Web.IHttpHandler, System.Web.SessionState.IReadOnlySessionState
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/javascript";

            context.Response.Write("var _g_username='" + context.User.Identity.Name + "';\n");
            context.Response.Write("var _g_usertype='" + context.Session["UserType"] + "';\n");
            context.Response.Write("var _g_browserheight=" + context.Request.Browser.ScreenPixelsHeight + ";\n");
            context.Response.Write("var _g_browserwidth=" + context.Request.Browser.ScreenPixelsWidth + ";\n");
            context.Response.Write("var _g_queryparam='" + context.Request["queryparam"] + "';\n");
            context.Response.Write("var _g_developmentmode=" + context.Request.Url.Host.ToLower().StartsWith("localhost") + ";\n");
            context.Response.Write("var _g_approoturl='" + context.Request.ApplicationPath + "';\n");
        }
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }