diff --git a/src/Mvc/Mvc.ViewFeatures/src/ViewComponentResultExecutor.cs b/src/Mvc/Mvc.ViewFeatures/src/ViewComponentResultExecutor.cs index ed480263c9..88b8027e9a 100644 --- a/src/Mvc/Mvc.ViewFeatures/src/ViewComponentResultExecutor.cs +++ b/src/Mvc/Mvc.ViewFeatures/src/ViewComponentResultExecutor.cs @@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewFeatures.Buffers; using Microsoft.AspNetCore.Mvc.ViewFeatures.Filters; +using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -148,14 +149,13 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures } else { - using var memoryStream = new MemoryStream(); - using (var intermediateWriter = _writerFactory.CreateWriter(response.Body, resolvedContentTypeEncoding)) + using var bufferingStream = new FileBufferingWriteStream(); + using (var intermediateWriter = _writerFactory.CreateWriter(bufferingStream, resolvedContentTypeEncoding)) { viewComponentResult.WriteTo(intermediateWriter, _htmlEncoder); } - memoryStream.Position = 0; - await memoryStream.CopyToAsync(response.Body); + await bufferingStream.DrainBufferAsync(response.Body); } } } diff --git a/src/Mvc/Mvc.ViewFeatures/test/ViewComponentResultTest.cs b/src/Mvc/Mvc.ViewFeatures/test/ViewComponentResultTest.cs index b217c08679..0eff0f4df0 100644 --- a/src/Mvc/Mvc.ViewFeatures/test/ViewComponentResultTest.cs +++ b/src/Mvc/Mvc.ViewFeatures/test/ViewComponentResultTest.cs @@ -439,6 +439,48 @@ namespace Microsoft.AspNetCore.Mvc Assert.Equal(expected, body); } + [Fact] + public async Task ExecuteResultAsync_WithCustomViewComponentHelper_ForLargeText() + { + // Arrange + var expected = new string('a', 64 * 1024 * 1024); + var methodInfo = typeof(TextViewComponent).GetMethod(nameof(TextViewComponent.Invoke)); + var descriptor = new ViewComponentDescriptor() + { + FullName = "Full.Name.Text", + ShortName = "Text", + TypeInfo = typeof(TextViewComponent).GetTypeInfo(), + MethodInfo = methodInfo, + Parameters = methodInfo.GetParameters(), + }; + var result = Task.FromResult(new HtmlContentBuilder().AppendHtml(expected)); + + var helper = Mock.Of(h => h.InvokeAsync(It.IsAny(), It.IsAny()) == result); + + var httpContext = new DefaultHttpContext(); + var services = CreateServices(diagnosticListener: null, httpContext, new[] { descriptor }); + services.AddSingleton(helper); + + httpContext.RequestServices = services.BuildServiceProvider(); + httpContext.Response.Body = new MemoryStream(); + + var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); + + var viewComponentResult = new ViewComponentResult() + { + Arguments = new { name = "World!" }, + ViewComponentType = typeof(TextViewComponent), + TempData = _tempDataDictionary, + }; + + // Act + await viewComponentResult.ExecuteResultAsync(actionContext); + + // Assert + var body = ReadBody(actionContext.HttpContext.Response); + Assert.Equal(expected, body); + } + [Fact] public async Task ExecuteResultAsync_SetsStatusCode() {