I'm trying to extract some data out of a request in the new Asp.Net Web Api. I have a handler setup like this:
public class MyTestHandler : DelegatingHandler
{
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (request.Content.IsFormData())
{
request.Content.ReadAsStreamAsync().ContinueWith(x => {
var result = "";
using (var sr = new StreamReader(x.Result))
{
result = sr.ReadToEnd();
}
Console.Write(result);
});
}
return base.SendAsync(request, cancellationToken);
}
}
This is my http request:
POST http://127.0.0.1/test HTTP/1.1
Connection: Keep-Alive
Content-Length: 29
Content-Type: application/x-www-form-urlencoded
Expect: 100-continue
Host: 127.0.0.1
my_property=my_value
the problem is that no matter how I try to read the info from request.Content
it's always empty. I've tried
request.Content.ReadAsStreamAsync
request.Content.ReadAsFormDataAsync
request.Content.ReadAs<FormDataCollection>
as well as
[HttpGet,HttpPost]
public string Index([FromBody]string my_property)
{
//my_property == null
return "Test";
}
None if it works. I cannot get the data out of the body. I'm hosting inside IIS on Windows 7 and using Fiddler to submit the request. What am I doing wrong?
The problem is that with the Web Api the body can only be read once. I had an HTTP module running that was logging all the details of the request and was reading through the body.
It's ugly, but you it seems from initial tinkering that you can, in fact, replace the Content in DelegatingHandler ...
protected override Task SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
Stream stream = new MemoryStream();
request.Content.ReadAsStreamAsync().Result.CopyTo(stream);
stream.Seek(0,SeekOrigin.Begin);
// copy off the content "for later"
string query = new StreamReader(stream).ReadToEnd();
stream.Seek(0,SeekOrigin.Begin);
// if further processing depends on content type
// go ahead and grab current value
var contentType = request.Content.Headers.ContentType;
request.Content = new StreamContent(stream);
request.Content.Headers.ContentType = contentType;
return base.SendAsync(request, cancellationToken);
}
I have no idea if this is good form or bad (suspect bad), but .... it seems to work and follows model I've seen recommended for those that need to modify request headers and content "on the way in" with a DelegatingHandler.
Your mileage may vary substantially.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With