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

Has this been resolved in 5.8.0?

I have the following configured:

PreRequestFilters.Insert(0, (httpReq, httpRes) =>
{
httpReq.UseBufferedStream = true;
});

  • This is on .net core 3.1, SS v5.8.0
  • Getting - “Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.”

It’s not something ServiceStack can resolve, sync IO operations is to be avoided in .NET Core, ServiceStack can only mark the request to allow async io per request.

How are you retrieving the body are you using IRequest.GetRawBodyAsync()? e.g.

var body = await req.GetRawBodyAsync();

please post the full exception stacktrace.

I am retrieving the body exactly like you have:

var body = await req.GetRawBodyAsync();

Here’s the full stacktrace:

{ "responseStatus": { "errorCode": "InvalidOperationException", "message": "Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.", "stackTrace": " at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.Read(Byte[] buffer, Int32 offset, Int32 count)\n at System.IO.Stream.CopyTo(Stream destination, Int32 bufferSize)\n at System.IO.Stream.CopyTo(Stream destination)\n at ServiceStack.StreamExtensions.CopyToNewMemoryStream(Stream stream) in C:\\BuildAgent\\work\\912418dcce86a188\\src\\ServiceStack.Text\\StreamExtensions.cs:line 507\n at ServiceStack.BufferedExtensions.CreateBufferedStream(Stream stream) in C:\\BuildAgent\\work\\3481147c480f4a2f\\src\\ServiceStack\\RequestExtensions.cs:line 296\n at ServiceStack.Host.NetCore.NetCoreRequest.set_UseBufferedStream(Boolean value) in C:\\BuildAgent\\work\\3481147c480f4a2f\\src\\ServiceStack\\Host\\NetCore\\NetCoreRequest.cs:line 202\n at StageAgent.Web.StageAgentAppHost.<>c.<Configure>b__1_0(IRequest httpReq, IResponse httpRes) in /Users/kebin/projects/stageagent/stageagent-web/src/StageAgentAppHost.cs:line 27\n at ServiceStack.ServiceStackHost.ApplyPreRequestFilters(IRequest httpReq, IResponse httpRes) in C:\\BuildAgent\\work\\3481147c480f4a2f\\src\\ServiceStack\\ServiceStackHost.Runtime.cs:line 101\n at ServiceStack.Host.RestHandler.ProcessRequestAsync(IRequest req, IResponse httpRes, String operationName) in C:\\BuildAgent\\work\\3481147c480f4a2f\\src\\ServiceStack\\Host\\RestHandler.cs:line 81" } }

If I don’t have => httpReq.UseBufferedStream = true, then the body is empty string.

Error goes away and I can read fine when I configure the app with:

services.Configure(options =>
{
options.AllowSynchronousIO = true;
});

Let me know if this mutes the exception?

PreRequestFilters.Insert(0, (httpReq, httpRes) =>
{
    httpRes.AllowSyncIO();
    httpReq.UseBufferedStream = true;
});

Yes, that worked. Thanks!

So in order to target certain request I’d do something like?

`RegisterTypedRequestFilter<IncomingWebhook>((req, res, dto) =>
        {
            PreRequestFilters.Insert(0, (httpReq, httpRes) =>
            {
                httpRes.AllowSyncIO();
                httpReq.UseBufferedStream = true;
            });
        });`

FYI this is now being automatically applied from the latest v5.8.1 that’s now available on MyGet so you wont have to call AllowSyncIO() manually.

Never nest filters, filters should only be registered on Startup, registering filters within themsleves will add a filter each time its run resulting in a memory leak and duplicated logic each time the request is called.

The Request InputStream isn’t read and the Request DTO isn’t created when PreRequestFilters is called so you’ll need to inspect the request to determine which requests you want to selectively buffer, e.g:

PreRequestFilters.Insert(0, (httpReq, httpRes) =>
{
    httpRes.AllowSyncIO(); // not required from v5.8.1
    if (httpReq.PathInfo.StartsWith("..."))
        httpReq.UseBufferedStream = true;
});
2 Likes

Awesome! Thank you so much!

Hi,

