public async Task WriteAsync_DoesNotWriteNullStrings()
        {
            // Arrange
            Encoding encoding = Encoding.UTF8;
            var memoryStream = new MemoryStream();
            var response = new Mock<HttpResponse>();
            response.SetupProperty<long?>(o => o.ContentLength);
            response.SetupGet(r => r.Body).Returns(memoryStream);
            var httpContext = new Mock<HttpContext>();
            httpContext.Setup(o => o.Response).Returns(response.Object);

            var formatter = new StringOutputFormatter();
            var context = new OutputFormatterWriteContext(
                httpContext.Object,
                new TestHttpResponseStreamWriterFactory().CreateWriter,
                typeof(string),
                @object: null);

            // Act
            await formatter.WriteResponseBodyAsync(context);

            // Assert
            Assert.Equal(0, memoryStream.Length);
            response.VerifySet(r => r.ContentLength = It.IsAny<long?>(), Times.Never());
        }
        public void CanWriteResult_ReturnsTrueForStringTypes(
            object value,
            bool useDeclaredTypeAsString,
            bool expectedCanWriteResult)
        {
            // Arrange
            var expectedContentType = expectedCanWriteResult ? 
                MediaTypeHeaderValue.Parse("text/plain") :
                MediaTypeHeaderValue.Parse("application/json");

            var formatter = new StringOutputFormatter();
            var type = useDeclaredTypeAsString ? typeof(string) : typeof(object);

            var context = new OutputFormatterWriteContext(
                new DefaultHttpContext(),
                new TestHttpResponseStreamWriterFactory().CreateWriter,
                type,
                value);
            context.ContentType = MediaTypeHeaderValue.Parse("application/json");

            // Act
            var result = formatter.CanWriteResult(context);

            // Assert
            Assert.Equal(expectedCanWriteResult, result);
            Assert.Equal(expectedContentType, context.ContentType);
        }
예제 #3
0
        public void CanWriteResult_ByDefault_ReturnsTrue_IfTheValueIsNull(
            object value,
            bool declaredTypeAsString,
            bool expected,
            bool useNonNullContentType)
        {
            // Arrange
            var type = declaredTypeAsString ? typeof(string) : typeof(object);
            var contentType = useNonNullContentType ? MediaTypeHeaderValue.Parse("text/plain") : null;

            var context = new OutputFormatterWriteContext(
                new DefaultHttpContext(),
                new TestHttpResponseStreamWriterFactory().CreateWriter,
                type,
                value)
            {
                ContentType = contentType,
            };

            var formatter = new HttpNoContentOutputFormatter();

            // Act
            var result = formatter.CanWriteResult(context);

            // Assert
            Assert.Equal(expected, result);
        }
        public void SelectFormatter_WithNoProvidedContentType_DoesConneg()
        {
            // Arrange
            var executor = CreateExecutor();

            var formatters = new List<IOutputFormatter>
            {
                new TestXmlOutputFormatter(),
                new TestJsonOutputFormatter(), // This will be chosen based on the accept header
            };

            var context = new OutputFormatterWriteContext(
                new DefaultHttpContext(),
                new TestHttpResponseStreamWriterFactory().CreateWriter,
                objectType: null,
                @object: null);

            context.HttpContext.Request.Headers[HeaderNames.Accept] = "application/json";

            // Act
            var formatter = executor.SelectFormatter(
                context,
                new[] { new MediaTypeHeaderValue("application/json") },
                formatters);

            // Assert
            Assert.Same(formatters[1], formatter);
            Assert.Equal(new MediaTypeHeaderValue("application/json"), context.ContentType);
        }
