GitHub repository now available

Introduction

In ASP.NET, we have something that is usually overlooked that is called Generic Handlers. I see a lot o f people using pages to process AJAX requests when we can use this much less expensive
endpoint.
This is an completely worked out Generic Handler that truly knows how to handle your http (AJAX and not) requests.

Background

For a long time I used plain Generic Handlers (ASHX files) to handle my AJAX requests but it felt stupid and painful.
I mean, the functionality was there but the whole process of handling the requests wasn't straight forward.
So I made a list of the things I would like to have and now it's already a lot more than that.

NEW v2.5!

Fully supports collections as requests arguments

Nested collections are fully supported

Native and Complex item types supported

Improved support for complex types as method arguments

Improved HTTP verbs filter

New HTTP verbs filter attributes (DELETE and PUT)

Improved controller Help (more to come soon)

Improved performance (still working to further improve this)

Performance improvements are always a work in progress. From the simple tests I've done this controller already performs at the same level as the ASP.net MVC controllers.

New PerformanceTest.aspx added to main demo project

New ASP.net MVC project created for performance comparison with MVC controllers

This project isn't added to the solution. Add if you want to use it.

Small refactoring and improvements all around

NEW v2.0!

OnMethodInvoke and AfterMethodInvoke virtual methods

These allow the possibility to intersect the execution before and after the method call

public void SetResponseContentType(ResponseContentTypes value)

Easy way to set the response content type from the enum

Specify supported HTTP verbs by handler and by method

Now we can specify if a method only supports certain HTTP verbs by simply decorating the method with the related Attribute

Default methods for main HTTP verbs (GET, POST, PUT and DELETE)

If no method is passed the handler will call the method related with the Request HTTP verb.

These methods can me overrided to implement your logic.

Response serialization improvements (JSON and XML)

You can now use the returntype parameter on the Request to specify how you want your response data without having to modify your code.

The default is JSON but you can also pass XML or HTML.

The default serialization can be disabled on method scope.

Performance optimization

v1.1

Support for complex objects as method argument

Now you can put your custom classes on the handler methods arguments.

Automatically hydrates the class and all its nested types!!

v1.0

Standard way to parse the query string

Transparently handle multiple methods within the same handler

Support methods with multiple typed arguments, not just strings

Support Methods that receive lists as an argument

Support passing less arguments than the method is expecting (like optional parameters)

Transparently reply either POSTs or GETs

Support default object serialization to JSON but still let me override it on each method

Return application/json by default but still let me override it on each method

Support jQuery $.ajax request

Support request by query string (URL right on the browser)

A way to visualize the methods the handler supports (like webservices do)

Extensible

Using the code

I'm working to improve this documentation.
Until then, all you need to know is on the Default.aspx of the demo project.

List the Handler methods

I've provided a very basic way of listing the methods the Handler exposes.
This is specially useful to test if the handler is working correctly (like on webservices).
Do do so just append ?help at the end of the handler URL:

http://localhost/mydemohandler.ashx?help

Calling the Handler from the browser URL

Using this handles is very simple:

Create a new Generic Handler

Clear everything inside the handler class

Inherit from my Handler class

DONE! Now you only need to add your methods.

Let's create a very simple example that receives a name and returns a string (see on the project).

Writing a method that returns HTML

Like I said on my intention points above, I need to have some methods that return whatever I want like HTML, XML, images, files, etc...
The default behavior of the handler is to return JSON so, by method, we need to explicitly say that we want to handle things our way.
For that just use these lines anywhere within the method:

Optional Parameters and nullable types

All parameters in the methods are optional. If they're not passed their default value is assigned.
Also all parameters can be nullable. In this case the default value will be null.

Support for complex types

