Fix issue #1280 - Add HttpResponseMessageFormatter
Adds a formatter that can convert an HttpResponseMessage returned from an action into HttpContext.Response output.
This commit is contained in:
parent
aad3ae42ca
commit
22869b41c0
|
|
@ -0,0 +1,69 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
|
||||||
|
using Microsoft.AspNet.HttpFeature;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.WebApiCompatShim
|
||||||
|
{
|
||||||
|
public class HttpResponseMessageOutputFormatter : IOutputFormatter
|
||||||
|
{
|
||||||
|
public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||||
|
{
|
||||||
|
return context.Object is HttpResponseMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IReadOnlyList<MediaTypeHeaderValue> GetSupportedContentTypes(
|
||||||
|
Type declaredType,
|
||||||
|
Type runtimeType,
|
||||||
|
MediaTypeHeaderValue contentType)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task WriteAsync(OutputFormatterContext context)
|
||||||
|
{
|
||||||
|
var response = context.ActionContext.HttpContext.Response;
|
||||||
|
|
||||||
|
var responseMessage = context.Object as HttpResponseMessage;
|
||||||
|
if (responseMessage == null)
|
||||||
|
{
|
||||||
|
var message = Resources.FormatHttpResponseMessageFormatter_UnsupportedType(
|
||||||
|
nameof(HttpResponseMessageOutputFormatter),
|
||||||
|
nameof(HttpResponseMessage));
|
||||||
|
|
||||||
|
throw new InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
response.StatusCode = (int)responseMessage.StatusCode;
|
||||||
|
|
||||||
|
var responseFeature = context.ActionContext.HttpContext.GetFeature<IHttpResponseFeature>();
|
||||||
|
if (responseFeature != null)
|
||||||
|
{
|
||||||
|
responseFeature.ReasonPhrase = responseMessage.ReasonPhrase;
|
||||||
|
}
|
||||||
|
|
||||||
|
var responseHeaders = responseMessage.Headers;
|
||||||
|
foreach (var header in responseHeaders)
|
||||||
|
{
|
||||||
|
response.Headers.AppendValues(header.Key, header.Value.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseMessage.Content != null)
|
||||||
|
{
|
||||||
|
var contentHeaders = responseMessage.Content.Headers;
|
||||||
|
foreach (var header in contentHeaders)
|
||||||
|
{
|
||||||
|
response.Headers.AppendValues(header.Key, header.Value.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
await responseMessage.Content.CopyToAsync(response.Body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,22 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShim
|
||||||
private static readonly ResourceManager _resourceManager
|
private static readonly ResourceManager _resourceManager
|
||||||
= new ResourceManager("Microsoft.AspNet.Mvc.WebApiCompatShim.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
= new ResourceManager("Microsoft.AspNet.Mvc.WebApiCompatShim.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The {0} only supports writing objects of type {1}.
|
||||||
|
/// </summary>
|
||||||
|
internal static string HttpResponseMessageFormatter_UnsupportedType
|
||||||
|
{
|
||||||
|
get { return GetString("HttpResponseMessageFormatter_UnsupportedType"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The {0} only supports writing objects of type {1}.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatHttpResponseMessageFormatter_UnsupportedType(object p0, object p1)
|
||||||
|
{
|
||||||
|
return string.Format(CultureInfo.CurrentCulture, GetString("HttpResponseMessageFormatter_UnsupportedType"), p0, p1);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The key is invalid JQuery syntax because it is missing a closing bracket.
|
/// The key is invalid JQuery syntax because it is missing a closing bracket.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,9 @@
|
||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
|
<data name="HttpResponseMessageFormatter_UnsupportedType" xml:space="preserve">
|
||||||
|
<value>The {0} only supports writing objects of type {1}.</value>
|
||||||
|
</data>
|
||||||
<data name="JQuerySyntaxMissingClosingBracket" xml:space="preserve">
|
<data name="JQuerySyntaxMissingClosingBracket" xml:space="preserve">
|
||||||
<value>The key is invalid JQuery syntax because it is missing a closing bracket.</value>
|
<value>The key is invalid JQuery syntax because it is missing a closing bracket.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,9 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShim
|
||||||
|
|
||||||
// Add a model binder to be able to bind HttpRequestMessage
|
// Add a model binder to be able to bind HttpRequestMessage
|
||||||
options.ModelBinders.Insert(0, new HttpRequestMessageModelBinder());
|
options.ModelBinders.Insert(0, new HttpRequestMessageModelBinder());
|
||||||
|
|
||||||
|
// Add a formatter to write out an HttpResponseMessage to the response
|
||||||
|
options.OutputFormatters.Insert(0, new HttpResponseMessageOutputFormatter());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Invoke(WebApiCompatShimOptions options)
|
public void Invoke(WebApiCompatShimOptions options)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#if ASPNET50
|
#if ASPNET50
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Formatting;
|
using System.Net.Http.Formatting;
|
||||||
|
|
@ -123,6 +124,58 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
Assert.Equal(expected, content);
|
Assert.Equal(expected, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ApiController_ResponseReturned()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var server = TestServer.Create(_provider, _app);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var expected =
|
||||||
|
"POST Hello, HttpResponseMessage world!";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await client.PostAsync(
|
||||||
|
"http://localhost/api/Blog/HttpRequestMessage/EchoWithResponseMessage",
|
||||||
|
new StringContent("Hello, HttpResponseMessage world!"));
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Equal(expected, content);
|
||||||
|
|
||||||
|
IEnumerable<string> values;
|
||||||
|
Assert.True(response.Headers.TryGetValues("X-Test", out values));
|
||||||
|
Assert.Equal(new string[] { "Hello!" }, values);
|
||||||
|
Assert.Equal(38, response.Content.Headers.ContentLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ApiController_ResponseReturned_Chunked()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var server = TestServer.Create(_provider, _app);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var expected =
|
||||||
|
"POST Hello, HttpResponseMessage world!";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await client.PostAsync(
|
||||||
|
"http://localhost/api/Blog/HttpRequestMessage/EchoWithResponseMessageChunked",
|
||||||
|
new StringContent("Hello, HttpResponseMessage world!"));
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Equal(expected, content);
|
||||||
|
|
||||||
|
IEnumerable<string> values;
|
||||||
|
Assert.True(response.Headers.TryGetValues("X-Test", out values));
|
||||||
|
Assert.Equal(new string[] { "Hello!" }, values);
|
||||||
|
Assert.Equal(true, response.Headers.TransferEncodingChunked);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
||||||
using System.Web.Http;
|
using System.Web.Http;
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
using Microsoft.AspNet.Mvc;
|
using Microsoft.AspNet.Mvc;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace WebApiCompatShimWebSite
|
namespace WebApiCompatShimWebSite
|
||||||
{
|
{
|
||||||
|
|
@ -29,6 +30,33 @@ namespace WebApiCompatShimWebSite
|
||||||
return new EmptyResult();
|
return new EmptyResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<HttpResponseMessage> EchoWithResponseMessage(HttpRequestMessage request)
|
||||||
|
{
|
||||||
|
var message = string.Format(
|
||||||
|
"{0} {1}",
|
||||||
|
request.Method.ToString(),
|
||||||
|
await request.Content.ReadAsStringAsync());
|
||||||
|
|
||||||
|
var response = request.CreateResponse(HttpStatusCode.OK);
|
||||||
|
response.Content = new StringContent(message);
|
||||||
|
response.Headers.TryAddWithoutValidation("X-Test", "Hello!");
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<HttpResponseMessage> EchoWithResponseMessageChunked(HttpRequestMessage request)
|
||||||
|
{
|
||||||
|
var message = string.Format(
|
||||||
|
"{0} {1}",
|
||||||
|
request.Method.ToString(),
|
||||||
|
await request.Content.ReadAsStringAsync());
|
||||||
|
|
||||||
|
var response = request.CreateResponse(HttpStatusCode.OK);
|
||||||
|
response.Content = new StringContent(message);
|
||||||
|
response.Headers.TransferEncodingChunked = true;
|
||||||
|
response.Headers.TryAddWithoutValidation("X-Test", "Hello!");
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task Echo(HttpRequestMessage request)
|
private async Task Echo(HttpRequestMessage request)
|
||||||
{
|
{
|
||||||
var message = string.Format(
|
var message = string.Format(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue