Create Webhook to tracking change of Asana Task

1.1k views Asked by At

Now I'm trying to set up a webhook in Asana to send me event updates for a particular task on my Asana Project. I am pretty novice so keep that in mind when reading and answering, thanks. This also my first post on here so be easy on me. Here's my code I am running.

WCF that received notify:

public string ReceiveHooks(Stream JSONdataStream)
{

    IncomingWebRequestContext request = WebOperationContext.Current.IncomingRequest;
    WebHeaderCollection headers = request.Headers;

    if (headers.AllKeys.Contains("X-Hook-Secret"))
    {
        var key = headers["X-Hook-Secret"];

        WebOperationContext.Current.OutgoingResponse.Headers.Add("X-Hook-Secret", key);
        WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.OK;

    }

    //Handle Json body

    using (var reader = new StreamReader(JSONdataStream))
    {
        List<AsanaEvent> listEvent = null;
        string values = reader.ReadToEnd();

        logger.Info("Asana receive hook successful: " + values);
        return "true";
    }

    return "False";
}

My Request to create Webhook:

var client = new RestClient("https://app.asana.com/api/1.0/webhooks");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddHeader("authorization", "Bearer 0/<key>");
request.AddParameter("application/x-www-form-urlencoded", "resource=234806314393357&target=https%3A%2F%2Fmywebservice.com%2FWCFService.svc%2FReceiveHooks", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

I can received HookId:

 {
"data": {
    "id": 235053304,
    "target": "https://myservice.com/WCFService.svc/ReceiveHooks",
    "active": true,
    "created_at": "2016-12-22T16:02:29.899Z",
    "last_failure_at": null,
    "last_failure_content": "",
    "last_success_at": null,
    "resource": {
      "id": 2349951,
      "name": "My Task Name"
    }
  }
}

But when I try to get webhook by Id I got error message:

"message": "webhook: Unknown object: 235053304"

Do anyone have any clue on this error message? I assume that the code to do handshake and handle received hook are in same place.?

Many Thanks

1

There are 1 answers

3
Matt On BEST ANSWER

I'm a developer advocate at Asana. This is strange; it appears to me that you're doing things correctly...

Just to be sure, because webhooks can be tricky, you're experiencing the handshake happening like this:

  • Req1 to Asana: POST to app.asana.com/api/1.0/webhooks; this blocks while
    • Req2 to Target: POST from Asana to your target
    • Res2 from Target: 200 OK with the same X-Hook-Secret header
  • Res1 from Asana: 200 OK with the data you listed above

and then you GET from app.asana.com/api/1.0/webhooks/{webhook-id}, and you get the error?

Everything but getting the error seems completely normal in that scenario. Are you able to see the webhook listed when you GET all webhooks at app.asana.com/api/1.0/webhooks? Did you try right away? Did you retry when you couldn't find the webhook?

(Sometimes webhooks can die, unfortunately, especially over time, for various reasons, and I'm trying to get a clear picture of what's going on - sorry for all the questions.)

Edit

I reached out in person through our [email protected] email. We keep a record of the content returned through the last attempt to get in touch; it seems to me in reading the return that the callback path isn't configured to accept the Content-Type: application/json header and payload when it tries to call back. What's curious is that the handshake works, because this should also be the case there: we send back json of {} in the handshake. Hopefully this may present an easy fix.

I hope that we keep making progress here - the handshake is supposed to let you know if you can catch the callback properly; the fact that it's not doing this is the most confusing aspect. Especially the "right after that" part of your comment when you try to GET the webhook - it seems like way too soon for the webhook to be trashed, unless the handshake should have failed. We'll keep investigating this on our side, and hopefully this is useful information from what we saw with the webhook for your end!

Final edit

I investigated further. There is a bug on our side if we receive an error on the first delivery attempt. The intent is to have an exponential retry backoff, but instead, we trash the webhook.

To be clear, this is where the bug happens:

  • Req1 to Asana: POST to app.asana.com/api/1.0/webhooks; this blocks while
    • Req2 to Target: POST from Asana to your target
    • Res2 from Target: 200 OK with the same X-Hook-Secret header
  • Res1 from Asana: 200 OK with the data you listed above

In other words, a successful handshake.

And then, some (possibly short) time later, when the resource changes, if this is the very first resource update callback for that webhook:

  • Req3 to Target: POST from Asana that the resource has changed
  • Res3 from Target: 4xx/5xx failure (anything other than 200)

At this point, the correct behavior is for Asana to retry with backoff. Instead we mistakenly trash the webhook.

We're working to correct this bug, because the behavior it creates is strange: the handshake works, then to test it developers tweak the resource; then the webhook disappears. On the receiving side, in the meantime, I encourage developers to check their logs to see if they have responded to any incoming Asana requests with a HTTP error code; this would verify the cause of the webhook being trashed.

Thanks for letting us know, and sorry about the strange observed behavior!