| File: Infrastructure\ContentResultExecutor.cs | Web Access |
| Project: src\aspnetcore\src\Mvc\Mvc.Core\src\Microsoft.AspNetCore.Mvc.Core.csproj (Microsoft.AspNetCore.Mvc.Core) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable enable using System.Text; using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.Infrastructure; /// <summary> /// A <see cref="IActionResultExecutor{ContentResult}"/> that is responsible for <see cref="ContentResult"/> /// </summary> public partial class ContentResultExecutor : IActionResultExecutor<ContentResult> { private const string DefaultContentType = "text/plain; charset=utf-8"; private readonly ILogger<ContentResultExecutor> _logger; private readonly IHttpResponseStreamWriterFactory _httpResponseStreamWriterFactory; /// <summary> /// Initializes a new instance of <see cref="ContentResultExecutor"/>. /// </summary> /// <param name="logger">The logger to use.</param> /// <param name="httpResponseStreamWriterFactory">The stream writer factory.</param> public ContentResultExecutor(ILogger<ContentResultExecutor> logger, IHttpResponseStreamWriterFactory httpResponseStreamWriterFactory) { _logger = logger; _httpResponseStreamWriterFactory = httpResponseStreamWriterFactory; } /// <inheritdoc /> public virtual async Task ExecuteAsync(ActionContext context, ContentResult result) { ArgumentNullException.ThrowIfNull(context); ArgumentNullException.ThrowIfNull(result); var response = context.HttpContext.Response; ResponseContentTypeHelper.ResolveContentTypeAndEncoding( result.ContentType, response.ContentType, (DefaultContentType, Encoding.UTF8), MediaType.GetEncoding, out var resolvedContentType, out var resolvedContentTypeEncoding); response.ContentType = resolvedContentType; if (result.StatusCode != null) { response.StatusCode = result.StatusCode.Value; } Log.ContentResultExecuting(_logger, resolvedContentType); if (result.Content != null) { response.ContentLength = resolvedContentTypeEncoding.GetByteCount(result.Content); await using (var textWriter = _httpResponseStreamWriterFactory.CreateWriter(response.Body, resolvedContentTypeEncoding)) { await textWriter.WriteAsync(result.Content); // Flushing the HttpResponseStreamWriter does not flush the underlying stream. This just flushes // the buffered text in the writer. // We do this rather than letting dispose handle it because dispose would call Write and we want // to call WriteAsync. await textWriter.FlushAsync(); } } } private static partial class Log { [LoggerMessage(1, LogLevel.Information, "Executing ContentResult with HTTP Response ContentType of {ContentType}", EventName = "ContentResultExecuting")] public static partial void ContentResultExecuting(ILogger logger, string contentType); } }