Say you have a JSON object and a class server side that maps it. Hydrating this class server side is a pain. Usually we pass each property as an argument of the method on the Handler, instantiate a new instance of the class and set the properties one by on... a pain right?
NO MORE! This handler now supports automatic class instance creation and property set. Something I like to call Object Hydratation! https://www.codeproject.com/script/Forums/Images/smiley_smile.gif " />
And there's more! If this class have properties that also expose other custom classes they will be hydrated too!!
Just make sure all classes have a public default constructorr

Comments and Discussions

Thank you for sharing your work. This is what I was looking for, and very glad I found it, hence my vote of 5.

I wonder if you could help me with this problem: How should I build a cURL query to access a method and pass parameters?For instance, how would cURL call, from command line, the methods GreetMe(string name) or TalkAboutMe(string name, int age) or SendPersonData(Person person)?

As it's a GET, the arguments must be passed in the URL.
My examples use jquery for the ajax request which does exactly that with the data property.

I need to set it up and test but this would be my first attempt

Regarding your second example, it's a POST and, in that case, the handler is expecting the data to go in the request body. I need to debug those requests to be sure how they're arriving in the handler.

Meanwhile, you can simply put a breakpoint in the ProcessRequest method and see if the request is arriving and how it's arriving.

Before posting my message yesterday, I have attempted to do what you suggested, namely "putting a breakpoint in the ProcessRequest method and see if the request is arriving and how it's arriving."However, it was already pretty late in the night, so thought I may get faster asking you

On the javascript side you just have to pass the arrays in the correct format.If it's an int[] then you should pass something like : [1,2,3,4,5]Otherwise if it's an array of objects: [ {name: 'Person 1', age: 12}, {name: 'Person 2', age: 35} ]

The handler will do its best to map the json objects into your .Net objects.Any missing properties will be left with their default values.In case of complex objects, just make sure you have a default constructor so that the handler can initialize the object.

This project needs a bit of love from my part... the sources are a mess.I've been whiling to do so but there's always something else that jumps in front

I already explained my intentions and reasons on earlier the comments.HTTP Handlers have their own space and usage and they don't compete with anything else.

So, If HTTP Handlers are the best choice for your implementation then you might consider using this helper to avoid tedious and repetitive code, otherwise you have a full stack of other options even from WebMethods or WCF...

I think it's time to improve article and explain the reasons and alternatives in up front.

I liked your article, it was interesting. While reading it, I was wondering if you had a chance to look into the Json.NET project on Codeplex, and if so, if you could comment on the serialization facilities provided between .NET objects and JSON by that library? From my naïve point of view, it seemed like it might be quite useful for the kind of problem you're discussing.

We are actually passing JSON into the controller so parsing it back to an object should be straight forward, specially using a neat tool like JSON.net, right?I must confess that I had to test it before replying but at the end I couldn't find a way to do this using either JSON.net or any other helper tool and here's why:

Simple GET requestLets forget JSON for now and do a normal GET request to the controller:

http://localhost/mycontroller.ashx?method=MyMethod&name=Alex&age=36

This will be received by a method on the controller with the following signature:

publicobject MyMethod(String name, int age) { return"something"; }

So one of the main functionalities of this Advanced controller is to actually automatically call the method we want and parse the request arguments into the method's arguments. You can test this on the demo project.

Now with JSON and AJAX HTTP GET requestIf you do an AJAX call to the controller and pass the following object:

{method:'MyMethod', args:{name:'Alex',age:36}}

You'll basically get the same result as the previous request but a bit different:

The 'method' is used internally to search for the method to invoke within the controller.the rest are the arguments that will be passed to that method. These arguments also need to be casted to the correct type expected by the method.

And it gets worse...If for example we are passing an array of objects we can get something like:

This last example samples a people class that has a person class collection property.We need to create new instances of each type and hydrate the objects.

Collection types can also be basic Arrays or List<>, which need to be created and handled differently.

Beyond HTTP GETPOST, PUT and DELETE pass data differently. They don't use the QueryString.Instead the pass all the data in the request params which need to be handle slightly differently.

