Netcore 3.0 - GetRawBody - Could not load 'Microsoft.AspNetCore.Http.Internal.BufferingHelper'

Hi

Trying to migrate to netcore 3 i found an exception when i use Request.GetRawBody()

Then have created a new project of AspNetCore with netcore3 (VS2019), add ServiceStack nuget, and the exceptions is thrown again

Exception:
System.TypeLoadException
HResult=0x80131522
Message=Could not load type ‘Microsoft.AspNetCore.Http.Internal.BufferingHelper’ from assembly ‘Microsoft.AspNetCore.Http, Version=3.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60’.
Source=ServiceStack
StackTrace:
at ServiceStack.Host.NetCore.NetCoreRequest.GetRawBody() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\NetCore\NetCoreRequest.cs:line 211
at ServiceStackAspNetCoreTest.AspNetCoreTestServices.Any(SayHello request) in D:\experiments\ServiceStackAspNetCoreTest\ServiceStackAspNetCoreTest\Program.cs:line 59

The InnerException property is empty (null)

System:

  • Windows 10,
  • Visual Studio 2019,
  • netcore: multiple versoins of 2.1.x, 2.2.x and of 3.0 have:
  • Microsoft.AspNetCore.App 3.0.0,
  • Microsoft.NETCore.App 3.0.0,
  • Microsoft.WindowsDesktop.App 3.0.0
  • ServiceStack 5.7.0 & 5.7.1 (retrieved today)

Code:

– Program.cs –

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using ServiceStack;
using Funq;

namespace ServiceStackAspNetCoreTest
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services) { }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseServiceStack(new AspNetCoreTestAppHost());
        }
    }

    public class AspNetCoreTestAppHost : AppHostBase
    {
        public AspNetCoreTestAppHost() : base("AspNetCoreTestApp", typeof(AspNetCoreTestServices).Assembly)  {}
        public override void Configure(Container container) =>
            SetConfig(new HostConfig { DebugMode = true });
    }

    public class AspNetCoreTestServices : Service
    {
        public object Any(SayHello request)
        {
            var body = Request.GetRawBody();

            return new SayHelloResponse
            {
                Message = $"Hello {request.Name}!",
            };
        }
    }

    [Route("/api/hello/{name}")]
    public class SayHello : IReturn<SayHelloResponse>
    {
        public string Name { get; set; }
    }

    internal class SayHelloResponse
    {
        public string Message { get; set; }
    }
}

Looks like this is an unannounced breaking change in .NET Core 3.0 where we need to change to use EnableBuffering() instead of EnableRewind().

Also as .NET Core 3.0 disallows sync I/O access by default I’ve marked GetRawBody() to AllowSyncIO and have also added GetRawBodyAsync() which should be preferred in .NET Core 3.0.

This change is available from v5.7.1 that’s now available on MyGet.