public async Task ExecuteAsync(ActionContext context, JsonResult result)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            var jsonSerializerOptions = GetSerializerOptions(result);

            var response = context.HttpContext.Response;

            ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
                result.ContentType,
                response.ContentType,
                DefaultContentType,
                out var resolvedContentType,
                out var resolvedContentTypeEncoding);

            response.ContentType = resolvedContentType;

            if (result.StatusCode != null)
            {
                response.StatusCode = result.StatusCode.Value;
            }

            Log.JsonResultExecuting(_logger, result.Value);

            // Keep this code in sync with SystemTextJsonOutputFormatter
            var writeStream = GetWriteStream(context.HttpContext, resolvedContentTypeEncoding);

            try
            {
                var value = result.Value;
                if (value is IAsyncEnumerable <object> asyncEnumerable)
                {
                    Log.BufferingAsyncEnumerable(_logger, asyncEnumerable);
                    value = await _asyncEnumerableReader.ReadAsync(asyncEnumerable);
                }

                var type = value?.GetType() ?? typeof(object);
                await JsonSerializer.SerializeAsync(writeStream, value, type, jsonSerializerOptions);

                // The transcoding streams use Encoders and Decoders that have internal buffers. We need to flush these
                // when there is no more data to be written. Stream.FlushAsync isn't suitable since it's
                // acceptable to Flush a Stream (multiple times) prior to completion.
                if (writeStream is TranscodingWriteStream transcodingStream)
                {
                    await transcodingStream.FinalWriteAsync(CancellationToken.None);
                }
                await writeStream.FlushAsync();
            }
            finally
            {
                if (writeStream is TranscodingWriteStream transcodingStream)
                {
                    await transcodingStream.DisposeAsync();
                }
            }
        }
