고객에게 오류를 반환하는 방법에 대해 우려가 있습니다.
오류가 발생 하면 HttpResponseException을 발생시켜 즉시 오류를 반환합니까?
public void Post(Customer customer)
{
if (string.IsNullOrEmpty(customer.Name))
{
throw new HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest)
}
if (customer.Accounts.Count == 0)
{
throw new HttpResponseException("Customer does not have any account", HttpStatusCode.BadRequest)
}
}
또는 모든 오류를 누적 한 다음 클라이언트로 다시 보냅니다.
public void Post(Customer customer)
{
List<string> errors = new List<string>();
if (string.IsNullOrEmpty(customer.Name))
{
errors.Add("Customer Name cannot be empty");
}
if (customer.Accounts.Count == 0)
{
errors.Add("Customer does not have any account");
}
var responseMessage = new HttpResponseMessage<List<string>>(errors, HttpStatusCode.BadRequest);
throw new HttpResponseException(responseMessage);
}
이것은 샘플 코드 일 뿐이며 유효성 검사 오류 또는 서버 오류는 중요하지 않습니다. 각 방법의 우수 사례, 장단점을 알고 싶습니다.
답변
나를 위해 나는 보통을 돌려 보내고 HttpResponseException
예외에 따라 상태 코드를 설정하고 예외가 치명적인지 여부는 HttpResponseException
즉시 다시 보낼지 여부를 결정할 것 입니다.
하루가 끝나면 응답이 아닌 뷰를 다시 보내는 API이므로 예외 및 상태 코드가있는 메시지를 소비자에게 다시 보내는 것이 좋습니다. 현재 대부분의 예외는 일반적으로 잘못된 매개 변수 또는 호출 등으로 인해 오류를 누적하고 다시 보낼 필요가 없습니다.
내 응용 프로그램의 예는 때때로 클라이언트가 데이터를 요구하지만 사용 가능한 데이터가 없으므로 사용자 정의를 던진다는 것입니다 NoDataAvailableException
Web API 앱으로 버블 링하도록 한 다음 사용자 정의 필터에서 올바른 상태 코드와 함께 관련 메시지가 표시됩니다.
나는 이것을 위해 최선의 방법이 무엇인지 100 % 확신하지 못하지만, 이것은 현재 나를 위해 일하고 있기 때문에 내가하고있는 일입니다.
업데이트 :
이 질문에 대답 한 이후 몇 가지 블로그 게시물이 주제에 대해 작성되었습니다.
https://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling
(이것은 야간 빌드에 새로운 기능이 있습니다)
https://docs.microsoft.com/archive/blogs/youssefm/error-handling-in-asp-net-webapi
업데이트 2
오류 처리 프로세스를 업데이트하면 다음 두 가지 경우가 있습니다.
-
찾을 수 없거나 잘못된 매개 변수가 조치로 전달되는 것과 같은 일반적인 오류의 경우
HttpResponseException
처리를 즉시 중지 하기 위해 a 를 리턴 합니다. 또한 액션에서 모델 오류가 발생하면 모델 상태 사전을Request.CreateErrorResponse
확장 프로그램으로 전달하여에 래핑합니다HttpResponseException
. 모델 상태 사전을 추가하면 응답 본문에 전송 된 모델 오류 목록이 생성됩니다. -
상위 계층, 서버 오류에서 발생하는 오류의 경우 예외를 Web API 앱에 적용합니다. 여기서 예외를보고 ELMAH로 기록하고 올바른 HTTP 설정을 이해하려는 전역 예외 필터가 있습니다. 에서 상태 코드 및 관련 오류 메시지를 다시 본문으로 표시합니다
HttpResponseException
. 예외로 인해 클라이언트가 기본 500 내부 서버 오류를받지는 않지만 보안상의 이유로 일반 메시지가 표시 될 것으로 예상됩니다.
업데이트 3
최근에 Web API 2를 가져온 후 일반 오류를 다시 전송하기 위해 IHttpActionResult 인터페이스, 특히 System.Web.Http.Results
NotFound, BadRequest와 같은 네임 스페이스 에 내장 클래스 ( 예 : 확장하지 않은 경우)를 사용합니다. 응답 메시지가있는 NotFound 결과 :
public class NotFoundWithMessageResult : IHttpActionResult
{
private string message;
public NotFoundWithMessageResult(string message)
{
this.message = message;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = new HttpResponseMessage(HttpStatusCode.NotFound);
response.Content = new StringContent(message);
return Task.FromResult(response);
}
}
답변
ASP.NET Web API 2는이를 단순화했습니다. 예를 들어, 다음 코드는
public HttpResponseMessage GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null)
{
var message = string.Format("Product with id = {0} not found", id);
HttpError err = new HttpError(message);
return Request.CreateResponse(HttpStatusCode.NotFound, err);
}
else
{
return Request.CreateResponse(HttpStatusCode.OK, item);
}
}
항목을 찾을 수 없을 때 브라우저에 다음 내용을 반환합니다.
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
Date: Thu, 09 Aug 2012 23:27:18 GMT
Content-Length: 51
{
"Message": "Product with id = 12 not found"
}
제안 : 치명적인 오류 (예 : WCF 오류 예외)가 없으면 HTTP 오류 500을 발생시키지 마십시오. 데이터 상태를 나타내는 적절한 HTTP 상태 코드를 선택하십시오. (아래의 apigee 링크를 참조하십시오.)
연결:
- ASP.NET 웹 API (asp.net) 에서의 예외 처리
- RESTful API 디자인 : 오류는 어떻습니까? (apigee.com)
답변
오류 / 예외보다 유효성 검사에 더 많은 문제가있는 것 같습니다. 둘 다에 대해 조금 말씀 드리겠습니다.
확인
컨트롤러 작업은 일반적으로 모델에서 직접 유효성 검사가 선언 된 입력 모델을 가져와야합니다.
public class Customer
{
[Require]
public string Name { get; set; }
}
그런 다음 ActionFilter
자동으로 유효성 검사 메시지를 클라이언트로 다시 보내는를 사용할 수 있습니다 .
public class ValidationActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var modelState = actionContext.ModelState;
if (!modelState.IsValid) {
actionContext.Response = actionContext.Request
.CreateErrorResponse(HttpStatusCode.BadRequest, modelState);
}
}
}
이에 대한 자세한 내용은 http://ben.onfabrik.com/posts/automatic-modelstate-validation-in-aspnet-mvc를 확인하십시오.
오류 처리
발생한 예외 (관련 상태 코드 포함)를 나타내는 메시지를 클라이언트에 다시 보내는 것이 가장 좋습니다.
Request.CreateErrorResponse(HttpStatusCode, message)
메시지를 지정 하려면 즉시 사용해야 합니다. 그러나 이것은 코드를 Request
객체에 연결하므로 필요하지 않습니다.
나는 일반적으로 클라이언트가 일반적인 500 오류로 다른 모든 것을 처리하고 포장하는 방법을 알 것으로 기대하는 “안전한”예외 유형을 직접 만듭니다.
액션 필터를 사용하여 예외를 처리하는 방법은 다음과 같습니다.
public class ApiExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
var exception = context.Exception as ApiException;
if (exception != null) {
context.Response = context.Request.CreateErrorResponse(exception.StatusCode, exception.Message);
}
}
}
그런 다음 전역으로 등록 할 수 있습니다.
GlobalConfiguration.Configuration.Filters.Add(new ApiExceptionFilterAttribute());
이것이 내 맞춤 예외 유형입니다.
using System;
using System.Net;
namespace WebApi
{
public class ApiException : Exception
{
private readonly HttpStatusCode statusCode;
public ApiException (HttpStatusCode statusCode, string message, Exception ex)
: base(message, ex)
{
this.statusCode = statusCode;
}
public ApiException (HttpStatusCode statusCode, string message)
: base(message)
{
this.statusCode = statusCode;
}
public ApiException (HttpStatusCode statusCode)
{
this.statusCode = statusCode;
}
public HttpStatusCode StatusCode
{
get { return this.statusCode; }
}
}
}
내 API에서 발생할 수있는 예외 예입니다.
public class NotAuthenticatedException : ApiException
{
public NotAuthenticatedException()
: base(HttpStatusCode.Forbidden)
{
}
}
답변
HttpResponseException을 던질 수 있습니다
HttpResponseMessage response =
this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "your message");
throw new HttpResponseException(response);
답변
웹 API 2의 경우 내 메소드는 지속적으로 IHttpActionResult를 반환하므로 다음을 사용합니다.
public IHttpActionResult Save(MyEntity entity)
{
....
return ResponseMessage(
Request.CreateResponse(
HttpStatusCode.BadRequest,
validationErrors));
}
답변
ASP.NET Web API 2를 사용하는 경우 가장 쉬운 방법은 ApiController Short-Method를 사용하는 것입니다. 이로 인해 BadRequestResult가 발생합니다.
return BadRequest("message");
답변
Web Api에서 사용자 정의 ActionFilter를 사용하여 모델을 검증 할 수 있습니다.
public class DRFValidationFilters : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (!actionContext.ModelState.IsValid)
{
actionContext.Response = actionContext.Request
.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
//BadRequest(actionContext.ModelState);
}
}
public override Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
return Task.Factory.StartNew(() => {
if (!actionContext.ModelState.IsValid)
{
actionContext.Response = actionContext.Request
.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
}
});
}
public class AspirantModel
{
public int AspirantId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string AspirantType { get; set; }
[RegularExpression(@"^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$", ErrorMessage = "Not a valid Phone number")]
public string MobileNumber { get; set; }
public int StateId { get; set; }
public int CityId { get; set; }
public int CenterId { get; set; }
}
[HttpPost]
[Route("AspirantCreate")]
[DRFValidationFilters]
public IHttpActionResult Create(AspirantModel aspirant)
{
if (aspirant != null)
{
}
else
{
return Conflict();
}
return Ok();
}
webApiConfig.cs에 CustomAttribute 클래스를 등록하십시오. config.Filters.Add (new DRFValidationFilters ());