예제 #5
0
        public void SelectResponseCharacterEncoding_SelectsEncoding(
            string acceptCharsetHeaders,
            string[] supportedEncodings,
            string expectedEncoding)
        {
            // Arrange
            var httpContext = new Mock<HttpContext>();
            var httpRequest = new DefaultHttpContext().Request;
            httpRequest.Headers[HeaderNames.AcceptCharset] = acceptCharsetHeaders;
            httpRequest.Headers[HeaderNames.Accept] = "application/acceptCharset";
            httpContext.SetupGet(o => o.Request).Returns(httpRequest);

            var formatter = new TestOutputFormatter();
            foreach (string supportedEncoding in supportedEncodings)
            {
                formatter.SupportedEncodings.Add(Encoding.GetEncoding(supportedEncoding));
            }

            var context = new OutputFormatterWriteContext(
                httpContext.Object,
                new TestHttpResponseStreamWriterFactory().CreateWriter,
                typeof(string),
                "someValue")
            {
                ContentType = MediaTypeHeaderValue.Parse(httpRequest.Headers[HeaderNames.Accept]),
            };

            // Act
            var actualEncoding = formatter.SelectCharacterEncoding(context);

            // Assert
            Assert.Equal(Encoding.GetEncoding(expectedEncoding), actualEncoding);
        }
 public static void FormatterSelected(
     this ILogger logger,
     IOutputFormatter outputFormatter,
     OutputFormatterWriteContext context)
 {
     var contentType = Convert.ToString(context.ContentType);
     _formatterSelected(logger, outputFormatter, contentType, null);
 }
        public async Task WriteAsync(OutputFormatterWriteContext context)
        {
            var response = context.HttpContext.Response;

            var responseMessage = context.Object as HttpResponseMessage;
            if (responseMessage == null)
            {
                var message = Resources.FormatHttpResponseMessageFormatter_UnsupportedType(
                    nameof(HttpResponseMessageOutputFormatter),
                    nameof(HttpResponseMessage));

                throw new InvalidOperationException(message);
            }

            using (responseMessage)
            {
                response.StatusCode = (int)responseMessage.StatusCode;

                var responseFeature = context.HttpContext.Features.Get<IHttpResponseFeature>();
                if (responseFeature != null)
                {
                    responseFeature.ReasonPhrase = responseMessage.ReasonPhrase;
                }

                var responseHeaders = responseMessage.Headers;

                // Ignore the Transfer-Encoding header if it is just "chunked".
                // We let the host decide about whether the response should be chunked or not.
                if (responseHeaders.TransferEncodingChunked == true &&
                    responseHeaders.TransferEncoding.Count == 1)
                {
                    responseHeaders.TransferEncoding.Clear();
                }
                
                foreach (var header in responseHeaders)
                {
                    response.Headers.Append(header.Key, header.Value.ToArray());
                }

                if (responseMessage.Content != null)
                {
                    var contentHeaders = responseMessage.Content.Headers;
                    
                    // Copy the response content headers only after ensuring they are complete.
                    // We ask for Content-Length first because HttpContent lazily computes this
                    // and only afterwards writes the value into the content headers.
                    var unused = contentHeaders.ContentLength;
                    
                    foreach (var header in contentHeaders)
                    {
                        response.Headers.Append(header.Key, header.Value.ToArray());
                    }

                    await responseMessage.Content.CopyToAsync(response.Body);
                }
            }
        }
        /// <inheritdoc />
        public Task WriteAsync(OutputFormatterWriteContext context)
        {
            var response = context.HttpContext.Response;
            response.ContentLength = 0;

            if (response.StatusCode == StatusCodes.Status200OK)
            {
                response.StatusCode = StatusCodes.Status204NoContent;
            }

            return Task.FromResult(true);
        }
        public override void WriteResponseHeaders(OutputFormatterWriteContext context)
        {
            var model = (QuerySummary)context.Object;
            var headers = context.HttpContext.Response.Headers;

            string paginationString = String.Join(",", 
                model.Page.ToString(), 
                model.PageSize.ToString(), 
                model.Total.ToString());

            headers.Add("X-Pagination", paginationString);
        }
예제 #10
0
        public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
        {
            var contact = (Contact)context.Object;

            var builder = new StringBuilder();
            builder.AppendLine("BEGIN:VCARD");
            builder.AppendFormat("FN:{0}", contact.Name);
            builder.AppendLine();
            builder.AppendLine("END:VCARD");

            await context.HttpContext.Response.WriteAsync(
                builder.ToString(),
                context.ContentType?.Encoding ?? Encoding.UTF8);
        }
        public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
        {
            var model = (QuerySummary)context.Object;
            var response = context.HttpContext.Response;

            using (var csv = new StringWriter())
            {
                foreach (string id in model.IDs)
                {
                    csv.WriteLine(id);
                }
                response.WriteAsync(csv.ToString());
            }

            return Task.FromResult(response);
        }