Esempio n. 2
0
        public async Task ExecuteAsync(ActionContext context, JsonResult result)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            var jsonSerializerOptions = GetSerializerOptions(result);

            var response = context.HttpContext.Response;

            ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
                result.ContentType,
                response.ContentType,
                DefaultContentType,
                out var resolvedContentType,
                out var resolvedContentTypeEncoding);

            response.ContentType = resolvedContentType;

            if (result.StatusCode != null)
            {
                response.StatusCode = result.StatusCode.Value;
            }

            Log.JsonResultExecuting(_logger, result.Value);

            var value = result.Value;

            if (value != null && _asyncEnumerableReaderFactory.TryGetReader(value.GetType(), out var reader))
            {
                Log.BufferingAsyncEnumerable(_logger, value);
                value = await reader(value);
            }

            var objectType = value?.GetType() ?? typeof(object);

            // Keep this code in sync with SystemTextJsonOutputFormatter
            var responseStream = response.Body;

            if (resolvedContentTypeEncoding.CodePage == Encoding.UTF8.CodePage)
            {
                await JsonSerializer.SerializeAsync(responseStream, value, objectType, jsonSerializerOptions);

                await responseStream.FlushAsync();
            }
            else
            {
                // JsonSerializer only emits UTF8 encoded output, but we need to write the response in the encoding specified by
                // selectedEncoding
                var transcodingStream = Encoding.CreateTranscodingStream(response.Body, resolvedContentTypeEncoding, Encoding.UTF8, leaveOpen: true);

                ExceptionDispatchInfo?exceptionDispatchInfo = null;
                try
                {
                    await JsonSerializer.SerializeAsync(transcodingStream, value, objectType, jsonSerializerOptions);

                    await transcodingStream.FlushAsync();
                }
                catch (Exception ex)
                {
                    // TranscodingStream may write to the inner stream as part of it's disposal.
                    // We do not want this exception "ex" to be eclipsed by any exception encountered during the write. We will stash it and
                    // explicitly rethrow it during the finally block.
                    exceptionDispatchInfo = ExceptionDispatchInfo.Capture(ex);
                }
                finally
                {
                    try
                    {
                        await transcodingStream.DisposeAsync();
                    }
                    catch when(exceptionDispatchInfo != null)
                    {
                    }

                    exceptionDispatchInfo?.Throw();
                }
            }
        }
        /// <summary>
        /// Executes the <see cref="JsonResult"/> and writes the response.
        /// </summary>
        /// <param name="context">The <see cref="ActionContext"/>.</param>
        /// <param name="result">The <see cref="JsonResult"/>.</param>
        /// <returns>A <see cref="Task"/> which will complete when writing has completed.</returns>
        public async Task ExecuteAsync(ActionContext context, JsonResult result)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            var jsonSerializerSettings = GetSerializerSettings(result);

            var response = context.HttpContext.Response;

            ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
                result.ContentType,
                response.ContentType,
                DefaultContentType,
                out var resolvedContentType,
                out var resolvedContentTypeEncoding);

            response.ContentType = resolvedContentType;

            if (result.StatusCode != null)
            {
                response.StatusCode = result.StatusCode.Value;
            }

            Log.JsonResultExecuting(_logger, result.Value);

            var responseStream = response.Body;
            FileBufferingWriteStream?fileBufferingWriteStream = null;

            if (!_mvcOptions.SuppressOutputFormatterBuffering)
            {
                fileBufferingWriteStream = new FileBufferingWriteStream();
                responseStream           = fileBufferingWriteStream;
            }

            try
            {
                await using (var writer = _writerFactory.CreateWriter(responseStream, resolvedContentTypeEncoding))
                {
                    using var jsonWriter           = new JsonTextWriter(writer);
                    jsonWriter.ArrayPool           = _charPool;
                    jsonWriter.CloseOutput         = false;
                    jsonWriter.AutoCompleteOnClose = false;

                    var jsonSerializer = JsonSerializer.Create(jsonSerializerSettings);
                    var value          = result.Value;
                    if (value != null && _asyncEnumerableReaderFactory.TryGetReader(value.GetType(), out var reader))
                    {
                        Log.BufferingAsyncEnumerable(_logger, value);
                        value = await reader(value);
                    }

                    jsonSerializer.Serialize(jsonWriter, value);
                }

                if (fileBufferingWriteStream != null)
                {
                    await fileBufferingWriteStream.DrainBufferAsync(response.Body);
                }
            }
            finally
            {
                if (fileBufferingWriteStream != null)
                {
                    await fileBufferingWriteStream.DisposeAsync();
                }
            }
        }
Esempio n. 4
0
    public virtual async Task ExecuteAsync(ActionContext context, ViewComponentResult result)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (result == null)
        {
            throw new ArgumentNullException(nameof(result));
        }

        var response = context.HttpContext.Response;

        var viewData = result.ViewData;

        if (viewData == null)
        {
            viewData = new ViewDataDictionary(_modelMetadataProvider, context.ModelState);
        }

        var tempData = result.TempData;

        if (tempData == null)
        {
            tempData = _tempDataDictionaryFactory.GetTempData(context.HttpContext);
        }

        ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
            result.ContentType,
            response.ContentType,
            (ViewExecutor.DefaultContentType, Encoding.UTF8),
            MediaType.GetEncoding,
            out var resolvedContentType,
            out var resolvedContentTypeEncoding);

        response.ContentType = resolvedContentType;

        if (result.StatusCode != null)
        {
            response.StatusCode = result.StatusCode.Value;
        }

        await using var writer = _writerFactory.CreateWriter(response.Body, resolvedContentTypeEncoding);
        var viewContext = new ViewContext(
            context,
            NullView.Instance,
            viewData,
            tempData,
            writer,
            _htmlHelperOptions);

        OnExecuting(viewContext);

        // IViewComponentHelper is stateful, we want to make sure to retrieve it every time we need it.
        var viewComponentHelper = context.HttpContext.RequestServices.GetRequiredService <IViewComponentHelper>();

        (viewComponentHelper as IViewContextAware)?.Contextualize(viewContext);
        var viewComponentResult = await GetViewComponentResult(viewComponentHelper, _logger, result);

        if (viewComponentResult is ViewBuffer viewBuffer)
        {
            // In the ordinary case, DefaultViewComponentHelper will return an instance of ViewBuffer. We can simply
            // invoke WriteToAsync on it.
            await viewBuffer.WriteToAsync(writer, _htmlEncoder);

            await writer.FlushAsync();
        }
        else
        {
            await using var bufferingStream = new FileBufferingWriteStream();
            await using (var intermediateWriter = _writerFactory.CreateWriter(bufferingStream, resolvedContentTypeEncoding))
            {
                viewComponentResult.WriteTo(intermediateWriter, _htmlEncoder);
            }

            await bufferingStream.DrainBufferAsync(response.Body);
        }
    }
Esempio n. 5
0
        /// <inheritdoc />
        public virtual async Task ExecuteAsync(ActionContext context, ViewComponentResult result)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            var response = context.HttpContext.Response;

            var viewData = result.ViewData;

            if (viewData == null)
            {
                viewData = new ViewDataDictionary(_modelMetadataProvider, context.ModelState);
            }

            var tempData = result.TempData;

            if (tempData == null)
            {
                tempData = _tempDataDictionaryFactory.GetTempData(context.HttpContext);
            }

            ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
                result.ContentType,
                response.ContentType,
                ViewExecutor.DefaultContentType,
                out var resolvedContentType,
                out var resolvedContentTypeEncoding);

            response.ContentType = resolvedContentType;

            if (result.StatusCode != null)
            {
                response.StatusCode = result.StatusCode.Value;
            }

            // Opt into sync IO support until we can work out an alternative https://github.com/aspnet/AspNetCore/issues/6397
            var syncIOFeature = context.HttpContext.Features.Get <Http.Features.IHttpBodyControlFeature>();

            if (syncIOFeature != null)
            {
                syncIOFeature.AllowSynchronousIO = true;
            }

            using (var writer = new HttpResponseStreamWriter(response.Body, resolvedContentTypeEncoding))
            {
                var viewContext = new ViewContext(
                    context,
                    NullView.Instance,
                    viewData,
                    tempData,
                    writer,
                    _htmlHelperOptions);

                OnExecuting(viewContext);

                // IViewComponentHelper is stateful, we want to make sure to retrieve it every time we need it.
                var viewComponentHelper = context.HttpContext.RequestServices.GetRequiredService <IViewComponentHelper>();
                (viewComponentHelper as IViewContextAware)?.Contextualize(viewContext);

                var viewComponentResult = await GetViewComponentResult(viewComponentHelper, _logger, result);

                viewComponentResult.WriteTo(writer, _htmlEncoder);
            }
        }
        /// <inheritdoc />
        public virtual async Task ExecuteAsync(ActionContext context, ViewComponentResult result)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            var response = context.HttpContext.Response;

            var viewData = result.ViewData;

            if (viewData == null)
            {
                viewData = new ViewDataDictionary(_modelMetadataProvider, context.ModelState);
            }

            var tempData = result.TempData;

            if (tempData == null)
            {
                tempData = _tempDataDictionaryFactory.GetTempData(context.HttpContext);
            }

            ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
                result.ContentType,
                response.ContentType,
                ViewExecutor.DefaultContentType,
                out var resolvedContentType,
                out var resolvedContentTypeEncoding);

            response.ContentType = resolvedContentType;

            if (result.StatusCode != null)
            {
                response.StatusCode = result.StatusCode.Value;
            }

            using (var writer = new HttpResponseStreamWriter(response.Body, resolvedContentTypeEncoding))
            {
                var viewContext = new ViewContext(
                    context,
                    NullView.Instance,
                    viewData,
                    tempData,
                    writer,
                    _htmlHelperOptions);

                // IViewComponentHelper is stateful, we want to make sure to retrieve it every time we need it.
                var viewComponentHelper = context.HttpContext.RequestServices.GetRequiredService <IViewComponentHelper>();
                (viewComponentHelper as IViewContextAware)?.Contextualize(viewContext);

                var viewComponentResult = await GetViewComponentResult(viewComponentHelper, _logger, result);

                viewComponentResult.WriteTo(writer, _htmlEncoder);
            }
        }
