Пример #1
0
        public async Task WriteToStream(object model, HttpResponse response)
        {
            using (var textWriter =
                       new HttpResponseStreamWriter(response.Body, Encoding.UTF8, 1024, _bytePool, _charPool))
                using (var jsonWriter = new JsonTextWriter(textWriter)
                {
                    ArrayPool = _jsonCharPool,
                    CloseOutput = false
                                  //AutoCompleteOnClose = false // TODO -- put this in if we upgrad Newtonsoft
                })
                {
                    var serializer = _serializerPool.Get();

                    try
                    {
                        serializer.Serialize(jsonWriter, model);
                        await textWriter.FlushAsync();
                    }
                    finally
                    {
                        _serializerPool.Return(serializer);
                    }
                }

            response.Headers["content-type"] = ContentType;
        }
Пример #2
0
        private async Task SendResponse(HttpResponse response, Encoding encoding, TResponse message)
        {
            object responseBody = message;

            if (_responseBodyDescriptor != null)
            {
                responseBody = _responseBodyDescriptor.Accessor.GetValue((IMessage)responseBody);
            }

            response.StatusCode  = StatusCodes.Status200OK;
            response.ContentType = "application/json";

            using (var writer = new HttpResponseStreamWriter(response.Body, encoding))
            {
                if (responseBody is IMessage responseMessage)
                {
                    JsonFormatter.Default.Format(responseMessage, writer);
                }
                else
                {
                    JsonFormatter.Default.WriteValue(writer, responseBody);
                }

                // Perf: call FlushAsync to call WriteAsync on the stream with any content left in the TextWriter's
                // buffers. This is better than just letting dispose handle it (which would result in a synchronous
                // write).
                await writer.FlushAsync();
            }
        }
Пример #3
0
 /// <summary>
 /// Writes the result body to the output stream
 /// </summary>
 protected override async Task WriteResultBody(HttpResponse response)
 {
     using (var writer = new HttpResponseStreamWriter(response.Body, Encoding))
     {
         var jsonSerializer = JsonSerializer.Create(JsonSerializerSettings);
         jsonSerializer.Serialize(writer, _result);
         await writer.FlushAsync();
     }
 }
    public async Task NoDataWritten_FlushAsync_DoesNotFlushUnderlyingStream()
    {
        // Arrange
        var stream = new TestMemoryStream();
        var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);

        // Act
        await writer.FlushAsync();

        // Assert
        Assert.Equal(0, stream.FlushAsyncCallCount);
        Assert.Equal(0, stream.Length);
    }
Пример #5
0
 public static async Task WriteResponseBodyAsync(this HttpContext httpContext, object value)
 {
     httpContext.Response.ContentType = "application/json";
     using (var writer = new HttpResponseStreamWriter(httpContext.Response.Body, Encoding.UTF8))
     {
         using (var jsonWriter = new JsonTextWriter(writer)
         {
             CloseOutput = false, AutoCompleteOnClose = false
         })
         {
             JsonSerializer.Serialize(jsonWriter, value);
         }
         await writer.FlushAsync();
     }
 }
Пример #6
0
        /// <inheritdoc />
        public override async Task ExecuteAsync(ApiOperationContext context)
        {
            await base.ExecuteAsync(context);

            var httpContext = context.GetHttpContext();
            var response    = httpContext.Response;

            response.ContentType = this.ContentType;

            using var httpResponseStreamWriter = new HttpResponseStreamWriter(response.Body, Encoding.UTF8);

            await httpResponseStreamWriter.WriteAsync(this._content);

            await httpResponseStreamWriter.FlushAsync();
        }
