Use a WebHook with this code:
``` c#
using System;
using System.Net;
using System.Threading.Tasks;
public static async Task
class Foo {}
```
If I pass the request body {} from our Functions test UI, it works fine. i.e. foo is not null.
But if I try to do the same thing from postman, passing the same body {} as application/json, then I end up with foo=null.
If It set the x-functions-key header to the master key in postman (to do the same as Function Portal, instead of using code query string), then it works! So I suspect some issue from the WebHook SDK auth messing up the state of the request.
I've been looking into this already. You can access the payload, but for some reason the POCO ReadAs doesn't work. This works for example (read JSON first then deserialize):
public static async Task<object> Run(HttpRequestMessage req, TraceWriter log)
{
string json = await req.Content.ReadAsStringAsync();
Payload payload = JsonConvert.DeserializeObject<Payload>(json);
return req.CreateResponse(HttpStatusCode.OK, $"Value: {payload.Value}");
}
So this isn't blocking - for short term you can use the above pattern until we find out why the other doesn't work.
Awesome to have a fix!
But I still don't understand the root cause. Why is it that ReadAsAsync<Foo>() is not working, but ReadAsStringAsync works fine? And that the issue only occurs when auth goes through WebHook library?
Yeah, I'd like to know the root cause too - to be sure it isn't something we're doing wrong. I think it only happens when going through the WebHook receiver pipeline because those libraries are also reading the content, so there are multiple readers.
It'd be interesting to try to reproduce this issue using the WebHook receiver libraries outside of functions, to truly find out if it's something we're doing wrong, or whether Henrik has a bug.
Also, I had Pizza for dinner. @paulbatum @fabiocav
The key difference between ReadAsAsync<T> and ReadAsStringAsync is that while the later reads from the buffer, while ReasAsAsync<T> will pass the underlying stream to the appropriate formatter (depending on the media/content type). In our case, the content stream is being consumed when going through the WebHooks pipeline, so when our DelegatingWebHookHandler is finally invoked and in turn, invokes the function, it passes an HTTP Request object with a content with a stream that has been read to the end, causing the call to ReadAsAsync<T> to pass a fully consumed stream down to the formatter, which causes the issue.
This fix resets the stream position so when that stream is read, it is read from the beginning and the formatter can successfully read the content (and in the test case, deserialize the type).
@mathewc we can't move to handle request as the WebHooks pipeline is engaged after that code executes, but we could move it to the DelegatingWebHookHandler if you prefer. I added the code to the delegate we pass in as it is immediately before the function invocation, but it would also make sense to have it in the handler.
It's worth following up with Henrik to see if this is something the WebHooks SDK should be handling.
I know this was a bit lengthy, so let me know if I was unclear.
@fabiocav thanks for the detailed explanation, which does help clarify.
Most helpful comment
Also, I had Pizza for dinner. @paulbatum @fabiocav