예제 #12
0
        public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var valueAsString = (string)context.Object;
            if (string.IsNullOrEmpty(valueAsString))
            {
                return TaskCache.CompletedTask;
            }

            var response = context.HttpContext.Response;

            return response.WriteAsync(valueAsString, context.ContentType?.Encoding ?? Encoding.UTF8);
        }
        public async Task WriteAsync_Sets406NotAcceptable()
        {
            // Arrange
            var formatter = new HttpNotAcceptableOutputFormatter();

            var context = new OutputFormatterWriteContext(
                new DefaultHttpContext(),
                new TestHttpResponseStreamWriterFactory().CreateWriter,
                objectType: null,
                @object: null);

            // Act
             await formatter.WriteAsync(context);

            // Assert
            Assert.Equal(StatusCodes.Status406NotAcceptable, context.HttpContext.Response.StatusCode);
        }
예제 #14
0
        public void CanWriteResult_OnlyActsOnStreams(Type type)
        {
            // Arrange
            var formatter = new StreamOutputFormatter();
            var @object = type != null ? Activator.CreateInstance(type) : null;

            var context = new OutputFormatterWriteContext(
                new DefaultHttpContext(),
                new TestHttpResponseStreamWriterFactory().CreateWriter,
                type,
                @object);

            // Act
            var result = formatter.CanWriteResult(context);

            // Assert
            Assert.False(result);
        }
        public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
        {
            if (context == null)
                throw new ArgumentNullException(nameof(context));

            var response = context.HttpContext.Response;
            var encoding = context.ContentType?.Encoding ?? Encoding.UTF8;

            var o = context.Object as StandardResponse;
            var standard = o ?? StandardResponse.Create(context.Object);

            return Task.Run(() =>
            {
                using (var stream = new HttpResponseStreamWriter(response.Body, encoding))
                {
                    WriteObject(stream, standard);
                }
            });
        }
예제 #16
0
        public void CanWriteResult_ReturnsTrue_IfReturnTypeIsVoidOrTask(Type declaredType)
        {
            // Arrange
            var context = new OutputFormatterWriteContext(
                new DefaultHttpContext(),
                new TestHttpResponseStreamWriterFactory().CreateWriter,
                declaredType,
                "Something non null.")
            {
                ContentType = MediaTypeHeaderValue.Parse("text/plain"),
            };

            var formatter = new HttpNoContentOutputFormatter();

            // Act
            var result = formatter.CanWriteResult(context);

            // Assert
            Assert.True(result);
        }
        public void CanWriteResult_ReturnsTrue_WhenConnegHasFailed()
        {
            // Arrange
            var formatter = new HttpNotAcceptableOutputFormatter();

            var context = new OutputFormatterWriteContext(
                new DefaultHttpContext(),
                new TestHttpResponseStreamWriterFactory().CreateWriter,
                objectType: null,
                @object: null)
            {
                FailedContentNegotiation = true,
            };

            // Act
            var result = formatter.CanWriteResult(context);

            // Assert
            Assert.True(result);
        }
        public async Task WriteAsync(OutputFormatterWriteContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var response = context.HttpContext.Response;
            var selectedEncoding = Encoding.UTF8;

            using (var writer = context.WriterFactory(response.Body, selectedEncoding))
            {
                var requestUri = context.HttpContext.Request.Scheme + "://" + context.HttpContext.Request.Host.ToUriComponent() + context.HttpContext.Request.Path;
                writer.Write(_serializer.Serialize(context.Object as ResourceResult, requestUri));

                // 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();
            }
        }
예제 #19
0
        public void CanWriteResult_ReturnsTrue_ForStreams(Type type, string contentType)
        {
            // Arrange
            var formatter = new StreamOutputFormatter();
            var contentTypeHeader = contentType == null ? null : new MediaTypeHeaderValue(contentType);

            var context = new OutputFormatterWriteContext(
                new DefaultHttpContext(),
                new TestHttpResponseStreamWriterFactory().CreateWriter,
                type,
                new MemoryStream())
            {
                ContentType = contentTypeHeader,
            };

            // Act
            var canWrite = formatter.CanWriteResult(context);

            // Assert
            Assert.True(canWrite);
        }