Пример #7
0
        public async Task WriteAsync(HttpContext httpContext, object value)
        {
            httpContext.Response.ContentType = "application/json";

            using (var writer = new HttpResponseStreamWriter(httpContext.Response.Body, Encoding.UTF8))
            {
                using (var jsonWriter = new JsonTextWriter(writer))
                {
                    var json = new JsonSerializer();

                    json.Serialize(jsonWriter, value);

                    await writer.FlushAsync();
                }
            }
        }
        public static async Task WriteJson <T>(this HttpResponse response, T obj)
        {
            response.ContentType = "application/json";
            using (var writer = new HttpResponseStreamWriter(response.Body, Encoding.UTF8))
            {
                using (var jsonWriter = new JsonTextWriter(writer))
                {
                    jsonWriter.CloseOutput = false;

                    jsonWriter.AutoCompleteOnClose = false;

                    Serializer.Serialize(jsonWriter, obj);
                }

                await writer.FlushAsync();
            }
        }
    public async Task FlushesBuffer_ButNotStream_OnFlushAsync(int byteLength)
    {
        // Arrange
        var stream = new TestMemoryStream();
        var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
        await writer.WriteAsync(new string('a', byteLength));

        var expectedWriteCount = Math.Ceiling((double)byteLength / HttpResponseStreamWriter.DefaultBufferSize);

        // Act
        await writer.FlushAsync();

        // Assert
        Assert.Equal(0, stream.FlushAsyncCallCount);
        Assert.Equal(expectedWriteCount, stream.WriteAsyncCallCount);
        Assert.Equal(byteLength, stream.Length);
    }
Пример #10
0
        public Task WriteJsonToStreamAsync(Stream stream, object value, JsonSerializerSettings jsonSerializerSettings = null)
        {
            var jsonSerializer = jsonSerializerSettings != null
                ? JsonSerializer.Create(jsonSerializerSettings)
                : _jsonSerializer;

            using (var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8))
            {
                using (var jsonWriter = new JsonTextWriter(writer)
                {
                    CloseOutput = false, AutoCompleteOnClose = false
                })
                {
                    jsonSerializer.Serialize(jsonWriter, value);
                }
                return(writer.FlushAsync());
            }
        }
Пример #11
0
        public async Task CopyToAsync(Stream stream, CancellationToken cancellationToken = default)
        {
            using (var sb = new HttpResponseStreamWriter(stream, Encoding.ASCII))
            {
                await sb.WriteAsync("Content-Type: application/http; msgtype=response").ConfigureAwait(false);

                await sb.WriteAsync(Crlf).ConfigureAwait(false);

                await sb.WriteAsync(Crlf).ConfigureAwait(false);

                await sb.WriteAsync(_httpVersion).ConfigureAwait(false);

                await sb.WriteAsync(' ').ConfigureAwait(false);

                // ReSharper disable once ImpureMethodCallOnReadonlyValueField
                await sb.WriteAsync(StatusCode.ToString()).ConfigureAwait(false);

                await sb.WriteAsync(' ').ConfigureAwait(false);

                await sb.WriteAsync(_reasonPhrase).ConfigureAwait(false);

                await sb.WriteAsync(Crlf).ConfigureAwait(false);

                foreach (var header in Headers)
                {
                    await sb.WriteAsync(header.Key).ConfigureAwait(false);

                    await sb.WriteAsync(": ").ConfigureAwait(false);

                    await sb.WriteAsync(header.Value).ConfigureAwait(false);

                    await sb.WriteAsync(Crlf).ConfigureAwait(false);
                }

                await sb.WriteAsync(Crlf).ConfigureAwait(false);

                await sb.FlushAsync().ConfigureAwait(false);
            }

            if (_content != null)
            {
                await _content.CopyToAsync(stream, cancellationToken).ConfigureAwait(false);
            }
        }