Esempio n. 7
0
        public override Task ExecuteAsync(ActionContext context, JsonResult result)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            var response = context.HttpContext.Response;

            ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
                result.ContentType,
                response.ContentType,
                DefaultContentType,
                out var resolvedContentType,
                out var resolvedContentTypeEncoding);

            response.ContentType = resolvedContentType;

            if (result.Value != null)
            {
                using (var writer = WriterFactory.CreateWriter(response.Body, resolvedContentTypeEncoding))
                {
                    JsonSerializeOption option = null;
                    if (result is JsonResultWrapper wrapper)
                    {
                        option = wrapper.Option;
                    }
                    else
                    {
                        var hosting = context.HttpContext.RequestServices.GetService <JsonSerializeOptionHosting>();
                        if (hosting != null)
                        {
                            option = hosting.Option;
                        }
                    }

                    if (option == null)
                    {
                        option = mvcOptions.JsonSerializeOption;
                    }
                    else
                    {
                        option.Reference(mvcOptions.JsonSerializeOption);
                    }

                    var serializer = new JsonSerializer(option);

                    using (var jsonWriter = new JsonWriter(writer))
                    {
                        serializer.Serialize(result.Value, jsonWriter);
                    }
                }
            }

            return(Task.CompletedTask);
        }
Esempio n. 8
0
        /// <summary>
        /// Executes a view asynchronously.
        /// </summary>
        /// <param name="actionContext">The <see cref="ActionContext"/> associated with the current request.</param>
        /// <param name="view">The <see cref="IView"/>.</param>
        /// <param name="viewData">The <see cref="ViewDataDictionary"/>.</param>
        /// <param name="tempData">The <see cref="ITempDataDictionary"/>.</param>
        /// <param name="contentType">
        /// The content-type header value to set in the response. If <c>null</c>,
        /// <see cref="DefaultContentType"/> will be used.
        /// </param>
        /// <param name="statusCode">
        /// The HTTP status code to set in the response. May be <c>null</c>.
        /// </param>
        /// <returns>A <see cref="Task"/> which will complete when view execution is completed.</returns>
        public virtual async Task ExecuteAsync(
            ActionContext actionContext,
            IView view,
            ViewDataDictionary viewData,
            ITempDataDictionary tempData,
            string contentType,
            int?statusCode)
        {
            if (actionContext == null)
            {
                throw new ArgumentNullException(nameof(actionContext));
            }

            if (view == null)
            {
                throw new ArgumentNullException(nameof(view));
            }

            if (viewData == null)
            {
                viewData = new ViewDataDictionary(_modelMetadataProvider, actionContext.ModelState);
            }

            if (tempData == null)
            {
                tempData = TempDataFactory.GetTempData(actionContext.HttpContext);
            }

            var response = actionContext.HttpContext.Response;

            string   resolvedContentType         = null;
            Encoding resolvedContentTypeEncoding = null;

            ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
                contentType,
                response.ContentType,
                DefaultContentType,
                out resolvedContentType,
                out resolvedContentTypeEncoding);

            response.ContentType = resolvedContentType;

            if (statusCode != null)
            {
                response.StatusCode = statusCode.Value;
            }

            using (var writer = WriterFactory.CreateWriter(response.Body, resolvedContentTypeEncoding))
            {
                var viewContext = new ViewContext(
                    actionContext,
                    view,
                    viewData,
                    tempData,
                    writer,
                    ViewOptions.HtmlHelperOptions);

                DiagnosticSource.BeforeView(view, viewContext);

                await view.RenderAsync(viewContext);

                DiagnosticSource.AfterView(view, viewContext);

                // Perf: Invoke FlushAsync to ensure any buffered content is asynchronously written to the underlying
                // response asynchronously. In the absence of this line, the buffer gets synchronously written to the
                // response as part of the Dispose which has a perf impact.
                await writer.FlushAsync();
            }
        }