I’ve just had this issue with v5.9.0 and had to apply this fix to get around it.
Oddly, JSV and JSON worked fine but the error occurred with all the other formats.
You mentioned in another comment that this shouldn’t be necessary from v5.8.1 onwards. Is there something else that I need to do (a config switch or somesuch) that removes the need for this filter?

Regards,
Alan

All registered Serializers need to either asynchronously read/write to the Request/Response Streams, async read into a buffer or call AllowSyncIO() to mark to allow sync read/writes for that request.

Which formats have the issue?

Our app uses JSV, JSON, ProtoBuf, MsgPack, XML, and CSV.
As I mentioned, JSV and JSON both work fine, but the others all need the filter to stop the error message.

Most serializers are synchronous, this filter says to allow synchronous serializers for that request.
Can you provide the full Exception StackTrace?

Okay, here’s the weird thing. I wrestled with this issue for most of yesterday afternoon and saw the exception being thrown every time I used any client service other than JSV and JSON.

At the end of the day, I left my machine running overnight, then this morning I ran it again to create a fresh exception message to send to you. I didn’t make any code changes, or even re-compile. This morning it is working as expected for all client services.

To prove that I wasn’t going mad, I 'm pasting the last exception from yesterday’s log file in case it sheds any light:

[15:40:32.481428][ThrdId: 31][DBG] CreateContentTypeRequest/hasContentBody:True:POST:application/x-protobuf:70:
[15:40:32.492371][ThrdId: 31][ERR] Could not deserialize 'application/x-protobuf' request using ABD.Track.DataService.App.CrossCutting.Core.Data.Entities.VehicleManufacturerEntities.DeleteVehicleManufacturer[]'
Error: System.InvalidOperationException: Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at ProtoBuf.ProtoReader.StreamProtoReader.Ensure(State& state, Int32 count, Boolean strict) in /_/src/protobuf-net.Core/ProtoReader.Stream.cs:line 382
   at ProtoBuf.ProtoReader.StreamProtoReader.ImplTryReadUInt32VarintWithoutMoving(State& state, Read32VarintMode mode, UInt32& value) in /_/src/protobuf-net.Core/ProtoReader.Stream.cs:line 189
   at ProtoBuf.ProtoReader.State.ReadFieldHeaderFallback() in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 706
   at ProtoBuf.ProtoReader.State.<ReadAsRoot>g__ReadFieldOne|101_0[T](State& state, SerializerFeatures features, T value, ISerializer`1 serializer) in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 1066
   at ProtoBuf.ProtoReader.State.ReadAsRoot[T](T value, ISerializer`1 serializer) in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 1058
   at ProtoBuf.ProtoReader.State.DeserializeRoot[T](T value, ISerializer`1 serializer) in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 1032
   at ProtoBuf.Internal.DynamicStub.ConcreteStub`1.TryDeserializeRoot(TypeModel model, State& state, Object& value, Boolean autoCreate) in /_/src/protobuf-net.Core/Internal/DynamicStub.cs:line 184
   at ProtoBuf.Meta.TypeModel.DeserializeRootAny(State& state, Type type, Object value, Boolean autoCreate) in /_/src/protobuf-net.Core/Meta/TypeModel.cs:line 1057
   at ProtoBuf.ProtoReader.State.DeserializeRootFallback(Object value, Type type) in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 1142
   at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type) in /_/src/protobuf-net.Core/Meta/TypeModel.cs:line 707
   at ServiceStack.ProtoBuf.ProtoBufFormat.Deserialize(Type type, Stream fromStream) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.ProtoBuf\ProtoBufFormat.cs:line 35
   at ServiceStack.Host.ContentTypes.<>c__DisplayClass37_0.<GetStreamDeserializerAsync>b__0(Type type, Stream stream) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\ContentTypes.cs:line 366
   at ServiceStack.Host.Handlers.ServiceStackHandlerBase.CreateContentTypeRequestAsync(IRequest httpReq, Type requestType, String contentType) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\Handlers\ServiceStackHandlerBase.cs:line 221