예제 #20
0
        public void CanWriteResult_OnlyActsOnStreams_IgnoringContentType(Type type, string contentType)
        {
            // Arrange
            var formatter = new StreamOutputFormatter();
            var contentTypeHeader = contentType == null ? null : new MediaTypeHeaderValue(contentType);

            var context = new OutputFormatterWriteContext(
                new DefaultHttpContext(),
                new TestHttpResponseStreamWriterFactory().CreateWriter,
                type,
                new SimplePOCO())
            {
                ContentType = contentTypeHeader,
            };

            // Act
            var canWrite = formatter.CanWriteResult(context);

            // Assert
            Assert.False(canWrite);
        }
예제 #21
0
        /// <inheritdoc />
        public async Task WriteAsync(OutputFormatterWriteContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            using (var valueAsStream = ((Stream)context.Object))
            {
                var response = context.HttpContext.Response;

                if (context.ContentType != null)
                {
                    response.ContentType = context.ContentType.ToString();
                }

                var bufferingFeature = context.HttpContext.Features.Get<IHttpBufferingFeature>();
                bufferingFeature?.DisableResponseBuffering();

                await valueAsStream.CopyToAsync(response.Body);
            }
        }
        /// <inheritdoc />
        public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var response = context.HttpContext.Response;

            var writerSettings = WriterSettings.Clone();
            writerSettings.Encoding = context.ContentType.Encoding ?? Encoding.UTF8;

            // Wrap the object only if there is a wrapping type.
            var value = context.Object;
            var wrappingType = GetSerializableType(context.ObjectType);
            if (wrappingType != null && wrappingType != context.ObjectType)
            {
                var wrapperProvider = WrapperProviderFactories.GetWrapperProvider(new WrapperProviderContext(
                    declaredType: context.ObjectType,
                    isSerialization: true));

                value = wrapperProvider.Wrap(value);
            }

            var xmlSerializer = GetCachedSerializer(wrappingType);

            using (var textWriter = context.WriterFactory(context.HttpContext.Response.Body, writerSettings.Encoding))
            {
                using (var xmlWriter = CreateXmlWriter(textWriter, writerSettings))
                {
                    xmlSerializer.Serialize(xmlWriter, value);
                }

                // 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 textWriter.FlushAsync();
            }
        }
 public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
 {
     throw new NotImplementedException();
 }
예제 #24
0
 /// <summary>
 /// Writes the response body.
 /// </summary>
 /// <param name="context">The formatter context associated with the call.</param>
 /// <returns>A task which can write the response body.</returns>
 public abstract Task WriteResponseBodyAsync(OutputFormatterWriteContext context);
예제 #25
0
        /// <summary>
        /// Sets the headers on <see cref="Microsoft.AspNet.Http.HttpResponse"/> object.
        /// </summary>
        /// <param name="context">The formatter context associated with the call.</param>
        public virtual void WriteResponseHeaders(OutputFormatterWriteContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var response = context.HttpContext.Response;
            response.ContentType = context.ContentType?.ToString();
        }
예제 #26
0
        /// <inheritdoc />
        public Task WriteAsync(OutputFormatterWriteContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var selectedMediaType = context.ContentType;
            if (selectedMediaType == null)
            {
                // If content type is not set then set it based on supported media types.
                if (SupportedEncodings.Count > 0)
                {
                    selectedMediaType = SupportedMediaTypes[0];
                }
                else
                {
                    throw new InvalidOperationException(Resources.FormatOutputFormatterNoMediaType(GetType().FullName));
                }
            }

            // Copy the media type as it may be a 'frozen' instance.
            selectedMediaType = selectedMediaType.Copy();

            // Note: Text-based media types will use an encoding/charset - binary formats just ignore it. We want to
            // make this class work with media types that use encodings, and those that don't.
            //
            // The default implementation of SelectCharacterEncoding will read from the list of SupportedEncodings
            // and will always choose a default encoding if any are supported. So, the only cases where the
            // selectedEncoding can be null are:
            //
            // 1). No supported encodings - we assume this is a non-text format
            // 2). Custom implementation of SelectCharacterEncoding - trust the user and give them what they want.
            var selectedEncoding = SelectCharacterEncoding(context);
            if (selectedEncoding != null)
            {
                // Override the content type value even if one already existed.
                selectedMediaType.Encoding = selectedEncoding;
            }

            context.ContentType = selectedMediaType;

            WriteResponseHeaders(context);
            return WriteResponseBodyAsync(context);
        }