Пример #12
0
        /// <summary>
        /// Writes the content to the HTTP response.
        /// </summary>
        /// <param name="httpContext">The <see cref="HttpContext"/> for the current request.</param>
        /// <returns>A task that represents the asynchronous execute operation.</returns>
        async Task IResult.ExecuteAsync(HttpContext httpContext)
        {
            if (httpContext == null)
            {
                throw new ArgumentNullException(nameof(httpContext));
            }

            var response = httpContext.Response;

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

            response.ContentType = resolvedContentType;

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

            var factory = httpContext.RequestServices.GetRequiredService <ILoggerFactory>();
            var logger  = factory.CreateLogger <ContentResult>();

            logger.ContentResultExecuting(resolvedContentType);

            if (Content != null)
            {
                response.ContentLength = resolvedContentTypeEncoding.GetByteCount(Content);

                await using (var textWriter = new HttpResponseStreamWriter(response.Body, resolvedContentTypeEncoding))
                {
                    await textWriter.WriteAsync(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();
                }
            }
        }
    public async Task HttpResponseStreamWriter_WritesDataCorrectly_ForCharactersHavingSurrogatePairs(int characterSize)
    {
        // Arrange
        // Here "𐐀" (called Deseret Long I) actually represents 2 characters. Try to make this character split across
        // the boundary
        var content = new string('a', characterSize - 1) + "𐐀";
        var stream  = new TestMemoryStream();
        var writer  = new HttpResponseStreamWriter(stream, Encoding.Unicode);

        // Act
        await writer.WriteAsync(content);

        await writer.FlushAsync();

        // Assert
        stream.Seek(0, SeekOrigin.Begin);
        var streamReader  = new StreamReader(stream, Encoding.Unicode);
        var actualContent = await streamReader.ReadToEndAsync();

        Assert.Equal(content, actualContent);
    }
    public async Task FlushWriteThrows_DontFlushInDispose(int byteLength)
    {
        // Arrange
        var stream = new TestMemoryStream()
        {
            ThrowOnWrite = true
        };
        var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);

        await writer.WriteAsync(new string('a', byteLength));

        await Assert.ThrowsAsync <IOException>(() => writer.FlushAsync());

        // Act
        writer.Dispose();

        // Assert
        Assert.Equal(1, stream.WriteAsyncCallCount);
        Assert.Equal(0, stream.WriteCallCount);
        Assert.Equal(0, stream.FlushCallCount);
        Assert.Equal(0, stream.FlushAsyncCallCount);
        Assert.Equal(0, stream.Length);
    }
        public async Task NoDataWritten_FlushAsync_DoesNotFlushUnderlyingStream()
        {
            // Arrange
            var stream = new TestMemoryStream();
            var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);

            // Act
            await writer.FlushAsync();

            // Assert
            Assert.Equal(0, stream.FlushAsyncCallCount);
            Assert.Equal(0, stream.Length);
        }
Пример #16
0
        /// <summary>
        /// Asynchronously renders the specified <paramref name="view"/> to the response body.
        /// </summary>
        /// <param name="view">The <see cref="IView"/> to render.</param>
        /// <param name="actionContext">The <see cref="ActionContext"/> for the current executing action.</param>
        /// <param name="viewData">The <see cref="ViewDataDictionary"/> for the view being rendered.</param>
        /// <param name="tempData">The <see cref="ITempDataDictionary"/> for the view being rendered.</param>
        /// <returns>A <see cref="Task"/> that represents the asynchronous rendering.</returns>
        public static async Task ExecuteAsync(
            IView view,
            ActionContext actionContext,
            ViewDataDictionary viewData,
            ITempDataDictionary tempData,
            HtmlHelperOptions htmlHelperOptions,
            MediaTypeHeaderValue contentType)
        {
            if (view == null)
            {
                throw new ArgumentNullException(nameof(view));
            }

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

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

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

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

            var response = actionContext.HttpContext.Response;

            if (contentType != null && contentType.Encoding == null)
            {
                // Do not modify the user supplied content type, so copy it instead
                contentType = contentType.Copy();
                contentType.Encoding = Encoding.UTF8;
            }

            // Priority list for setting content-type:
            //      1. passed in contentType (likely set by the user on the result)
            //      2. response.ContentType (likely set by the user in controller code)
            //      3. ViewExecutor.DefaultContentType (sensible default)
            response.ContentType = contentType?.ToString() ?? response.ContentType ?? DefaultContentType.ToString();

            using (var writer = new HttpResponseStreamWriter(response.Body, contentType?.Encoding ?? DefaultContentType.Encoding))
            {
                var viewContext = new ViewContext(
                    actionContext,
                    view,
                    viewData,
                    tempData,
                    writer,
                    htmlHelperOptions);

                await view.RenderAsync(viewContext);
                // Invoke FlushAsync to ensure any buffered content is asynchronously written to the underlying
                // response. 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();
            }
        }
        public async Task FlushesBuffer_ButNotStream_OnFlushAsync(int byteLength)
        {
            // Arrange
            var stream = new TestMemoryStream();
            var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);
            await writer.WriteAsync(new string('a', byteLength));

            var expectedWriteCount = Math.Ceiling((double)byteLength / HttpResponseStreamWriter.DefaultBufferSize);

            // Act
            await writer.FlushAsync();

            // Assert
            Assert.Equal(0, stream.FlushAsyncCallCount);
            Assert.Equal(expectedWriteCount, stream.WriteAsyncCallCount);
            Assert.Equal(byteLength, stream.Length);
        }