To wrap all upSo, all this explanation to say that AFAIK there's no way, out of the box, to translate this request information to objects. And this was my main goal when I started this project.

I can, in fact, use JSON.net to serialize the response.I didn't do it already because I didn't want to add a reference to an external assembly or increase the size of this one by adding the JSON.net source code into it.

Hope I managed to explain my intentions and decisions.If anyone knows a better way to do this I'm all ears!!!

What do you mean by "but these article is in novice level"?If it's for the quality of the article itself you're more than right but I was actually struggling to have time to make the tool itself working properly and posted the update as soon as I was satisfied enough with the result.

I'm currently working with different technologies so I'm not actively using this as I was at the time I posted the first version.

My next steps are to benchmark the controller and post some other things that I have that use this extensively like the query engine helper that supports the link with jqGrid out of the box.

The quality of the article itself I'm afraid will always be left for last as long as I have good stuff to share with you guys. Sorry for that, but I'm open to get some help or contribute if anyone wants to engage on something interesting.

On the solution you'll find a pretty good demo environment that illustrates pretty much everything you can do with this controller.

As usual, any feedback is always welcome, just tell me what you thing and how it can be improved and I'll try to push it forward.

Dear AlexCode My mean is that your article just illustrate the basic use of generic handler (Just this). my mean is not your article is bad, No No this article is pretty good , it's great just for beginners. But you named this article 'Advanced' (That I think this is not). My low rate is just because of it's name/tile.At the end, I thank you again and again...your article is very good( I think just for beginners not advanced programmers)(sorry for my bad English!)have a good time/bye

Out of the box, Generic Controllers do basically nothing but handling one request.If you want to have multiple methods inside and be able use them as different entry points of the same controller then you have to implement that by hand yourself.And this is actually the basic stuff.

The advanced part is to make the controller automatically redirect to the right method and parse whatever arguments you are passing into the method, hydrating classes, nested types, collections, etc... none of these are done by the native Generic Controller.

With this controller you can also filter the requests by HTTP verb on Controller level or method level and process the 4 different verbs transparently... The out of the box handler couldn't care less about the request. You receive it on the ProcessRequest method and is up do you to do all the plumbing by hand.

There are a lot other functionalities implemented, and I would recommend a more careful reading and usage of this tool if you want to better understand what it does.

Sure you can make AJAX calls directly to a WCF service but... do you really want to?Does WCF completely trashes HTTP Handlers?My answer to this have always been "No", and here's why:

1. WCF Services are usually and Application by themselves.The definition of service usually comes with the notion of sharing business rules between different applications and/or facilitate scalability on a certain functionality.Based on the above, it never seemed clever to me to put a WCF service inside a web application.Also, if all you want is an entry point to your AJAX requests, why would you need to go through the overhead of creating a WCF Service?

2. AuthenticationIf your WCF Service is a different application (and I explained on (1) why I believe it should be so), you'll have to deal with some sort of syndicated authentication mechanism or expose the service without authentication.If your application requires authentication then you'll want your AJAX requests also to be authenticated right?

On the other hand with HTTP Handlers, the authentication is done the very same way as with web pages. You can have them on the same authentication scope of put them inside a folder with a specific web.config file for different permissions. No extra effort.

3. HTTP Handlers are like Webpages but with a shorter pipeline.Basically speaking, ASHX's are like a Webform but without the rendering part which makes them the ideal candidate for the AJAX calls handlers. No unnecessary juice.

4. WebAPI[^]: the real true competitor but...Web API appeared a couple of years later this code have been produced (actually coded, not being posted here on CP) although WebAPI if still to attached to the MVC paradigm. You can use it on webforms but not quite, MVC will always be around in a undisguised way.

So here are my reasons.As usual, I try not to do things out of nothing and I surely didn't "reinvent the wheel".I was using HTTP Handlers as the end-point of my AJAX calls long before I came up with this code. In fact, the reason I wrote this was because I had enough of doing this plumbing manually all the time.

