Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the http body into a String in dot net core 2.0 using ReadAsync

I'm receiving and http post request, with raw body, and I'm trying to read the http body Stream into a String.

I'm using the basic Hello World web project generated by the dotnet web command. According to the documentation:

In the .NET Framework 4 and earlier versions, you have to use methods such as BeginRead and EndRead to implement asynchronous I/O operations. These methods are still available in the .NET Framework 4.5 to support legacy code; however, the new async methods, such as ReadAsync, WriteAsync, CopyToAsync, and FlushAsync, help you implement asynchronous I/O operations more easily.

So I tried with the ReadAsync method with something like this:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // _controller = controller;
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.Run(async (context) =>
    {

        using (Stream Body = context.Request.Body) {
            byte[] result;
            result = new byte[context.Request.Body.Length];
            await context.Request.Body.ReadAsync(result, 0, (int)context.Request.Body.Length);

            String body = System.Text.Encoding.UTF8.GetString(result).TrimEnd('\0');

            _log.LogInformation($"Body: {body}");
        }
        await context.Response.WriteAsync("Hello World!");
    });
}

But I'm getting the following error:

info: Microsoft.AspNetCore.Hosting.Internal.WebHost1 Request starting HTTP/1.1 POST http://localhost:5000/json/testing?id=2342&name=sas application/json 82 fail: Microsoft.AspNetCore.Server.Kestrel[13] Connection id "0HL7ISBH941G6", Request id "0HL7ISBH941G6:00000001": An unhandled exception was thrown by the application. System.NotSupportedException: Specified method is not supported. at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.FrameRequestStream.get_Length() at mtss.ws.Startup.<b__4_0>d.MoveNext() in /home/inspiron/devel/apps/dotnet/mtss-ws/Startup.cs:line 47

-- update

I could get something working setting the size of the buffer to Int16.MaxValue, but that way I can't read bodies larger that 32k.

like image 431
opensas Avatar asked Sep 03 '17 10:09

opensas


2 Answers

I found this question at SO that helped my find the following solution:

app.Run(async (context) =>
{

    string body = new StreamReader(context.Request.Body).ReadToEnd();
    _log.LogInformation($"Body: {body}");
    _log.LogInformation($"Body.Length: {body.Length}");

    await context.Response.WriteAsync("Hello World!");
});

and the async version is pretty much alike:

    string body = await new StreamReader(context.Request.Body).ReadToEndAsync();

Not sure if this is the best way to do it...

like image 156
opensas Avatar answered Oct 12 '22 23:10

opensas


I, too, had issues with ReadAsync stopping short of the full content. My solution is similar to the one offered by opensas, however, I did it with a "using" so the StreamReader's dispose method would be called automatically. I also added the UTF8 encoding option to the StreamReader.

using StreamReader reader = new StreamReader (Request.Body, Encoding.UTF8);
string body = await reader.ReadToEndAsync ();
like image 37
gcamp806 Avatar answered Oct 13 '22 00:10

gcamp806