Esempio n. 9
0
        public override Task ExecuteAsync(ActionContext context, JsonResult result)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            var serviceProvider = context.HttpContext.RequestServices;
            var response        = context.HttpContext.Response;

            ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
                result.ContentType,
                response.ContentType,
                DefaultContentType,
                out var resolvedContentType,
                out var resolvedContentTypeEncoding);

            response.ContentType = resolvedContentType;

            if (result.Value != null)
            {
                JsonSerializeOption option = null;
                if (result is JsonResultWrapper wrapper)
                {
                    option = wrapper.Option;
                }
                else
                {
                    var hosting = serviceProvider.GetService <JsonSerializeOptionHosting>();
                    if (hosting != null)
                    {
                        option = hosting.Option;
                    }
                }

                if (option == null)
                {
                    option = _mvcOptions.JsonSerializeOption;
                }
                else
                {
                    option.Reference(_mvcOptions.JsonSerializeOption);
                }

                var serializer = serviceProvider.TryGetService <ISerializer>(() => new JsonSerializer(option));

                if (serializer is ITextSerializer txtSerializer)
                {
                    var content = txtSerializer.Serialize(result.Value);
                    response.Body.WriteAsync(resolvedContentTypeEncoding.GetBytes(content));
                }
                else
                {
                    response.Body.WriteAsync(serializer.Serialize(result.Value));
                }
            }

            return(Task.CompletedTask);
        }
Esempio n. 10
0
        /// <inheritdoc />
        public override async Task ExecuteResultAsync(ActionContext context)
        {
            var response = context.HttpContext.Response;
            var services = context.HttpContext.RequestServices;

            var htmlHelperOptions   = services.GetRequiredService <IOptions <MvcViewOptions> >().Value.HtmlHelperOptions;
            var viewComponentHelper = services.GetRequiredService <IViewComponentHelper>();

            var loggerFactory = services.GetRequiredService <ILoggerFactory>();
            var logger        = loggerFactory.CreateLogger <ViewComponentResult>();
            var htmlEncoder   = services.GetRequiredService <HtmlEncoder>();

            var viewData = ViewData;

            if (viewData == null)
            {
                var modelMetadataProvider = services.GetRequiredService <IModelMetadataProvider>();
                viewData = new ViewDataDictionary(modelMetadataProvider, context.ModelState);
            }

            var tempData = TempData;

            if (tempData == null)
            {
                var factory = services.GetRequiredService <ITempDataDictionaryFactory>();
                tempData = factory.GetTempData(context.HttpContext);
            }

            string   resolvedContentType         = null;
            Encoding resolvedContentTypeEncoding = null;

            ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
                ContentType,
                response.ContentType,
                ViewExecutor.DefaultContentType,
                out resolvedContentType,
                out resolvedContentTypeEncoding);

            response.ContentType = resolvedContentType;

            if (StatusCode != null)
            {
                response.StatusCode = StatusCode.Value;
            }

            using (var writer = new HttpResponseStreamWriter(response.Body, resolvedContentTypeEncoding))
            {
                var viewContext = new ViewContext(
                    context,
                    NullView.Instance,
                    viewData,
                    tempData,
                    writer,
                    htmlHelperOptions);

                (viewComponentHelper as ICanHasViewContext)?.Contextualize(viewContext);
                var result = await GetViewComponentResult(viewComponentHelper, logger);

                result.WriteTo(writer, htmlEncoder);
            }
        }