System.Runtime.Serialization.SerializationException: Could not deserialize 'application/x-protobuf' request using ABD.Track.DataService.App.CrossCutting.Core.Data.Entities.VehicleManufacturerEntities.DeleteVehicleManufacturer[]'
Error: System.InvalidOperationException: Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at ProtoBuf.ProtoReader.StreamProtoReader.Ensure(State& state, Int32 count, Boolean strict) in /_/src/protobuf-net.Core/ProtoReader.Stream.cs:line 382
   at ProtoBuf.ProtoReader.StreamProtoReader.ImplTryReadUInt32VarintWithoutMoving(State& state, Read32VarintMode mode, UInt32& value) in /_/src/protobuf-net.Core/ProtoReader.Stream.cs:line 189
   at ProtoBuf.ProtoReader.State.ReadFieldHeaderFallback() in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 706
   at ProtoBuf.ProtoReader.State.<ReadAsRoot>g__ReadFieldOne|101_0[T](State& state, SerializerFeatures features, T value, ISerializer`1 serializer) in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 1066
   at ProtoBuf.ProtoReader.State.ReadAsRoot[T](T value, ISerializer`1 serializer) in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 1058
   at ProtoBuf.ProtoReader.State.DeserializeRoot[T](T value, ISerializer`1 serializer) in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 1032
   at ProtoBuf.Internal.DynamicStub.ConcreteStub`1.TryDeserializeRoot(TypeModel model, State& state, Object& value, Boolean autoCreate) in /_/src/protobuf-net.Core/Internal/DynamicStub.cs:line 184
   at ProtoBuf.Meta.TypeModel.DeserializeRootAny(State& state, Type type, Object value, Boolean autoCreate) in /_/src/protobuf-net.Core/Meta/TypeModel.cs:line 1057
   at ProtoBuf.ProtoReader.State.DeserializeRootFallback(Object value, Type type) in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 1142
   at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type) in /_/src/protobuf-net.Core/Meta/TypeModel.cs:line 707
   at ServiceStack.ProtoBuf.ProtoBufFormat.Deserialize(Type type, Stream fromStream) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.ProtoBuf\ProtoBufFormat.cs:line 35
   at ServiceStack.Host.ContentTypes.<>c__DisplayClass37_0.<GetStreamDeserializerAsync>b__0(Type type, Stream stream) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\ContentTypes.cs:line 366
   at ServiceStack.Host.Handlers.ServiceStackHandlerBase.CreateContentTypeRequestAsync(IRequest httpReq, Type requestType, String contentType) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\Handlers\ServiceStackHandlerBase.cs:line 221
 ---> System.InvalidOperationException: Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at ProtoBuf.ProtoReader.StreamProtoReader.Ensure(State& state, Int32 count, Boolean strict) in /_/src/protobuf-net.Core/ProtoReader.Stream.cs:line 382
   at ProtoBuf.ProtoReader.StreamProtoReader.ImplTryReadUInt32VarintWithoutMoving(State& state, Read32VarintMode mode, UInt32& value) in /_/src/protobuf-net.Core/ProtoReader.Stream.cs:line 189
   at ProtoBuf.ProtoReader.State.ReadFieldHeaderFallback() in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 706
   at ProtoBuf.ProtoReader.State.<ReadAsRoot>g__ReadFieldOne|101_0[T](State& state, SerializerFeatures features, T value, ISerializer`1 serializer) in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 1066
   at ProtoBuf.ProtoReader.State.ReadAsRoot[T](T value, ISerializer`1 serializer) in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 1058
   at ProtoBuf.ProtoReader.State.DeserializeRoot[T](T value, ISerializer`1 serializer) in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 1032
   at ProtoBuf.Internal.DynamicStub.ConcreteStub`1.TryDeserializeRoot(TypeModel model, State& state, Object& value, Boolean autoCreate) in /_/src/protobuf-net.Core/Internal/DynamicStub.cs:line 184
   at ProtoBuf.Meta.TypeModel.DeserializeRootAny(State& state, Type type, Object value, Boolean autoCreate) in /_/src/protobuf-net.Core/Meta/TypeModel.cs:line 1057
   at ProtoBuf.ProtoReader.State.DeserializeRootFallback(Object value, Type type) in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 1142
   at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type) in /_/src/protobuf-net.Core/Meta/TypeModel.cs:line 707
   at ServiceStack.ProtoBuf.ProtoBufFormat.Deserialize(Type type, Stream fromStream) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.ProtoBuf\ProtoBufFormat.cs:line 35
   at ServiceStack.Host.ContentTypes.<>c__DisplayClass37_0.<GetStreamDeserializerAsync>b__0(Type type, Stream stream) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\ContentTypes.cs:line 366
   at ServiceStack.Host.Handlers.ServiceStackHandlerBase.CreateContentTypeRequestAsync(IRequest httpReq, Type requestType, String contentType) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\Handlers\ServiceStackHandlerBase.cs:line 221
   --- End of inner exception stack trace ---
   at ServiceStack.Host.Handlers.ServiceStackHandlerBase.CreateContentTypeRequestAsync(IRequest httpReq, Type requestType, String contentType) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\Handlers\ServiceStackHandlerBase.cs:line 229
   at ServiceStack.Host.Handlers.ServiceStackHandlerBase.DeserializeHttpRequestAsync(Type operationType, IRequest httpReq, String contentType) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\Handlers\ServiceStackHandlerBase.cs:line 183
   at ServiceStack.Host.Handlers.GenericHandler.CreateRequestAsync(IRequest req, String operationName) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\Handlers\GenericHandler.cs:line 32
   at ServiceStack.Host.Handlers.GenericHandler.ProcessRequestAsync(IRequest httpReq, IResponse httpRes, String operationName) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\Handlers\GenericHandler.cs:line 53

