IIS/Owin 如何在管道中将 IHttpActionResult 转换为 application/json?
How IIS/Owin converts IHttpActionResult to application/json down the pipeline?
我正在探索 IIS/Owin 管道的工作原理。我正在尝试找到 IIS/Owin 使用的 library/method 在管道中将 IHttpActionResult (从控制器返回)转换为正确的内容类型,如请求中存在的 application/json。
控制器 -
[Route("")]
public IHttpActionResult Get()
{
IEnumerable<Product> productList = ProductService.GetAllProducts();
if (!productList.Any())
return Ok();
return Json(productList, new JsonSerializerSettings
{
ContractResolver = new WebContractResolver(),
Converters = new List<JsonConverter> { new TrimStringDataConverter() }
});
}
API 消费者收到的数据 -
[
{
"code": "prod101",
"title": "LAPTOP"
},
{
"code": "prod102",
"title": "MOBILE"
}
]
从 IHttpActionResult 到 application/json 的转换何时发生?
IHttpActionResult
有一个方法 ExecuteAsync
其中 returns HttpResponseMessage
public interface IHttpActionResult
{
Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken);
}
当您在控制器中使用 Json()
时,它将创建一个新的 JsonResult
(link)
这是创建 HttpResponseMessage
的方法,它是 json.(link)
public virtual Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Execute());
}
private HttpResponseMessage Execute()
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
try
{
ArraySegment<byte> segment = Serialize();
response.Content = new ByteArrayContent(segment.Array, segment.Offset, segment.Count);
MediaTypeHeaderValue contentType = new MediaTypeHeaderValue("application/json");
contentType.CharSet = _encoding.WebName;
response.Content.Headers.ContentType = contentType;
response.RequestMessage = _dependencies.Request;
}
catch
{
response.Dispose();
throw;
}
return response;
}
在 Owin
中有一个 HttpMessageHandlerAdapter
class 有一个 SendResponseMessageAsync
方法 return HttpResponseMessage
给客户端。这是来自 github 的来源:HttpMessageHandlerAdapter
private Task SendResponseMessageAsync(HttpRequestMessage request, HttpResponseMessage response,
IOwinResponse owinResponse, CancellationToken cancellationToken)
{
owinResponse.StatusCode = (int)response.StatusCode;
owinResponse.ReasonPhrase = response.ReasonPhrase;
// Copy non-content headers
IDictionary<string, string[]> responseHeaders = owinResponse.Headers;
foreach (KeyValuePair<string, IEnumerable<string>> header in response.Headers)
{
responseHeaders[header.Key] = header.Value.AsArray();
}
HttpContent responseContent = response.Content;
if (responseContent == null)
{
SetHeadersForEmptyResponse(responseHeaders);
return TaskHelpers.Completed();
}
else
{
// Copy content headers
foreach (KeyValuePair<string, IEnumerable<string>> contentHeader in responseContent.Headers)
{
responseHeaders[contentHeader.Key] = contentHeader.Value.AsArray();
}
// Copy body
return SendResponseContentAsync(request, response, owinResponse, cancellationToken);
}
}
我正在探索 IIS/Owin 管道的工作原理。我正在尝试找到 IIS/Owin 使用的 library/method 在管道中将 IHttpActionResult (从控制器返回)转换为正确的内容类型,如请求中存在的 application/json。
控制器 -
[Route("")]
public IHttpActionResult Get()
{
IEnumerable<Product> productList = ProductService.GetAllProducts();
if (!productList.Any())
return Ok();
return Json(productList, new JsonSerializerSettings
{
ContractResolver = new WebContractResolver(),
Converters = new List<JsonConverter> { new TrimStringDataConverter() }
});
}
API 消费者收到的数据 -
[
{
"code": "prod101",
"title": "LAPTOP"
},
{
"code": "prod102",
"title": "MOBILE"
}
]
从 IHttpActionResult 到 application/json 的转换何时发生?
IHttpActionResult
有一个方法 ExecuteAsync
其中 returns HttpResponseMessage
public interface IHttpActionResult
{
Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken);
}
当您在控制器中使用 Json()
时,它将创建一个新的 JsonResult
(link)
这是创建 HttpResponseMessage
的方法,它是 json.(link)
public virtual Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Execute());
}
private HttpResponseMessage Execute()
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
try
{
ArraySegment<byte> segment = Serialize();
response.Content = new ByteArrayContent(segment.Array, segment.Offset, segment.Count);
MediaTypeHeaderValue contentType = new MediaTypeHeaderValue("application/json");
contentType.CharSet = _encoding.WebName;
response.Content.Headers.ContentType = contentType;
response.RequestMessage = _dependencies.Request;
}
catch
{
response.Dispose();
throw;
}
return response;
}
在 Owin
中有一个 HttpMessageHandlerAdapter
class 有一个 SendResponseMessageAsync
方法 return HttpResponseMessage
给客户端。这是来自 github 的来源:HttpMessageHandlerAdapter
private Task SendResponseMessageAsync(HttpRequestMessage request, HttpResponseMessage response,
IOwinResponse owinResponse, CancellationToken cancellationToken)
{
owinResponse.StatusCode = (int)response.StatusCode;
owinResponse.ReasonPhrase = response.ReasonPhrase;
// Copy non-content headers
IDictionary<string, string[]> responseHeaders = owinResponse.Headers;
foreach (KeyValuePair<string, IEnumerable<string>> header in response.Headers)
{
responseHeaders[header.Key] = header.Value.AsArray();
}
HttpContent responseContent = response.Content;
if (responseContent == null)
{
SetHeadersForEmptyResponse(responseHeaders);
return TaskHelpers.Completed();
}
else
{
// Copy content headers
foreach (KeyValuePair<string, IEnumerable<string>> contentHeader in responseContent.Headers)
{
responseHeaders[contentHeader.Key] = contentHeader.Value.AsArray();
}
// Copy body
return SendResponseContentAsync(request, response, owinResponse, cancellationToken);
}
}