의 사용 패턴은 HttpResponseMessage.EnsureSuccessStatusCode()
무엇입니까? 그것은 메시지의 내용을 폐기하고 던진다 HttpRequestException
. 그러나 나는 그것을 제네릭과 다르게 프로그래밍 방식으로 처리하는 방법을 보지 못한다 Exception
. 예를 들어, 그것은 HttpStatusCode
편리했을 것입니다.
더 많은 정보를 얻을 수있는 방법이 있습니까? 누구든지 EnsureSuccessStatusCode()
HttpRequestException과 관련된 사용 패턴을 보여줄 수 있습니까?
답변
의 관용적 사용법은 EnsureSuccessStatusCode
특정 방식으로 실패 사례를 처리하고 싶지 않을 때 요청의 성공을 간결하게 확인하는 것입니다. 이것은 클라이언트의 프로토 타입을 빠르게 만들고 싶을 때 특히 유용합니다.
특정 방식으로 실패 사례를 처리하기로 결정한 경우 다음을 수행하지 마십시오.
var response = await client.GetAsync(...);
try
{
response.EnsureSuccessStatusCode();
// Handle success
}
catch (HttpRequestException)
{
// Handle failure
}
이것은 즉시 그것을 잡기 위해 예외를 던집니다. 이 목적을 위해 의 IsSuccessStatusCode
속성 HttpResponseMessage
이 있습니다. 대신 다음을 수행하십시오.
var response = await client.GetAsync(...);
if (response.IsSuccessStatusCode)
{
// Handle success
}
else
{
// Handle failure
}
답변
나는 의미있는 것을 반환하지 않기 때문에 ensureSuccessStatusCode를 좋아하지 않습니다. 그래서 내 자신의 확장 프로그램을 만들었습니다.
public static class HttpResponseMessageExtensions
{
public static async Task EnsureSuccessStatusCodeAsync(this HttpResponseMessage response)
{
if (response.IsSuccessStatusCode)
{
return;
}
var content = await response.Content.ReadAsStringAsync();
if (response.Content != null)
response.Content.Dispose();
throw new SimpleHttpResponseException(response.StatusCode, content);
}
}
public class SimpleHttpResponseException : Exception
{
public HttpStatusCode StatusCode { get; private set; }
public SimpleHttpResponseException(HttpStatusCode statusCode, string content) : base(content)
{
StatusCode = statusCode;
}
}
Microsoft의 ensureSuccessStatusCode에 대한 소스 코드는 여기 에서 찾을 수 있습니다.
SO 링크를 기반으로 한 동기 버전 :
public static void EnsureSuccessStatusCode(this HttpResponseMessage response)
{
if (response.IsSuccessStatusCode)
{
return;
}
var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
if (response.Content != null)
response.Content.Dispose();
throw new SimpleHttpResponseException(response.StatusCode, content);
}
IsSuccessStatusCode에 대해 내가 싫어하는 점은 “멋지게”재사용 할 수 없다는 것입니다. 예를 들어 polly 와 같은 라이브러리를 사용 하여 네트워크 문제가 발생한 경우 요청을 반복 할 수 있습니다 . 이 경우 polly 또는 다른 라이브러리가 처리 할 수 있도록 예외를 발생시키는 코드가 필요합니다.
답변
동일한 메서드에서 예외를 처리하고 싶지 않을 때 ensureSuccessStatusCode를 사용합니다.
public async Task DoSomethingAsync(User user)
{
try
{
...
var userId = await GetUserIdAsync(user)
...
}
catch(Exception e)
{
throw;
}
}
public async Task GetUserIdAsync(User user)
{
using(var client = new HttpClient())
{
...
response = await client.PostAsync(_url, context);
response.EnsureSuccesStatusCode();
...
}
}
GetUserIdAsync에서 발생한 예외는 DoSomethingAsync에서 처리됩니다.
답변
아래는 제가 제안한 솔루션입니다. 유일한 결점은 ASP.NET Core 프레임 워크 리소스 관리자가 프레임 워크 내부에 있기 때문에 Microsoft의 국제화 된 메시지 문자열을 직접 재사용 할 수 없기 때문에 여기서는 그대로 영어 메시지 리터럴을 사용하고 있다는 것입니다.
장점
- 5xx 서버 오류에 대한 내용을 기록합니다.
- 경우에 따라 서버 오류는 실제로 종료 된 더 이상 사용되지 않는 엔드 포인트를 사용하는 클라이언트와 같이 위장 된 클라이언트 오류입니다.
- 다음을 사용하여 통합 테스트를 작성할 때 오류를 쉽게 발견 할 수 있습니다.
ConfigureTestContainer<T>
단점
- 무능한.
- 응답 내용을 읽고 내용이 너무 길면 클라이언트 속도가 느려집니다. 소프트 실시간 응답 요구 사항이있는 일부 클라이언트의 경우이 지터가 허용되지 않을 수 있습니다.
- 오류 로깅 및 모니터링에 대한 잘못된 책임.
- 이것이 5xx 서버 오류 인 경우 클라이언트가 잘못한 것이 없기 때문에 클라이언트가 신경을 쓰는 이유는 무엇입니까? 그냥 전화 해
response.EnsureSuccessStatusCode();
서버가 처리하도록하십시오. - 내부 서버 오류가있을 때 서버 오류 로그를 확인하는 것이 어떻습니까?
- 이것이 5xx 서버 오류 인 경우 클라이언트가 잘못한 것이 없기 때문에 클라이언트가 신경을 쓰는 이유는 무엇입니까? 그냥 전화 해
Content
상태를 확인하기 전에 속성을 읽어야합니다 . 이것이 바람직하지 않은 상황이있을 수 있으며 그중 하나는 비 효율성입니다.
용법
using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, "controller/action"))
{
using (var response = await HttpClient.SendAsync(requestMessage))
{
var content = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode2(content);
var result = JsonConvert.DeserializeObject<ResponseClass>(content);
}
}
API
public static class HttpResponseMessageExtensions
{
public static void EnsureSuccessStatusCode2(this HttpResponseMessage message, string content = null)
{
if (message.IsSuccessStatusCode)
return;
var contentMessage = string.IsNullOrWhiteSpace(content) ? string.Empty : $"Content: {content}";
throw new HttpRequestException(string.Format(
System.Globalization.CultureInfo.InvariantCulture,
"Response status code does not indicate success: {0} ({1}).{2}",
(int)message.StatusCode,
message.ReasonPhrase,
contentMessage)
);
}
}