简体   繁体   中英

How do I receive a custom webhook in an IIS hosted website?

Here is what I have done:

1 - I have installed the nuget package: Microsoft.AspNet.WebHooks.Receivers.Custom 1.2.0-beta

2 - I configured the WebApiConfig to receive custom webhooks:

    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        config.InitializeReceiveCustomWebHooks(); //<<<---
    }

3 - I set up a secret key in the web.config:

  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    ...
    <add key="MS_WebHookReceiverSecret_GenericJson" value="z=SECRET"/> 
  </appSettings>

4 - I have written a basic receiver (with the genericjson hook capture)

public class GenericJsonWebHookHandler : WebHookHandler
{
    public static string dataReceived;
    public GenericJsonWebHookHandler()
    {
        this.Receiver = "genericjson";
    }

    public override Task ExecuteAsync(string generator, WebHookHandlerContext context)
    {
        // Get JSON from WebHook
        JObject data = context.GetDataOrDefault<JObject>();

        if (context.Id == "i")
        {
            // do stuff
        }
        else if (context.Id == "z")
        {
            // do more stuff
            dataReceived = data.ToString();

            File.Create(@"c:\test\test1.txt");
        }

        return Task.FromResult(true);
    }
}

Now, one would expect with the steps above, if a webhook sender is set up to publish Json to the IIS hosted site, it should capture the notification as Json, assign the captured data to dataReceived and write a blank text file to c:\\test\\test.txt - which was not the case

Currently, I am testing this using Team Foundation Server to send a webhook test to https://mywebbhooksite.com:5050/?z=SECRET , and It succeeds - however, when I check if that little test file has been created, it's not there. I also have some javascript running on the homepage to poll for any changes to dataReceived but I see nothing is happening.

Mentioning here: I have a remote debugger attached to the w3wp.exe process, the breakpoint on ExecuteAsync and GenericJsonWebHookHandler does not get hit

Are there any other specific setup that needs to be done in order for the webhook to be captured?

I took a filthy approach which works

I ditched GenericJsonWebHookHandler and instead I have utilized the Application_BeginRequest() event in WebApiApplication instead to intercept data posted by the sender Webhook. The body of the hook resides in the HttpRequest.Request.Inputstream , which can be opened using a streamreader. The contents can be read onto a string and parsed into a JObject (if the body of the request sent by the webhook Request is JSon)

Here is my code.

    protected void Application_BeginRequest()
    {
        if (!Request.HttpMethod.Equals("post", StringComparison.InvariantCultureIgnoreCase)) {
            return; 
        }

        string documentContents;
        using (var receiveStream = Request.InputStream)
        {
            using (var readStream = new StreamReader(receiveStream, Encoding.UTF8))
            {
                documentContents = readStream.ReadToEnd();
            }
        }

        try
        {
            var json = JObject.Parse(documentContents);
            File.WriteAllLines(@"C:\test\keys.txt", new[] { documentContents, "\r\n", json.ToString() });
        }
        catch (Exception)
        {
             // do something
        }
    }

The test:

I went onto my webhook and commenced a webhook test. It published the request with the json. HTTP 200 was the response from the server.

Breakpoint was hit. The HttpMethod picked up the post. The Request's InputStream was read and stored in documentContents . JObject.Parse fired off and put the contents of the post into a JObject variable called json

The contents of json was written to a file stored on the server - indicating that the request was properly received.

What I plan to do to improve this, for security

For security purposes, I will encrypt the secret key I set in the web.config, and set the encrypted key in the web.config instead, and after that match it with the incoming URL Query parameters (using the same encryption algorithm) to see if that key is present and exactly the same

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM