Click here to Skip to main content
15,879,474 members
Articles / Web Development / ASP.NET / ASP.NETvNext

Implementing custom WebHook using persistent storage

Rate me:
Please Sign up or sign in to vote.
3.90/5 (6 votes)
22 Nov 2015CPOL3 min read 14.9K   4   1
This article mainly explains about how you can write custom webhook using persistent storage, how they can be created and also a sample source code on custom webhook. The purpose of this article is just to give an idea on writing your own custom web hook.

Introduction

Before going into custom WebHook let me give you a small description on web hook, the pattern behind it and why are they used for? A WebHook can be simply explained as an HTTP callback mechanism which provides a simple publisher / subscriber model for wiring up two or more services which may live on different location.When an event happens in a service, a notification is sent in the form of an HTTP POST request to the registered subscribers. The POST request contains information about the event which makes it possible for the receiver to act accordingly.

WebHook uses a publish–subscribe messaging pattern where the senders of messages are called publishers and the receivers are called subscribers.

The main advantage of the webhooks pattern is that your application doesn’t have to make periodic calls to APIs.
Instead, APIs will call your application on a specific endpoint informing that something interesting has happened.
Now, i guess you may got some idea on webhooks and how they are working behind the scene.

Implementing Custom WebHook

Recently we got a chance to implement webhook in one of our project. The situation in the project demands us to implement custom webhook in our current code base which is in ASP.NET MVC 5.0.Thanks to Microsoft.AspNet.WebHooks.Custom.dll which makes my work very easier. Microsoft.AspNet.WebHooks.Custom.dll uses the class MemoryWebHookStore which stores the webhook information in-memory. The class MemoryWebHookStore make use of a thread safe collection ConcurrentDictionary to store the webhook details. Storing the webhook details in-memory was pretty fine as long as the application was in a demo server. However in the  real production environment we need to store webhook details in a persistent storage and we dont have a choice to use Azure table since the application is going to be deployed on a different server. So we have to achieve this task some how. Now at the time of writing this article, we have a new web hook update on storing data in a SQL server, Microsoft.AspNet.WebHooks.Custom.SqlStorage dll is now avaialable for download which stores the WebHook details in a SQL server. But at the time of our implementation, Microsoft.AspNet.WebHooks.Custom.SqlStorage.dll was not yet released and we have write our own mechanism to store the WebHook in a persistent storage.

Let me explain how we have achieved this. Basically WebHook subscriptions are managed through an interface called IWebHookStore which provide an abstraction for querying, inserting, updating, and deleting subscriptions.
The default IWebHookStore implementation is in-memory-only. The idea here is to write a class which implements the IWebHookStore interface and pass the dependency to WebHookManager.

Sample code implementation

We created a Persistent storage class like below and passed its instane to WebHookManager.

C#
IWebHookStore _whStore = new PersistentWebHookStore();
IWebHookManager _whManager = new WebHookManager(_whStore, new TraceLogger());

Lets write a PersistentWebHookStore class and implement the IWebHookStore interface available in Microsoft.AspNet.WebHooks

C#
    namespace Microsoft.AspNet.WebHooks
    {
        public interface IWebHookStore
        {
            Task DeleteAllWebHooksAsync(string user);
            Task<storeresult> DeleteWebHookAsync(string user, string id);
            Task<icollection<webhook>> GetAllWebHooksAsync(string user);
            Task<storeresult> InsertWebHookAsync(string user, WebHook webHook);
            Task<webhook> LookupWebHookAsync(string user, string id);
            Task<icollection<webhook>> QueryWebHooksAsync(string user, IEnumerable<string> actions);
            Task<storeresult> UpdateWebHookAsync(string user, WebHook webHook);
        }
    }
</storeresult></string></icollection<webhook></webhook></storeresult></icollection<webhook></storeresult>
C#
    public class PersistentWebHookStore : IWebHookStore
    {
        #region Member Variables

        private readonly IWebHookRepository _webHookRepository = null;

        #endregion

        #region Constructor

        public PersistentWebHookStore()
        {
            _webHookRepository = new WebHookRepository();
        }

        #endregion

        #region IWebHookStore Methods
        
        //Register or in other words inserts a new web hook for a user.
        public Task<StoreResult> InsertWebHookAsync(string user, WebHook webHook)
        {
            if (!string.IsNullOrWhiteSpace(user) && webHook != null)
            {
                // Do the insert logic as you wish, here i am using a WebHook Repository 
                // to insert the details to SQL Server.The web hook repository uses  
                // EntityFrameWork to insert the web hook details to DB.
                user = Normalize(user);                
                bool isInserted = _webHookRepository.Insert(user, webHook);
                StoreResult result = isInserted ? StoreResult.Success : StoreResult.Conflict;
                return Task.FromResult(result);
            }
            else
            {
                throw new Exception("Values expected for either user or webHook");
            }
        }

        public Task<StoreResult> UpdateWebHookAsync(string user, WebHook webHook)
        {
            bool isUpdated = false;

            // Do the web hook update logic here.

            StoreResult result = isUpdated ? StoreResult.Success : StoreResult.Conflict;
            return Task.FromResult(result);
        }

        public Task<StoreResult> DeleteWebHookAsync(string user, string id)
        {
            bool isDeleted = false;

            // Do the web hook delete logic here.

            StoreResult result = isDeleted ? StoreResult.Success : StoreResult.Conflict;
            return Task.FromResult(result);
        }

        public Task<ICollection<WebHook>> GetAllWebHooksAsync(string user)
        {
            ICollection<webhook> result = null;

            // Do the logic to get all web hooks against a user.

            return Task.FromResult(result);
        }
        
        ...
        ...

        #endregion
    }
</webhook>

that's all!. From this ariticle i just want to explain how i have implemented custom WebHook using persistent storage, few months before the release of  Microsoft.AspNet.WebHooks.Custom.SqlStorage class which excatly does the same thing.

Reference

http://blogs.msdn.com/b/webdev/archive/2015/09/04/introducing-microsoft-asp-net-webhooks-preview.aspx

http://blogs.msdn.com/b/webdev/archive/2015/09/15/sending-webhooks-with-asp-net-webhooks-preview.aspx

http://blogs.msdn.com/b/webdev/archive/2015/11/07/updates-to-microsoft-asp-net-webhooks-preview.aspx

https://www.nuget.org/packages/Microsoft.AspNet.WebHooks.Custom.SqlStorage

https://en.wikipedia.org/wiki/Webhook

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralSample Code Required Pin
Member 133093122-May-19 3:15
Member 133093122-May-19 3:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.