Creating a Web Hook listener using ASP.NET

Posted : Wednesday, 20 January 2010 22:34:08

Below is my account of the technique I used to first analyze a set of request data containing a Web Hook and then process and act upon that data. If you're only interested in the processing of the data skip ahead to about halfway down where I detail the ProcessWebHook ActionResult method or click here.

I recently came across an excellent online source-code hosting product called Beanstalk - this is based on the open source subversion file tracking system that has been around for a while. There is a rich integration API made available by the BeanStalk guys and a few weeks ago I had cause to make use of it. I am currently building an MVC.NET application working remotely with a Mac using designer (aren't they all?). When I perform site upgrades I use a websetup project which copies all the files included in the solution to the development machine. If the designer adds any files to the subversion repository, they will get copied on to my machine when I update but crucially they will not be deployed to the webserver unless I include them in the solution.

Beanstalk provides a number of integration points that enable users to add certain functionality to various points in the project lifecycle. One such integration point is a Web Hook which, once correctly configured, will post a json formatted string to a user-supplied url every time a changeset is committed to the repository. The data sent contains details about the changeset including details of any added or modified files. The purpose of this post is to outline the process I used to receive this Web Hook, parse the data, and then act on it accordingly - in this case email me with a list of any added files so I could make sure to manually add the files to the Visual Studio solution.

On the Beanstalk site the Web Hook instructions state that a single post parameter called "commit" containing the json string. In order to set up the Web Hook, you need to provide a Url to which this information will be posted. Unfortunately I dont have a publically accessible webserver so I couldn't just point the Web Hook to my local machine, stick a breakpoint in the code and then commit a file change. I therefore decided on the following approach. I would configure the Web Hook to post to one of my hosting accounts and then record all of the data included in the request such that I could replay exactly the same request data during development.

In visual studio I created a new project from the MVC Application template and then deleted most of the files created by default. Given that there is no real publically viewable interface for this project I decided that getting rid of the master page would speed up the initial project construction. During development a simple interface was required to give me feedback but because the ultimate aim of this project was to create a web method to receive posted data, these pages required only minimal attention to page layout. The resultant project looked as follows:

default MVC projct strucuture with unnessary files removed

I built this project with testability in mind and although I'm not including any tests here, I may post in the future detailing how to write an accompanying unit test project. So with testing in mind, as well as to follow good practice, I have implemented component interaction using interfaces and will use the open source StructureMap project to resolve the dependencies (more on this later). The first interface I called IRequestLogger and it consisted of a single method:

    9     public interface IRequestLogger

   10     {

   11         void CaptureRequestData(HttpRequestBase request);

   12     }

Incidentally I created a subfolder of the Models directory called "Interfaces" and placed the file containing the interface definition into this folder. With the interface definition in place I added an instance of IRequestLogger as a private class-level variable to the HomeController class and then altered the default Index method of this controller as follows:

   36         public ActionResult Index()

   37         {

   38             //capture request data

   39             _RequestLogger.CaptureRequestData(Request);


   41             //message will be displayed to user

   42             ViewData["Message"] = "default page - request logged";


   44             //return basic view template

   45             return View();

   46         }

This is a pretty straighforward method. First it passes the current Request property (an instance of HttpRequestBase provided by the controller base class) to the current IRequestLogger.CaptureRequestData method. Next a small feedback message is added to to the ViewData collection and finally an instance of ViewResult is returned from the method. By default MVC will look for a page template with the same name as the current method, as mentioned above I deleted all the view templates that Visual Studio creates by default (including all shared views) so had to (re)create the Index.aspx view template to accompany this method. I did this by right-clicking within the method above and selecting "Add View" from the context menu. NB Given that I deleted the master page I needed to make sure I unchecked the "select a master page" option when creating any ne

  • (This will not appear on the site)