What I came up with was extending the functionality of the HTTP Handler component to which there's still nothing really comparable.

1. Nothing limits you to use WCF together with website2. Even if WCF is a seperate app, you can disable all security and have it work just like http handler3. True - I wouldn't even think about using plain System.Web.Page for non UI processing4. I don't like anything coupled with anything

I use httphandlers a lot, but never as ajax service..

Some use cases:File downloading proxyDynamic image generatorRedirect service

1. I said so, I just find it fundamentally wrong in both development and architectural perspectives.2. Also said so, but that is a simplification for sites that don't require authentication. Personally I don't work on a website (web application) that don't require any kind of authentication for a lot of years.3. True, but it's not that uncommon.4. Usually is a good approach but if you're on an MVC project WebAPI is a good option.

HaBiX wrote:

I use httphandlers a lot, but never as ajax service..

Could you share your experience and explain why?

HaBiX wrote:

File downloading proxy, Dynamic image generator, Redirect service

I already used this AdvancedController for File download, Audio and Video streaming and dynamic or static image manipulation.It supports basic http requests also so for instance, on the Image manipulation Handler I have several methods and this makes it easy to invoke the right method and pass the arguments based on the QueryString.

You can still put the code in its own project, make dll and declare it in your web.config.This way you seperate the logic, but it runs on same website.

Most of my cases need windows authentication through domain controller. If I use WCF and set the same security on website&wcf, nothing special needs to be done on client side.. identity used to login to windows is used on website and wcf side (even sql login through domain group).

I like to use WCF for ajax applications coz most of the time the website in farm itself needs that service, but I don't want to use HTTP as transport over LAN. By using WCf I can simply change the transport and reuse the service.

Why I don't use httphandlers in ajax situations - because WCF service is implemented closer to what I need. (eg. I can start writing methods right away - without inheriting extra stuff).

I've been really busy lately but I really need to improve this tool.Returning a list is pretty straight forward, as you only need to return it from the controller method and it will get serialized on JSON automatically.

I'll include and example of this on the next release but if you need any further help feel free to get back to me.P.S.:All this code was written directly on this reply, it should work as is but might have some syntax errors that I missed.

First of all, congrats for your excellent job.I love the ashx and always use them when I can.Yes, I need array for my project.So if you do it it will be perfect.If you can't I'll try to do it myselfFede

I'm working on it but it's still not finished.fvilli sent me his solution to support this functionality (thank you very very much) but although it works perfectly on a one level hierarchy it fails if we have collections inside collection items.

Honestly I haven't been able to give too much time on this but I'm picking it just after this reply.

Thanks for your follow up, as I had to get an immediate solution, I workaround it by stringifying complex object arguments and keeping other types (string, int). stringified objects are deserialized in the invoked method accordingly where it passed as string objects.

Hi Alex and thanks for this great piece of code. I think I'm having a problem though. If I don't set the response content type to json manually then the response is served as text/html by default. This happens regardless of how i call the handlers method (tried manually from the browser, jquery's getJSON etc) You mention that the default response content type is json. Am I missing something here? Thank you!

Hi!As I usually use this on my jquery AJAX requests I simply disable the cache right on the request.I know it doesn't really "disables" the cache, it just add a timestamp at the end of each GET request to make it different and invalidate cache but it works fine

Your idea is great although that configuration must be passed on the querystring... not pretty.

Why query string? Why not some property that could be set in derived class constructor or in method (like you way of disabling default json serialization). If that property is true - add cache disabling headers to response. Something like that =)

Ah ok.I was seeing that as optional by request.Doing it on the handler method it self is much easier.

So what you really need is a common place where you can set configurations to all requests to that handler.The best solution for this and other "problems" is for me to add two virtual methods to the AdvancedHandler:BeforeProcessRequestIs called before your method

AfterProcessRequestIs called after your method.

This way you can put those Cache configuration on one of those and you'll be sure that each response will have them.