This is the deletion DTO:

   [ProtoContract]    
   [Route( "/api/vehicleManufacturers/{Id}", HttpMethods.Delete, Summary = "Delete a Vehicle Manufacturer" )]
    public class DeleteVehicleManufacturer : IDeleteDb< VehicleManufacturer >, IReturn< DeleteVehicleManufacturerResponse >, IChangeDb, IHasIntId
    {
        #region Properties and Indexers

        [ProtoMember( 1, DataFormat = DataFormat.ZigZag )]
        public int Id { get; set; }

        [ProtoMember( 2 )]
        public ulong RowVersion { get; set; }

        [ProtoMember( 3 )]
        public string NamedConnection { get; set; }

        #endregion
    }

The response (so that I can log the Id(s) affected by the deletion):

    [ProtoContract]
    public class DeleteVehicleManufacturerResponse : IHasResponseStatus, IHasIntId
    {
        #region Properties and Indexers

        [ProtoMember( 1, DataFormat = DataFormat.ZigZag )]
        public int Id { get; set; }

        [ProtoMember( 2 )]
        public ResponseStatus ResponseStatus { get; set; }

        #endregion
    }

And the triggering call:

var requests = new List< DeleteVehicleManufacturer >( batched.Length );
foreach ( var vehicleManufacturer in batched )
{
   requests.Add(
      new DeleteVehicleManufacturer
      {
         Id = vehicleManufacturer.Id,
         RowVersion = vehicleManufacturer.RowVersion,
         NamedConnection = Constants.DatabaseName
      } );
}

var responses = await _client.SendAllAsync( requests ).ConfigureAwait( false );

Are you sure this was with the latest ServiceStack v5.9?

Yes, I just re-checked my server and client projects. Both are using ServiceStack.*.Core v5.9.0

I’d like to be able to repro the issue, so I need confirmation the issue exists with the latest version, I.e. it occurred after upgrading?

I have only ever used v5.9.0, using the Core versions of the packages since I’m using Core 3.1, so not needed to upgrade from a previous version.

Note: The *.Core packages are only for running ASP.NET Core Apps on the .NET Framework, since you’re running on .NET Core 3.1 you should be running the normal NuGet packages, i.e. without the *.Core suffix.

Ah, okay. I’ll switch over when I finish working on my current ticket.

Ok reason why I couldn’t repro it locally was because I had made the change 3 weeks ago, unfortunately just after v5.9’s release. So if you upgrade to v5.9.1 on MyGet you’ll no longer need a custom filter.

Thanks for taking the time to look into this. I’ll try the 5.9.1 build on Monday.

1 Like