이것은 약간 오래된 스레드이지만 여기에 도착한 이후로 다른 사람들을 도울 수 있도록 내 결과를 게시 할 것이라고 생각했습니다.
먼저 Request.Body를 가져 와서 무언가를하고 싶었던 동일한 문제가있었습니다 (로깅 / 감사). 그러나 그렇지 않으면 끝 점이 똑같이 보이기를 원했습니다.
따라서 EnableBuffering () 호출이 트릭을 수행 할 수있는 것 같습니다. 그런 다음 본문에 대해 Seek (0, xxx)를 수행하고 내용을 다시 읽을 수 있습니다.
그러나 이것은 다음 문제로 이어졌습니다. 엔드 포인트에 액세스 할 때 "Synchornous operations are disallowed"예외가 발생합니다. 따라서 해결 방법은 옵션에서 AllowSynchronousIO = true 속성을 설정하는 것입니다. 이를 수행하는 방법에는 여러 가지가 있습니다 (하지만 여기서 자세히 설명하는 것은 중요하지 않습니다.).
그런 다음 다음 문제는 Request.Body를 읽으 러 가면 이미 폐기되었습니다. 으. 그래서, 무엇을 제공합니까?
Endpiont 호출에서 내 [FromBody] 파서로 Newtonsoft.JSON을 사용하고 있습니다. 이것이 동기 읽기를 담당하고 완료되면 스트림을 닫습니다. 해결책? JSON 구문 분석을 시작하기 전에 스트림을 읽으시겠습니까? 물론, 작동하고 나는 이것으로 끝났습니다.
public class ReadRequestBodyIntoItemsAttribute : AuthorizeAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
if (context == null) return;
var syncIOFeature = context.HttpContext.Features.Get<IHttpBodyControlFeature>();
if (syncIOFeature != null)
{
syncIOFeature.AllowSynchronousIO = true;
var req = context.HttpContext.Request;
req.EnableBuffering();
if (req.Body.CanSeek)
{
req.Body.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(
req.Body,
encoding: Encoding.UTF8,
detectEncodingFromByteOrderMarks: false,
bufferSize: 8192,
leaveOpen: true))
{
var jsonString = reader.ReadToEnd();
context.HttpContext.Items.Add("request_body", jsonString);
}
req.Body.Seek(0, SeekOrigin.Begin);
}
}
}
}
이제 [ReadRequestBodyIntoItems] 속성이있는 끝점에서 HttpContext.Items [ "request_body"]를 사용하여 본문에 액세스 할 수 있습니다.
하지만 이건 너무 많은 농구대를 뛰어 넘는 것 같아요. 그래서 여기에서 끝냈고 정말 만족 스럽습니다.
내 끝점은 다음과 같이 시작되었습니다.
[HttpPost("")]
[ReadRequestBodyIntoItems]
[Consumes("application/json")]
public async Task<IActionResult> ReceiveSomeData([FromBody] MyJsonObjectType value)
{
val bodyString = HttpContext.Items["request_body"];
}
그러나 다음과 같이 서명을 변경하는 것이 훨씬 더 간단합니다.
[HttpPost("")]
[Consumes("application/json")]
public async Task<IActionResult> ReceiveSomeData()
{
using (var reader = new StreamReader(
Request.Body,
encoding: Encoding.UTF8,
detectEncodingFromByteOrderMarks: false
))
{
var bodyString = await reader.ReadToEndAsync();
var value = JsonConvert.DeserializeObject<MyJsonObjectType>(bodyString);
}
}
본문 스트림을 한 번만 읽고 역 직렬화를 제어 할 수 있기 때문에 이것을 정말 좋아했습니다. 물론 ASP.NET 코어가이 마법을 사용하는 것이 좋지만 여기서는 스트림을 두 번 읽는 데 시간을 낭비하지 않고 (아마도 매번 버퍼링) 코드가 매우 명확하고 깨끗합니다.
많은 엔드 포인트에서이 기능이 필요한 경우 미들웨어 접근 방식이 더 깨끗할 수도 있고 적어도 본문 추출을 확장 함수로 캡슐화하여 코드를 더 간결하게 만들 수 있습니다.
어쨌든이 문제의 3 가지 측면을 모두 다룬 출처를 찾지 못했기 때문에이 게시물을 작성했습니다. 바라건대 이것은 누군가를 도울 것입니다!
BTW : 이것은 ASP .NET Core 3.1을 사용하고있었습니다.