Пример #18
0
        /// <summary>
        /// Asynchronously renders the specified <paramref name="view"/> to the response body.
        /// </summary>
        /// <param name="view">The <see cref="IView"/> to render.</param>
        /// <param name="actionContext">The <see cref="ActionContext"/> for the current executing action.</param>
        /// <param name="viewData">The <see cref="ViewDataDictionary"/> for the view being rendered.</param>
        /// <param name="tempData">The <see cref="ITempDataDictionary"/> for the view being rendered.</param>
        /// <returns>A <see cref="Task"/> that represents the asynchronous rendering.</returns>
        public static async Task ExecuteAsync(
            IView view,
            ActionContext actionContext,
            ViewDataDictionary viewData,
            ITempDataDictionary tempData,
            HtmlHelperOptions htmlHelperOptions,
            MediaTypeHeaderValue contentType)
        {
            if (view == null)
            {
                throw new ArgumentNullException(nameof(view));
            }

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

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

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

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

            var response = actionContext.HttpContext.Response;

            if (contentType != null && contentType.Encoding == null)
            {
                // Do not modify the user supplied content type, so copy it instead
                contentType          = contentType.Copy();
                contentType.Encoding = Encoding.UTF8;
            }

            // Priority list for setting content-type:
            //      1. passed in contentType (likely set by the user on the result)
            //      2. response.ContentType (likely set by the user in controller code)
            //      3. ViewExecutor.DefaultContentType (sensible default)
            response.ContentType = contentType?.ToString() ?? response.ContentType ?? DefaultContentType.ToString();

            using (var writer = new HttpResponseStreamWriter(response.Body, contentType?.Encoding ?? DefaultContentType.Encoding))
            {
                var viewContext = new ViewContext(
                    actionContext,
                    view,
                    viewData,
                    tempData,
                    writer,
                    htmlHelperOptions);

                await view.RenderAsync(viewContext);

                // Invoke FlushAsync to ensure any buffered content is asynchronously written to the underlying
                // response. 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();
            }
        }
        public async Task FlushWriteThrows_DontFlushInDispose(int byteLength)
        {
            // Arrange
            var stream = new TestMemoryStream() { ThrowOnWrite = true };
            var writer = new HttpResponseStreamWriter(stream, Encoding.UTF8);

            await writer.WriteAsync(new string('a', byteLength));
            await Assert.ThrowsAsync<IOException>(() =>  writer.FlushAsync());

            // Act
            writer.Dispose();

            // Assert
            Assert.Equal(1, stream.WriteAsyncCallCount);
            Assert.Equal(0, stream.WriteCallCount);
            Assert.Equal(0, stream.FlushCallCount);
            Assert.Equal(0, stream.FlushAsyncCallCount);
            Assert.Equal(0, stream.Length);
        }