{"id":5921,"date":"2015-09-04T01:03:00","date_gmt":"2015-09-04T01:03:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/webdev\/2015\/09\/04\/introducing-microsoft-asp-net-webhooks-preview\/"},"modified":"2023-09-19T11:29:31","modified_gmt":"2023-09-19T18:29:31","slug":"introducing-microsoft-asp-net-webhooks-preview","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/introducing-microsoft-asp-net-webhooks-preview\/","title":{"rendered":"Introducing Microsoft ASP.NET WebHooks Preview"},"content":{"rendered":"<p>We are very pleased to announce ASP.NET WebHooks preview as a new addition to the ASP.NET family. <a href=\"http:\/\/en.wikipedia.org\/wiki\/Webhook\">WebHooks<\/a> is a lightweight HTTP pattern providing a simple pub\/sub model for wiring together Web APIs and SaaS services. When an event happens in a service, a notification is sent in the form of an HTTP POST request to registered subscribers. The POST request contains information about the event which makes it possible for the receiver to act accordingly.<\/p>\n<p>Because of their simplicity, WebHooks are already exposed by a large number of services including <a href=\"http:\/\/dropbox.com\">Dropbox<\/a>, <a href=\"http:\/\/www.github.com\">GitHub<\/a>, <a href=\"http:\/\/www.instagram.com\">Instagram<\/a>, <a href=\"http:\/\/www.mailchimp.com\">MailChimp<\/a>, <a href=\"http:\/\/www.paypal.com\">PayPal<\/a>, <a href=\"https:\/\/slack.com\/\">Slack<\/a>, <a href=\"http:\/\/www.trello.com\">Trello<\/a>, and many more. For example, a WebHook can indicate that a file has changed in Dropbox, or a code change has been committed in GitHub, or a payment has been initiated in PayPal, or a card has been created in Trello \u2013 the possibilities are endless!<\/p>\n<p>Microsoft ASP.NET WebHooks makes it easier to both send and receive WebHooks as part of your ASP.NET application:<\/p>\n<ul>\n<li>On the receiving side, it provides a common model for receiving and processing WebHooks from any number of WebHook providers. It comes out of the box with support for <a href=\"https:\/\/azure.microsoft.com\/en-us\/blog\/webhooks-for-azure-alerts\/\">Azure Alerts<\/a>, <a href=\"https:\/\/www.dropbox.com\/developers\/webhooks\/tutorial\">Dropbox<\/a>, <a href=\"https:\/\/developer.github.com\/webhooks\/\">GitHub<\/a>, <a href=\"https:\/\/github.com\/projectkudu\/kudu\/wiki\/Web-hooks\">Kudu<\/a>, <a href=\"https:\/\/instagram.com\/developer\/realtime\/\">Instagram<\/a>, <a href=\"https:\/\/apidocs.mailchimp.com\/webhooks\/\">MailChimp<\/a>, <a href=\"https:\/\/developer.paypal.com\/webapps\/developer\/docs\/integration\/direct\/rest-webhooks-overview\/\">PayPal<\/a>, <a href=\"https:\/\/pusher.com\/docs\/webhooks\">Pusher<\/a>, <a href=\"http:\/\/blogs.msdn.com\/b\/webdev\/archive\/2015\/09\/07\/integrating-with-salesforce-using-asp-net-webhooks-preview.aspx\">Salesforce<\/a>, <a href=\"https:\/\/api.slack.com\/outgoing-webhooks\">Slack<\/a>, <a href=\"https:\/\/stripe.com\/docs\/webhooks\">Stripe<\/a>, <a href=\"http:\/\/blog.trello.com\/webhooks-are-here\/\">Trello<\/a>, and <a href=\"https:\/\/en.support.wordpress.com\/webhooks\/\">WordPress<\/a> but it is easy to add support for more.<\/li>\n<li>On the sending side it provides support for managing and storing subscriptions as well as for sending event notifications to the right set of subscribers. This allows you to define your own set of events that subscribers can subscribe to and notify them when things happens.<\/li>\n<\/ul>\n<p>The two parts can be used together or apart depending on your scenario. If you only need to receive WebHooks from other services then you can use just the receiver part; if you only want to expose WebHooks for others to consume, then you can do just that.<\/p>\n<p>The WebHook code targets <a href=\"http:\/\/www.asp.net\/web-api\/overview\/getting-started-with-aspnet-web-api\/tutorial-your-first-web-api\">ASP.NET Web API 2<\/a> and <a href=\"http:\/\/www.asp.net\/mvc\">ASP.NET MVC 5<\/a>, is available as <a href=\"https:\/\/github.com\/aspnet\/WebHooks\">OSS on GitHub<\/a>, and as preview Nuget packages.<\/p>\n<p>We are also adding topics to the <a href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkId=690277\">Microsoft ASP.NET WebHooks online documentation<\/a> so please also check there for additional details as they become available.<\/p>\n<h3>WebHooks Overview<\/h3>\n<p>WebHooks is a pattern which means that it varies how it is used from service to service but the basic idea is the same. You can think of WebHooks as a simple pub\/sub model where a user can subscribe to events happening elsewhere. The event notifications are propagated as HTTP POST requests containing information about the event itself.<\/p>\n<p>Typically the HTTP POST request contains a JSON object or HTML form data determined by the WebHook sender including information about the event causing the WebHook to trigger. For example, an example of a WebHook POST request body from <a href=\"https:\/\/developer.github.com\/webhooks\/\">GitHub<\/a> looks like this as a result of a new issue being opened in a particular repository:<\/p>\n<div id=\"codeSnippetWrapper\">\n<div id=\"codeSnippet\">\n<pre><span id=\"lnum1\" style=\"color: #606060;\"> 1:<\/span> {<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum2\" style=\"color: #606060;\"> 2:<\/span>   <span style=\"color: #006080;\">\"action\"<\/span>: <span style=\"color: #006080;\">\"opened\"<\/span>,<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum3\" style=\"color: #606060;\"> 3:<\/span>   <span style=\"color: #006080;\">\"issue\"<\/span>: {<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum4\" style=\"color: #606060;\"> 4:<\/span>     <span style=\"color: #006080;\">\"url\"<\/span>: <span style=\"color: #006080;\">\"https:\/\/api.github.com\/repos\/octocat\/Hello-World\/issues\/1347\"<\/span>,<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum5\" style=\"color: #606060;\"> 5:<\/span>     <span style=\"color: #006080;\">\"number\"<\/span>: 1347,<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum6\" style=\"color: #606060;\"> 6:<\/span>     ...<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum7\" style=\"color: #606060;\"> 7:<\/span>   },<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum8\" style=\"color: #606060;\"> 8:<\/span>   <span style=\"color: #006080;\">\"repository\"<\/span> : {<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum9\" style=\"color: #606060;\"> 9:<\/span>     <span style=\"color: #006080;\">\"id\"<\/span>: 1296269,<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum10\" style=\"color: #606060;\"> 10:<\/span>     <span style=\"color: #006080;\">\"full_name\"<\/span>: <span style=\"color: #006080;\">\"octocat\/Hello-World\"<\/span>,<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum11\" style=\"color: #606060;\"> 11:<\/span>     <span style=\"color: #006080;\">\"owner\"<\/span>: {<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum12\" style=\"color: #606060;\"> 12:<\/span>       <span style=\"color: #006080;\">\"login\"<\/span>: <span style=\"color: #006080;\">\"octocat\"<\/span>,<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum13\" style=\"color: #606060;\"> 13:<\/span>       <span style=\"color: #006080;\">\"id\"<\/span>: 1,<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum14\" style=\"color: #606060;\"> 14:<\/span>       ...<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum15\" style=\"color: #606060;\"> 15:<\/span>     },<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum16\" style=\"color: #606060;\"> 16:<\/span>     ...<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum17\" style=\"color: #606060;\"> 17:<\/span>   },<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum18\" style=\"color: #606060;\"> 18:<\/span>   <span style=\"color: #006080;\">\"sender\"<\/span>: {<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum19\" style=\"color: #606060;\"> 19:<\/span>     <span style=\"color: #006080;\">\"login\"<\/span>: <span style=\"color: #006080;\">\"octocat\"<\/span>,<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum20\" style=\"color: #606060;\"> 20:<\/span>     <span style=\"color: #006080;\">\"id\"<\/span>: 1,<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum21\" style=\"color: #606060;\"> 21:<\/span>     ...<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum22\" style=\"color: #606060;\"> 22:<\/span>   }<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum23\" style=\"color: #606060;\"> 23:<\/span> }<\/pre>\n<p><!--CRLF--><\/p>\n<\/div>\n<\/div>\n<p>To ensure that the WebHook is indeed from the intended sender, the POST request is secured in some way and then verified by the receiver. For example, GitHub includes an \u2018X-Hub-Signature\u2019 HTTP header with a hash of the request body which is checked by the receiver implementation so you don\u2019t have to worry about it.<\/p>\n<p>The WebHook flow generally goes something like this:<\/p>\n<ol>\n<li>The WebHook sender exposes events that a client can subscribe to. The events describe observable changes to the system, for example that a new data item has been inserted, that a process has completed, or something else.<\/li>\n<li>The WebHook receiver subscribes by registering a WebHook consisting of four things:\n<ul>\n<li>A URI for where the event notification should be posted in the form of an HTTP POST request;<\/li>\n<li>A set of filters describing the particular events for which the WebHook should be fired;<\/li>\n<li>A secret key which is used to sign the HTTP POST request;<\/li>\n<li>Additional data which is to be included in the HTTP POST request. This can for example be additional HTTP header fields or properties included in the HTTP POST request body<\/li>\n<\/ul>\n<\/li>\n<li>Once an event happens, the matching WebHook registrations are found and HTTP POST requests are submitted. Typically, the generation of the HTTP POST requests are retried several times if for some reason the recipient is not responding or the HTTP POST request results in an error response.<\/li>\n<\/ol>\n<p>As mentioned, Microsoft ASP.NET WebHooks support both sending and receiving WebHooks but in this blog we will focus on the receiving side. In the blog <a href=\"http:\/\/blogs.msdn.com\/b\/webdev\/archive\/2015\/09\/15\/sending-webhooks-with-asp-net-webhooks-preview.aspx\">Sending WebHooks with ASP.NET WebHooks Preview<\/a> we dive into the details of sending WebHooks.<\/p>\n<h3>Receiving WebHooks<\/h3>\n<p>Dealing with WebHooks depends on who the sender is. Sometimes there are additional steps registering a WebHook verifying that the subscriber is really listening. Some WebHooks provide a push-to-pull model where the HTTP POST request only contains a reference to the event information which is then to be retrieved independently. Often the security model varies quite a bit.<\/p>\n<p>The purpose of Microsoft ASP.NET WebHooks is to make it both simpler and more consistent to wire up your API without spending a lot of time figuring out how to handle any particular variant of WebHooks.<\/p>\n<p>To enable ASP.NET WebHooks, you first install the Nuget package for the WebHook provider or providers you want to receive WebHooks from. The Nuget packages are named <strong><a href=\"https:\/\/www.nuget.org\/packages?q=Microsoft.AspNet.WebHooks.Receivers\">Microsoft.AspNet.WebHooks.Receivers.*<\/a><\/strong> where the last part indicates the service supported. For example <strong><a href=\"https:\/\/www.nuget.org\/packages?q=Microsoft.AspNet.WebHooks.Receivers.GitHub\">Microsoft.AspNet.WebHooks.Receivers.GitHub<\/a><\/strong> provides support for receiving <a href=\"https:\/\/developer.github.com\/webhooks\/\">WebHooks from GitHub<\/a> and <strong><a href=\"https:\/\/www.nuget.org\/packages?q=Microsoft.AspNet.WebHooks.Receivers.Custom\">Microsoft.AspNet.WebHooks.Receivers.Custom<\/a><\/strong> provides support for receiving WebHooks generated by ASP.NET WebHooks.<\/p>\n<p>Out of the box you can find support for <a href=\"https:\/\/www.dropbox.com\/developers\/webhooks\/tutorial\">Dropbox<\/a>, <a href=\"https:\/\/developer.github.com\/webhooks\/\">GitHub<\/a>, <a href=\"https:\/\/apidocs.mailchimp.com\/webhooks\/\">MailChimp<\/a>, <a href=\"https:\/\/developer.paypal.com\/webapps\/developer\/docs\/integration\/direct\/rest-webhooks-overview\/\">PayPal<\/a>, <a href=\"https:\/\/pusher.com\/docs\/webhooks\">Pusher<\/a>, <a href=\"https:\/\/api.slack.com\/outgoing-webhooks\">Slack<\/a>, <a href=\"https:\/\/stripe.com\/docs\/webhooks\">Stripe<\/a>, <a href=\"http:\/\/blog.trello.com\/webhooks-are-here\/\">Trello<\/a>, and <a href=\"https:\/\/en.support.wordpress.com\/webhooks\/\">WordPress<\/a> but it is possible to support any number of other providers. Here we will show how to receive WebHooks from GitHub \u2013 in follow up blogs we will describe in detail how to do it for other service and explain how you can extend the list yourself. See also these blogs:<\/p>\n<ul>\n<li><a href=\"http:\/\/blogs.msdn.com\/b\/webdev\/archive\/2015\/09\/06\/receiving-slack-webhooks-with-asp-net-webhooks.aspx\">Integrating with Slack Using ASP.NET WebHooks Preview<\/a><\/li>\n<li><a href=\"http:\/\/blogs.msdn.com\/b\/webdev\/archive\/2015\/09\/07\/integrating-with-salesforce-using-asp-net-webhooks-preview.aspx\">Integrating with Salesforce using ASP.NET WebHooks Preview<\/a><\/li>\n<li><a href=\"http:\/\/blogs.msdn.com\/b\/webdev\/archive\/2015\/09\/21\/integrating-with-instagram-using-asp-net-webhooks-preview.aspx\">Integrating with Instagram using ASP.NET WebHooks Preview<\/a><\/li>\n<li><a href=\"http:\/\/blogs.msdn.com\/b\/webdev\/archive\/2015\/10\/04\/receive-webhooks-from-azure-alerts-and-kudu-azure-web-app-deployment.aspx\">Receive WebHooks from Azure Alerts and Kudu (Azure Web App Deployment)<\/a><\/li>\n<li><a href=\"http:\/\/blogs.msdn.com\/b\/webdev\/archive\/2015\/11\/21\/using-asp-net-webhooks-with-ifttt-and-zapier-to-monitor-twitter-and-google-sheets.aspx\">Using ASP.NET WebHooks with IFTTT and Zapier to Monitor Twitter and Google Sheets<\/a><\/li>\n<\/ul>\n<h3>WebHook Configuration<\/h3>\n<p>Once you have the preview Nuget for the WebHook sender you want to receive WebHooks from, you need to configure it. This typically requires two parts:<\/p>\n<ol>\n<li>Configuring the WebHook sender,<\/li>\n<li>Configuring the receiver with security settings.<\/li>\n<\/ol>\n<p>Configuration of the WebHook sender differs somewhat from service to service. Here we show how it works for GitHub but many other services provide a corresponding experience.<\/p>\n<p>By installing Microsoft ASP.NET WebHooks you get a WebHook controller which accepts WebHook requests from an open-ended number of services. When a request arrives, it picks the appropriate receiver that you have installed for handling a particular WebHook sender. The URI of this controller is the WebHook URI that you register with the service and is of the form:<\/p>\n<ul>\n<li>https:\/\/&lt;host&gt;\/api\/webhooks\/incoming\/&lt;receiver&gt;<\/li>\n<\/ul>\n<p>For GitHub, the receiver name is <strong>github<\/strong>. For security reasons, many WebHook providers require that the the URI is an \u2018https\u2019 URI. Further, the URI has to be publically available so that Slack service can reach it. The easiest way of doing this is to deploy your ASP.NET application as an Azure Web App which you can do directly from Visual Studio.<\/p>\n<p>To register the WebHook with GitHub, you obviously need a GitHub account. Then go to GitHub, pick a repository that you own, and select <strong>settings<\/strong>:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/16\/2018\/10\/0160.GitHubRepo_0B276A89.png\"><img decoding=\"async\" style=\"float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; padding-right: 0px; margin-right: auto; border-width: 0px;\" title=\"GitHubRepo\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2015\/09\/1663.GitHubRepo_thumb_188D7D8F.png\" alt=\"GitHubRepo\" width=\"600\" height=\"470\" border=\"0\" \/><\/a><\/p>\n<p>Under settings select <strong>WebHooks and Services<\/strong> and fill in the data in the red boxes (substituting the URI with yours):<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2015\/09\/1033.GitHubWebHooksCreate_thumb_73FBF00A.png\"><img decoding=\"async\" style=\"float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; padding-right: 0px; margin-right: auto; border-width: 0px;\" title=\"GitHubWebHooksCreate\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2015\/09\/1033.GitHubWebHooksCreate_thumb_73FBF00A.png\" alt=\"GitHubWebHooksCreate\" width=\"600\" height=\"470\" border=\"0\" \/><\/a><\/p>\n<p>As secret, you should pick a value that has a high entropy. A good idea is to pick something like a SHA256 hash which you for example can get from <a href=\"http:\/\/www.freeformatter.com\/hmac-generator.html\">FreeFormatter Online Tools For Developers<\/a>. Once you hit <strong>Add WebHook<\/strong>, GitHub sends a test event notification to check that the URI is correct. However, as we haven\u2019t configured the receiver yet, this will show an error under<strong> Recent Deliveries<\/strong>.<\/p>\n<p>Before going further, let\u2019s therefore configure the receiver back in your Web Application. The first part of the configuration is done in <strong>WebApiConfig.cs<\/strong> where you add line 21 like this:<\/p>\n<div id=\"codeSnippetWrapper\">\n<div id=\"codeSnippet\">\n<pre><span id=\"lnum1\" style=\"color: #606060;\"> 1:<\/span> <span style=\"color: #0000ff;\">using<\/span> System.Web.Http;<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum2\" style=\"color: #606060;\"> 2:<\/span><\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum3\" style=\"color: #606060;\"> 3:<\/span> <span style=\"color: #0000ff;\">namespace<\/span> WebHookReceivers<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum4\" style=\"color: #606060;\"> 4:<\/span> {<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum5\" style=\"color: #606060;\"> 5:<\/span>     <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">static<\/span> <span style=\"color: #0000ff;\">class<\/span> WebApiConfig<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum6\" style=\"color: #606060;\"> 6:<\/span>     {<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum7\" style=\"color: #606060;\"> 7:<\/span>         <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">static<\/span> <span style=\"color: #0000ff;\">void<\/span> Register(HttpConfiguration config)<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum8\" style=\"color: #606060;\"> 8:<\/span>         {<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum9\" style=\"color: #606060;\"> 9:<\/span>             <span style=\"color: #008000;\">\/\/ Web API configuration and services<\/span><\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum10\" style=\"color: #606060;\"> 10:<\/span><\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum11\" style=\"color: #606060;\"> 11:<\/span>             <span style=\"color: #008000;\">\/\/ Web API routes<\/span><\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum12\" style=\"color: #606060;\"> 12:<\/span>             config.MapHttpAttributeRoutes();<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum13\" style=\"color: #606060;\"> 13:<\/span><\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum14\" style=\"color: #606060;\"> 14:<\/span>             config.Routes.MapHttpRoute(<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum15\" style=\"color: #606060;\"> 15:<\/span>                 name: <span style=\"color: #006080;\">\"DefaultApi\"<\/span>,<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum16\" style=\"color: #606060;\"> 16:<\/span>                 routeTemplate: <span style=\"color: #006080;\">\"api\/{controller}\/{id}\"<\/span>,<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum17\" style=\"color: #606060;\"> 17:<\/span>                 defaults: <span style=\"color: #0000ff;\">new<\/span> { id = RouteParameter.Optional }<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum18\" style=\"color: #606060;\"> 18:<\/span>             );<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum19\" style=\"color: #606060;\"> 19:<\/span><\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum20\" style=\"color: #606060;\"> 20:<\/span>             <span style=\"color: #008000;\">\/\/ Load GitHub receiver<\/span><\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum21\" style=\"color: #606060;\"> 21:<\/span>             config.InitializeReceiveGitHubWebHooks();<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum22\" style=\"color: #606060;\"> 22:<\/span>         }<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum23\" style=\"color: #606060;\"> 23:<\/span>     }<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum24\" style=\"color: #606060;\"> 24:<\/span> }<\/pre>\n<p><!--CRLF--><\/p>\n<\/div>\n<\/div>\n<p>The second part is to set the secret token so that it can be verified by the receiver. This is done by setting the <strong>MS_WebHookReceiverSecret_GitHub<\/strong> app setting for your Web Application to the value of the secret from before. This can either be done directly in the Web.Config file or better yet, configured through the <a href=\"http:\/\/portal.azure.com\/\">Azure portal<\/a>:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2015\/09\/1220.AzureAppSettings_thumb_41863F8B.png\"><img decoding=\"async\" style=\"float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; padding-right: 0px; margin-right: auto; border-width: 0px;\" title=\"AzureAppSettings\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2015\/09\/1220.AzureAppSettings_thumb_41863F8B.png\" alt=\"AzureAppSettings\" width=\"600\" height=\"322\" border=\"0\" \/><\/a><\/p>\n<p>With the receiver configured, you should be able to go back to the WebHooks page on GitHub, hit <strong>Redeliver<\/strong> and see a 200 OK response:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2015\/09\/7840.GitHubWebHookConfirm_thumb_47DEF319.png\"><img decoding=\"async\" style=\"float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; padding-right: 0px; margin-right: auto; border-width: 0px;\" title=\"GitHubWebHookConfirm\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2015\/09\/7840.GitHubWebHookConfirm_thumb_47DEF319.png\" alt=\"GitHubWebHookConfirm\" width=\"600\" height=\"470\" border=\"0\" \/><\/a><\/p>\n<h3>WebHook Processing<\/h3>\n<p>You are now ready to receive WebHooks from GitHub and process them however you want. To do this, once the receiver is done processing the WebHook, it calls one or more handlers which is where your code runs processing the actual event notification.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2015\/09\/3051.WebHookReceivers_thumb_234D6595.png\"><img decoding=\"async\" style=\"float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; padding-right: 0px; margin-right: auto; border-width: 0px;\" title=\"WebHookReceivers\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2015\/09\/3051.WebHookReceivers_thumb_234D6595.png\" alt=\"WebHookReceivers\" width=\"600\" height=\"282\" border=\"0\" \/><\/a><\/p>\n<p>Here is a sample handler illustrating the basic model. No registration is necessary \u2013 it will automatically get picked up and called:<\/p>\n<div id=\"codeSnippetWrapper\">\n<div id=\"codeSnippet\">\n<pre><span id=\"lnum1\" style=\"color: #606060;\"> 1:<\/span> <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">class<\/span> MyHandler : WebHookHandler<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum2\" style=\"color: #606060;\"> 2:<\/span> {<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum3\" style=\"color: #606060;\"> 3:<\/span>     <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">override<\/span> Task ExecuteAsync(<span style=\"color: #0000ff;\">string<\/span> receiver, WebHookHandlerContext context)<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum4\" style=\"color: #606060;\"> 4:<\/span>     {<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum5\" style=\"color: #606060;\"> 5:<\/span>         <span style=\"color: #008000;\">\/\/ Here you can process the WebHook data<\/span><\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum6\" style=\"color: #606060;\"> 6:<\/span><\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum7\" style=\"color: #606060;\"> 7:<\/span>         <span style=\"color: #0000ff;\">return<\/span> Task.FromResult(<span style=\"color: #0000ff;\">true<\/span>);<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum8\" style=\"color: #606060;\"> 8:<\/span>     }<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum9\" style=\"color: #606060;\"> 9:<\/span> }<\/pre>\n<p><!--CRLF--><\/p>\n<\/div>\n<\/div>\n<p>In the case of GitHub, a handler could look like this:<\/p>\n<div id=\"codeSnippetWrapper\">\n<div id=\"codeSnippet\">\n<pre><span id=\"lnum1\" style=\"color: #606060;\"> 1:<\/span> <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">class<\/span> GitHubHandler : WebHookHandler<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum2\" style=\"color: #606060;\"> 2:<\/span> {<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum3\" style=\"color: #606060;\"> 3:<\/span>     <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">override<\/span> Task ExecuteAsync(<span style=\"color: #0000ff;\">string<\/span> receiver, WebHookHandlerContext context)<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum4\" style=\"color: #606060;\"> 4:<\/span>     {<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum5\" style=\"color: #606060;\"> 5:<\/span>         <span style=\"color: #0000ff;\">string<\/span> action = context.Actions.First();<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum6\" style=\"color: #606060;\"> 6:<\/span>         JObject data = context.GetDataOrDefault&lt;JObject&gt;();<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum7\" style=\"color: #606060;\"> 7:<\/span><\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum8\" style=\"color: #606060;\"> 8:<\/span>         <span style=\"color: #0000ff;\">return<\/span> Task.FromResult(<span style=\"color: #0000ff;\">true<\/span>);<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum9\" style=\"color: #606060;\"> 9:<\/span>     }<\/pre>\n<p><!--CRLF--><\/p>\n<pre><span id=\"lnum10\" style=\"color: #606060;\"> 10:<\/span> }<\/pre>\n<p><!--CRLF--><\/p>\n<\/div>\n<\/div>\n<p>The Actions property contains the name of the event and Data contains the actual notification which can either be operated on directly as a JObject instance or cast to an actual type if desired.<\/p>\n<h3>Trying it Out<\/h3>\n<p>Once deployed, we are now ready to try this out end-to-end: In the GitHub repository, we add a new issue like this:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/16\/2018\/10\/7103.GitHubNewIssue_63174C1A.png\"><img decoding=\"async\" style=\"float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; padding-right: 0px; margin-right: auto; border-width: 0px;\" title=\"GitHubNewIssue\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2015\/09\/6521.GitHubNewIssue_thumb_7EBBD810.png\" alt=\"GitHubNewIssue\" width=\"600\" height=\"470\" border=\"0\" \/><\/a><\/p>\n<p>And if we attach a debugger to the receiver then we will see the following:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/16\/2018\/10\/0358.GitHubWebHook_7E4FA51B.png\"><img decoding=\"async\" style=\"float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; padding-right: 0px; margin-right: auto; border-width: 0px;\" title=\"GitHubWebHook\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2015\/09\/1447.GitHubWebHook_thumb_3A0F3DCF.png\" alt=\"GitHubWebHook\" width=\"600\" height=\"162\" border=\"0\" \/><\/a><\/p>\n<p>This should give a quick overview of what ASP.NET WebHooks can do for you. In follow-up blogs we will dive into the the receivers as well as how to build your own as well as of course sending WebHook yourself.<\/p>\n<p>Your input is greatly appreciated so please send it my way. You can use my <a href=\"https:\/\/twitter.com\/frystyk\">@frystyk<\/a> twitter handle or email me at <a href=\"mailto:henrikn@microsoft.com\">henrikn@microsoft.com<\/a>.<\/p>\n<p>Have fun!<\/p>\n<p>Henrik<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We are very pleased to announce ASP.NET WebHooks preview as a new addition to the ASP.NET family. WebHooks is a lightweight HTTP pattern providing a simple pub\/sub model for wiring together Web APIs and SaaS services. When an event happens in a service, a notification is sent in the form of an HTTP POST request [&hellip;]<\/p>\n","protected":false},"author":403,"featured_media":58792,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[197],"tags":[7265,7333,34,7505,7506],"class_list":["post-5921","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aspnet","tag-announcements","tag-asp-net-mvc","tag-asp-net-web-api","tag-asp-net-webhooks","tag-webhooks"],"acf":[],"blog_post_summary":"<p>We are very pleased to announce ASP.NET WebHooks preview as a new addition to the ASP.NET family. WebHooks is a lightweight HTTP pattern providing a simple pub\/sub model for wiring together Web APIs and SaaS services. When an event happens in a service, a notification is sent in the form of an HTTP POST request [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/5921","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/403"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=5921"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/5921\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=5921"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=5921"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=5921"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}