aspnetcore: System.ObjectDisposedException: Cannot write to the response body, the response has completed

Application Name: Blazor-Blogs OS: Windows 10 19H1 CPU: X64 .NET Build Number: 5.0.100-rc.1.20425.5-win-x64 App Location: On repro machine, at C:\Users\Appcompat\Documents\Blazor-Blogs App Source: On repro machine, at C:\Users\Appcompat\Documents\Blazor-BlogsSource App Source on GitHub link: https://github.com/ADefWebserver/Blazor-Blogs (this source is new, we test old version )

Verify Scenarios: 1). Windows 10 19H1 X64 + .NET Core SDK build 5.0.100-rc.1.20425.5-win-x64: Fail 2). Windows 10 19H1 X64 + .NET Core SDK build 5.0.100-preview.8.20417.9-win-x64 5.0 Preview 8: Pass 3). Windows 10 19H1 X64 + .NET Core SDK build 3.1.401-win-x64 Pass

Repro Machine: See in https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1181306

Repo Machine Environment Info : .NET SDK (reflecting any global.json): Version: 5.0.100-rc.1.20425.5​ Commit: 85c205f9d8​

Runtime Environment:​ OS Name: Windows​ OS Version: 10.0.18362​ OS Platform: Windows​ RID: win10-x64​ Base Path: C:\Program Files\dotnet\sdk\5.0.100-rc.1.20425.5\​ ​ Host (useful for support):​ Version: 5.0.0-rc.1.20425.1​ Commit: f4e99f4afa​ ​ .NET SDKs installed:​ 5.0.100-rc.1.20425.5 [C:\Program Files\dotnet\sdk]​ ​ .NET runtimes installed:​ Microsoft.AspNetCore.App 5.0.0-rc.1.20424.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]​ Microsoft.NETCore.App 5.0.0-rc.1.20425.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]​ Microsoft.WindowsDesktop.App 5.0.0-rc.1.20424.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Repro steps: On the repo machine

  1. On CMD, type “set ASPNETCORE_ENVIRONMENT=Development”, then type “Enter”.
  2. Type “cd C:\Users\Appcompat\Documents\Blazor-Blogs\Publish”, then type “Enter”.
  3. Type “dotnet BlazorBlogs.dll”,then type “Enter”.
  4. Open the website: http://localhost:5000/ in Edge browser.

Expected Result: Open website successfully

Actual Result: An unhandled exception occurred while processing the request. MissingFieldException: Field not found: ‘Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame.FrameType’.

Exception Log:

MissingFieldException: Field not found: 'Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame.FrameType'.
Toolbelt.Blazor.HeadElement.Title.OnParametersSetAsync()​
System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<TStateMachine>(ref TStateMachine stateMachine)​
System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start<TStateMachine>(ref TStateMachine stateMachine)​
Toolbelt.Blazor.HeadElement.Title.OnParametersSetAsync()​
Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync()​
Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()​
Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.HandleException(Exception exception)​
Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToPendingTasks(Task task)​
Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters)​
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(ref DiffContext diffContext, int frameIndex)​
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(ref DiffContext diffContext, int frameIndex)​
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(ref DiffContext diffContext, int newFrameIndex)​
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(ref DiffContext diffContext, int oldStartIndex, int oldEndIndexExcl, int newStartIndex, int newEndIndexExcl)​
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer renderer, RenderBatchBuilder batchBuilder, int componentId, ArrayRange<RenderTreeFrame> oldTree, ArrayRange<RenderTreeFrame> newTree)​
Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment)​
Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry renderQueueEntry)​
Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()​
Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.HandleException(Exception exception)​
Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()​
Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessPendingRender()​
Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToRenderQueue(int componentId, RenderFragment renderFragment)​
Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged()​
Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync()​
Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()​
Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.HandleException(Exception exception)​
Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToPendingTasks(Task task)​
Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters)​
Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderRootComponentAsync(int componentId, ParameterView initialParameters)​
Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.CreateInitialRenderAsync(Type componentType, ParameterView initialParameters)​
Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.RenderComponentAsync(Type componentType, ParameterView initialParameters)​
Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext+<>c__11<TResult>+<<InvokeAsync>b__11_0>d.MoveNext()​
Microsoft.AspNetCore.Mvc.ViewFeatures.StaticComponentRenderer.PrerenderComponentAsync(ParameterView parameters, HttpContext httpContext, Type componentType)​
Microsoft.AspNetCore.Mvc.ViewFeatures.ComponentRenderer.PrerenderedServerComponentAsync(HttpContext context, ServerComponentInvocationSequence invocationId, Type type, ParameterView parametersCollection)​
Microsoft.AspNetCore.Mvc.ViewFeatures.ComponentRenderer.RenderComponentAsync(ViewContext viewContext, Type componentType, RenderMode renderMode, object parameters)​
Microsoft.AspNetCore.Mvc.TagHelpers.ComponentTagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output)​
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.<RunAsync>g__Awaited|0_0(Task task, TagHelperExecutionContext executionContext, int i, int count)​
BlazorBlogs.Pages.Pages__Host.<ExecuteAsync>b__14_1()​
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.SetOutputContentAsync()​
BlazorBlogs.Pages.Pages__Host.ExecuteAsync()​
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)​
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, bool invokeViewStarts)​
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)​
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)​
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)​
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0<TFilter, TFilterAsync>(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)​
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)​
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)​
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()​
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)​
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)​
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)​
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()​
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)​
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)​
WilderMinds.MetaWeblog.MetaWeblogMiddleware.Invoke(HttpContext context, MetaWeblogService service)​
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)​
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)​
Toolbelt.Blazor.HeadElement.Middlewares.HeadElementServerPrerenderingMiddleware.InvokeAsync(HttpContext context, IHeadElementHelperStore store)​
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context)​
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)​
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)​
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context).

