New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EnableBuffering not working on .Net Core 3.0.100 #14396
Comments
Also tried: services.Configure(options => Same result. |
Can you post a minimal, runnable, sample project that reproduces the issue. Specifically, it's important to know exactly when in the control flow you are accessing |
If you're getting an ObjectDisposedException from |
Hi, some further information: Startup.cs: in ConfigureServices(IServiceCollection services)...
in Configure(IApplicationBuilder app, IWebHostEnvironment env)…
All controllers derive from ControllerBase class which derives from Controller. In ControllerBase.cs: public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) I am trying to access the request body in there so I can log the full json. This worked in .Net 1.x and 2.x. In 3.0, I get that the stream has been disposed. |
Do you have logs and/or exception details including a stack trace indicating where the ObjectDisposedException was thrown from? |
The callstack of the exception itself is: at System.IO.MemoryStream.get_Length() The app call stack is:
|
@SledgeHammer01 can you provide a runnable example with all of the code? It's diffcult to figure out what's going on without seeing the entire application. Even better would be to come up with a minimal repro. |
I'm trying to put together an example, just cleaning it up... but got a fuller stack trace... will post an example probably tomorrow morning.
HEADERS
|
Ok, here you go... When you run, it'll bring up the Swagger page, and try out testMethod2 for example, it'll throw the exception in ControllerBase.cs : OnActionExecutionAsync. Thanks! |
I added the area-mvc label because it looks like something in MVC is disposing the request stream when it wasn't before. This is likely the regression. I'm leaving the area-servers label because it might be better for FileBufferingReadStream.Dispose() to no-op like it does for the raw request stream. |
Is there a work-around? The goal is to be able to log the raw request in a central location. |
@pranavkm Did we change anything here that you're aware of? |
The Json.NET based input formatter buffers the request body to avoid synchronously reading the request body. MVC avoids double buffering if it thinks that the request is already buffered: https://github.com/aspnet/AspNetCore/blob/master/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonInputFormatter.cs#L132 |
The above seems super suspect. It appears as if NewtonsoftJsonInputFormatter assumes that if But it's possible that |
Yeah, that's the bug. We'll need to set a flag that says that MVC owns the stream. @mkArtakMSFT this is a small enough change we could consider squeezing in for 3.1. |
Is this a regression in 3.0? |
Yes |
Remove calls to |
@keenjus -- I can't remove that. We use some of the Json.Net hooks to correct the wrong serialization. The new json serializer has the same issues (doesn't maintain correct property order). |
There’s no workaround and this should be considered for patching in 3.1 |
Well I take that back, the workaround is to create a wrapping stream that does nothing when dispose is called (but has to dispose the inner stream at the right time as well) |
Hi David, I did actually find a temp work-around... pulling out the body right after the call to EnableBuffering and then rewinding the stream to 0 and not disposing it. |
@SledgeHammer01 I tried that still getting let GetRequestBody (context : HttpContext) =
task {
try
context.Request.EnableBuffering()
let reader = new StreamReader(context.Request.Body, encoding = Encoding.UTF8, detectEncodingFromByteOrderMarks = false, bufferSize = 1024, leaveOpen = true)
let! body = (reader.ReadToEndAsync())
context.Request.Body.Position <- 0L;
return Ok body
with _ ->
return Error "failed to get http body"
} |
@afshawnlotfi where is GetRequestBody(context) being called from? Is it possible the request was already read? Did you debug to see if |
We've addressed the reported issue as part of fcc20ac. This should be fixed in 3.1-preview2. In the meanwhile, @davidfowl's suggestion here - #14396 (comment) - would be the way to go. @afshawnlotfi could you please file a separate issue? |
Decided to tell my case here. Hope it will help somebody and save time 😃 I ran into a similar issue because I was using Here is my workaround as suggested by the comment #14396 (comment) Workaround:
Looks hacky, but it works 🤣 Other way to go in my case is to read request before passing it down the pipeline. I had logging middleware like this:
|
BTW, is it OK that |
@davidfowl we spoke about this. Think we should just address this in the formatter, it improves the experience for everyone involved. |
Auto drain? Yes I agree |
Hey guys, as 3.1-preview2 is out, the same issue still occurs. I have enabled httpContext.Request.EnableBuffering(), but I still get "Cannot access a disposed object". Are there more pending changes that are not released yet? |
@aidbal would you mind starting a new issue for this so we can track it correctly? |
.Net Core 3.0.100
Startup.cs:
When I try to access the stream by context.HttpContext.Request.Body later on, it reports that the stream has already been disposed and an exception is thrown.
The text was updated successfully, but these errors were encountered: