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

2

9

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.

Elephant answered 3/9, 2017 at 10:6 Comment(3)
Can you show us the entire code, how youre getting the data in the first place?Hullda
sure, there you goElephant
Only async functions working! This code had ran in my app. <code> using (Stream Body = request.Body) { byte[] result; // int len = request.Body.Length ---> Error result = new byte[UInt16.MaxValue]; await request.Body.ReadAsync(result, 0, UInt16.MaxValue); return System.Text.Encoding.UTF8.GetString(result).TrimEnd('\0'); } </code>Felicio
E
11

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...

Elephant answered 3/9, 2017 at 18:32 Comment(0)
P
6

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 ();
Poach answered 20/2, 2020 at 22:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.