예제 #27
0
        /// <summary>
        /// Determines the best <see cref="Encoding"/> amongst the supported encodings
        /// for reading or writing an HTTP entity body based on the provided <paramref name="contentTypeHeader"/>.
        /// </summary>
        /// <param name="context">The formatter context associated with the call.
        /// </param>
        /// <returns>The <see cref="Encoding"/> to use when reading the request or writing the response.</returns>
        public virtual Encoding SelectCharacterEncoding(OutputFormatterWriteContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var request = context.HttpContext.Request;
            var encoding = MatchAcceptCharacterEncoding(request.GetTypedHeaders().AcceptCharset);
            if (encoding != null)
            {
                return encoding;
            }

            var charset = context.ContentType?.Charset;
            if (charset != null)
            {
                for (var i = 0; i < SupportedEncodings.Count; i++)
                {
                    if (string.Equals(charset, SupportedEncodings[i].WebName, StringComparison.OrdinalIgnoreCase))
                    {
                        // This is supported.
                        return context.ContentType.Encoding;
                    }
                }
            }

            // A formatter for a non-text media-type won't have any supported encodings.
            return SupportedEncodings.Count > 0 ? SupportedEncodings[0] : null;
        }
예제 #28
0
 public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
 {
     throw new NotImplementedException();
 }
예제 #29
0
 public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
 {
     return(Task.FromResult(true));
 }
        /// <inheritdoc />
        public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var response = context.HttpContext.Response;

            var writerSettings = WriterSettings.Clone();
            writerSettings.Encoding = context.ContentType.Encoding ?? Encoding.UTF8;

            // Wrap the object only if there is a wrapping type.
            var value = context.Object;
            var wrappingType = GetSerializableType(context.ObjectType);
            if (wrappingType != null && wrappingType != context.ObjectType)
            {
                var wrapperProvider = WrapperProviderFactories.GetWrapperProvider(new WrapperProviderContext(
                    declaredType: context.ObjectType,
                    isSerialization: true));

                value = wrapperProvider.Wrap(value);
            }

            var xmlSerializer = GetCachedSerializer(wrappingType);

            using (var textWriter = context.WriterFactory(context.HttpContext.Response.Body, writerSettings.Encoding))
            {
                using (var xmlWriter = CreateXmlWriter(textWriter, writerSettings))
                {
                    xmlSerializer.Serialize(xmlWriter, value);
                }
            }

            return TaskCache.CompletedTask;
        }
        public async Task WriteToStreamAsync_UsesCorrectCharacterEncoding(
            string content,
            string encodingAsString,
            bool isDefaultEncoding)
        {
            // Arrange
            var formatter = new JsonOutputFormatter();
            var formattedContent = "\"" + content + "\"";
            var mediaType = MediaTypeHeaderValue.Parse(string.Format("application/json; charset={0}", encodingAsString));
            var encoding = CreateOrGetSupportedEncoding(formatter, encodingAsString, isDefaultEncoding);
            var expectedData = encoding.GetBytes(formattedContent);


            var body = new MemoryStream();
            var actionContext = GetActionContext(mediaType, body);

            var outputFormatterContext = new OutputFormatterWriteContext(
                actionContext.HttpContext,
                new TestHttpResponseStreamWriterFactory().CreateWriter,
                typeof(string),
                content)
            {
                ContentType = mediaType,
            };

            // Act
            await formatter.WriteResponseBodyAsync(outputFormatterContext);

            // Assert
            var actualData = body.ToArray();
            Assert.Equal(expectedData, actualData);
        }
예제 #32
0
        public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var response = context.HttpContext.Response;
            var selectedEncoding = context.ContentType?.Encoding ?? Encoding.UTF8;

            using (var writer = context.WriterFactory(response.Body, selectedEncoding))
            {
                WriteObject(writer, context.Object);
            }

            return Task.FromResult(true);
        }
예제 #33
0
 /// <summary>
 /// Writes the response body.
 /// </summary>
 /// <param name="context">The formatter context associated with the call.</param>
 /// <returns>A task which can write the response body.</returns>
 public abstract Task WriteResponseBodyAsync(OutputFormatterWriteContext context);