Findings : When we check the ‘Microsoft.AspNetCore.Components.dll’ version 5.0.0, we found the field in RenderTree class is “FrameTypeField”.

[FieldOffset(4)] internal RenderTreeFrameType FrameTypeField; //changed here

But in previous version, it is FrameType.

DUMP file captured and stored in repo machine, path for the DUMP file is C:\Users\Appcompat\Documents\Blazor-Blogs.DMP Exception from the sample code above :

System.MissingFieldException: Field not found: 'Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame.FrameType'.
   at Toolbelt.Blazor.HeadElement.Title.OnParametersSetAsync()​
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)​
   at Toolbelt.Blazor.HeadElement.Title.OnParametersSetAsync()​
   at Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync()​
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()​
   at Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.HandleException(Exception exception)​
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToPendingTasks(Task task)​
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters)​
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext& diffContext, Int32 frameIndex)​
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext& diffContext, Int32 frameIndex)​
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& diffContext, Int32 newFrameIndex)​
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl)​
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer renderer, RenderBatchBuilder batchBuilder, Int32 componentId, ArrayRange`1 oldTree, ArrayRange`1 newTree)​
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment)​
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry renderQueueEntry)​
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()​
--- End of stack trace from previous location ---​
   at Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.HandleException(Exception exception)​
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()​
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessPendingRender()​
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToRenderQueue(Int32 componentId, RenderFragment renderFragment)​
   at Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged()​
   at Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync()​
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()​
   at Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.HandleException(Exception exception)​
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToPendingTasks(Task task)​
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters)​
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderRootComponentAsync(Int32 componentId, ParameterView initialParameters)​
   at Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.CreateInitialRenderAsync(Type componentType, ParameterView initialParameters)​
   at Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.RenderComponentAsync(Type componentType, ParameterView initialParameters)​
   at Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.<>c__11`1.<<InvokeAsync>b__11_0>d.MoveNext()

cc @dotnet-actwx-bot

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 23 (11 by maintainers)

Most upvoted comments

@jiangzeng01 I published the fixed version of the Toolbelt.Blazor.HeadElement.ServerPrerendering NuGet package.

Could you try it out?

@jsakamoto Thanks, we will have a try on this.

On the subject of the original binary-breaking change in RenderTreeFrame in the RC1 release, an announcement is now posted at https://github.com/aspnet/Announcements/issues/438.

Here’s something we could do to be more defensive. It’s a new method on StreamResponseBodyFeature to be registered with OnCompleted instead of CompleteAsync. It’s mostly the same as CompleteAsync but it doesn’t call StartAsync. StartAsync doesn’t make much sense from the OnCompleted callback, but it can matter when someone calls CompleteAsync directly.

        internal async Task DisposeAsync()
        {
            // DisposeAsync is registered with HttpResponse.OnCompleted and there's no way to unregister it.
            // Prevent it from running by marking as disposed.
            if (_disposed)
            {
                return;
            }
            if (_completed)
            {
                return;
            }

            _disposed = true;
            _completed = true;

            if (_pipeWriter != null)
            {
                await _pipeWriter.CompleteAsync();
            }
        }

On the subject of the original binary-breaking change in RenderTreeFrame in the RC1 release, an announcement is now posted at aspnet/Announcements#438.

@jsakamoto The app works fine with these 2 new packages, thanks a lot for fixing.

This only affects middleware that doesn’t reset the response body, and it’s just log noise because an “app-defined” (really DefaultHttpResponse-defined) callback threw an exception.

I talked to @Tratcher and we agree we can make changes to StreamResponseBodyFeature to make it more defensive in this case, but it’s not a big deal for RC1.

I see the issue, but I don’t know why it would have changed in RC1, most of this behavior has been around since 3.0.

FilterStream replaces Response.Body on they way in. https://github.com/jsakamoto/Toolbelt.Blazor.HeadElement/blob/c38e260c1434cd1297975191d300b8e81d67e12d/ServerPrerendering/Middlewares/FilterStream.cs#L50-L52 Here’s what that does internally: https://github.com/dotnet/aspnetcore/blob/3d042ac9aaf6df4cfd1d2bd4a984a86a45629285/src/Http/Http/src/Internal/DefaultHttpResponse.cs#L85-L87

The problem is that HeadElementServerPrerenderingMiddleware never reverts the change to the response body on the way out, so the default cleanup logic tries to run and hits the ODE. The fix is for HeadElementServerPrerenderingMiddleware to revert the response body which will suppress the default cleanup logic. https://github.com/jsakamoto/Toolbelt.Blazor.HeadElement/blob/c38e260c1434cd1297975191d300b8e81d67e12d/ServerPrerendering/Middlewares/HeadElementServerPrerenderingMiddleware.cs#L27-L29 https://github.com/dotnet/aspnetcore/blob/3d042ac9aaf6df4cfd1d2bd4a984a86a45629285/src/Http/Http/src/Internal/DefaultHttpResponse.cs#L78-L82

Side note. FilterStream.Dispose should not call OriginalStream.Dispose, it doesn’t own that resource, the server does. https://github.com/jsakamoto/Toolbelt.Blazor.HeadElement/blob/c38e260c1434cd1297975191d300b8e81d67e12d/ServerPrerendering/Middlewares/FilterStream.cs#L107