-
-
Save jrgcubano/dddcd292639f6be8fa7abfdb588db1e1 to your computer and use it in GitHub Desktop.
ASP.NET WebApi自訂回傳訊息Demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"StatusCode": 200, | |
"Result": { | |
Name = "Wellwind", | |
Age = 30 | |
}, | |
"Error": null | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"StatusCode": 404, | |
"Result": null, | |
"Error": { | |
"ErrorId": "api_doesnt_exist", | |
"Message": "此Api不存在" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ApiResponse | |
{ | |
public HttpStatusCode StatusCode { get; set; } | |
public object Result { get; set; } | |
public object Error { get; set; } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ApiException : Exception | |
{ | |
public string ErrorId { get; set; } | |
public HttpStatusCode StatusCode { get; set; } | |
public ApiException() | |
: this("API呼叫錯誤") | |
{ | |
} | |
public ApiException(string errorMessage) | |
: base(errorMessage) | |
{ | |
ErrorId = "unknown_api_error"; | |
StatusCode = HttpStatusCode.BadRequest; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ApiDoesntExistException : ApiException | |
{ | |
public ApiDoesntExistException() | |
: base("此Api不存在") | |
{ | |
ErrorId = "api_doesnt_exist"; | |
StatusCode = HttpStatusCode.NotFound; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ApiResponseAttribute : ActionFilterAttribute | |
{ | |
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) | |
{ | |
base.OnActionExecuted(actionExecutedContext); | |
if (actionExecutedContext.Exception != null) | |
{ | |
return; | |
} | |
var result = new ApiResponse | |
{ | |
StatusCode = actionExecutedContext.ActionContext.Response.StatusCode, | |
Result = actionExecutedContext.ActionContext.Response.Content.ReadAsAsync().Result }; | |
// 重新封裝回傳格式 | |
actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(result.StatusCode, result); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// add this line to enable custom api response message | |
config.Filters.Add(new ApiResponseAttribute()); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ApiExceptionResponseAttribute : ExceptionFilterAttribute | |
{ | |
/// <param name="actionExecutedContext">動作的內容。</param> | |
public override void OnException(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext) | |
{ | |
base.OnException(actionExecutedContext); | |
// 將錯誤訊息轉成要回傳的ApiResponseResult | |
var errorApiResponseResult = exceptionToApiResponse(actionExecutedContext.Exception); | |
// 重新打包回傳的訊息 | |
actionExecutedContext.Response = | |
actionExecutedContext.Request.CreateResponse(errorApiResponseResult.StatusCode, errorApiResponseResult); | |
} | |
private static ApiResponse exceptionToApiResponse(Exception exception) | |
{ | |
var errorApiResponseResult = new ApiResponse(); | |
if (exception is ApiException) | |
{ | |
var apiException = exception as ApiException; | |
errorApiResponseResult.StatusCode = apiException.StatusCode; | |
errorApiResponseResult.Error = new | |
{ | |
ErrorId = apiException.ErrorId, | |
Message = apiException.Message | |
}; | |
} | |
else | |
{ | |
errorApiResponseResult.StatusCode = HttpStatusCode.BadRequest; | |
errorApiResponseResult.Error = new | |
{ | |
ErrorId = "", | |
Message = exception.Message | |
}; | |
} | |
return errorApiResponseResult; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// add this line to enable custom api response message when exception thrown | |
config.Filters.Add(new ApiExceptionResponseAttribute()); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ExceptionTestController : ApiController | |
{ | |
public object Get() | |
{ | |
throw new Exception("Test Exception Message..."); | |
} | |
public object Post() | |
{ | |
throw new ApiException("Test Api Exception Message..."); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class WebApiApplication : System.Web.HttpApplication | |
{ | |
protected void Application_BeginRequest() | |
{ | |
throw new Exception("thrown by Application_BeginRequest"); | |
} | |
protected void Application_Error() | |
{ | |
var exception = Server.GetLastError(); | |
if (exception == null) | |
{ | |
return; | |
} | |
object exceptionToSerialize = exception.InnerException ?? exception; | |
Response.ContentType = "text/json"; | |
Response.Write( | |
JsonConvert.SerializeObject( | |
ExceptionUtils.ConvertToApiResponse((Exception)exceptionToSerialize))); | |
Response.End(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// HttpNotFound使用自訂Controller的ApiActionSelector | |
/// </summary> | |
public class HttpNotFoundAwareControllerActionSelector : ApiControllerActionSelector | |
{ | |
/// <summary> | |
/// Initializes a new instance of the <see cref="HttpNotFoundAwareControllerActionSelector"/> class. | |
/// </summary> | |
public HttpNotFoundAwareControllerActionSelector() | |
{ | |
} | |
/// <summary> | |
/// 為 <see cref="T:System.Web.Http.Controllers.ApiControllerActionSelector" /> 選取動作。 | |
/// </summary> | |
/// <param name="controllerContext">控制器內容。</param> | |
/// <returns> | |
/// 選取的動作。 | |
/// </returns> | |
public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext) | |
{ | |
HttpActionDescriptor decriptor = null; | |
try | |
{ | |
decriptor = base.SelectAction(controllerContext); | |
} | |
catch (HttpResponseException ex) | |
{ | |
setErrorController(controllerContext, ex); | |
decriptor = base.SelectAction(controllerContext); | |
} | |
return decriptor; | |
} | |
private static void setErrorController(HttpControllerContext controllerContext, HttpResponseException ex) | |
{ | |
var controllerName = "Error404"; | |
var code = ex.Response.StatusCode; | |
var routeValues = controllerContext.RouteData.Values; | |
if (code != HttpStatusCode.NotFound && code != HttpStatusCode.MethodNotAllowed) | |
{ | |
controllerName = "ErrorOthers"; | |
routeValues["id"] = code; | |
} | |
routeValues["action"] = "Get"; | |
controllerContext.Request.Method = HttpMethod.Get; | |
IHttpController httpController = new Error404Controller(); | |
controllerContext.Controller = httpController; | |
controllerContext.ControllerDescriptor = new HttpControllerDescriptor(controllerContext.Configuration, | |
controllerName, httpController.GetType()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// HttpNotFound使用自訂Controller的ControllerSelector | |
/// </summary> | |
public class HttpNotFoundAwareDefaultHttpControllerSelector : DefaultHttpControllerSelector | |
{ | |
/// <summary> | |
/// Initializes a new instance of the <see cref="HttpNotFoundAwareDefaultHttpControllerSelector"/> class. | |
/// </summary> | |
/// <param name="configuration">設定。</param> | |
public HttpNotFoundAwareDefaultHttpControllerSelector(HttpConfiguration configuration) | |
: base(configuration) | |
{ | |
} | |
/// <summary> | |
/// 為指定的 <see cref="T:System.Net.Http.HttpRequestMessage" /> 選取 <see cref="T:System.Web.Http.Controllers.HttpControllerDescriptor" />。 | |
/// </summary> | |
/// <param name="request">HTTP 要求的訊息。</param> | |
/// <returns> | |
/// 指定之 <see cref="T:System.Net.Http.HttpRequestMessage" /> 適用的 <see cref="T:System.Web.Http.Controllers.HttpControllerDescriptor" /> 執行個體。 | |
/// </returns> | |
public override HttpControllerDescriptor SelectController(HttpRequestMessage request) | |
{ | |
HttpControllerDescriptor decriptor = null; | |
try | |
{ | |
decriptor = base.SelectController(request); | |
} | |
catch (HttpResponseException ex) | |
{ | |
setErrorController(request, ex); | |
decriptor = base.SelectController(request); | |
} | |
return decriptor; | |
} | |
private static void setErrorController(HttpRequestMessage request, HttpResponseException ex) | |
{ | |
var code = ex.Response.StatusCode; | |
var routeValues = request.GetRouteData().Values; | |
routeValues["controller"] = "Error"; | |
if (code == HttpStatusCode.NotFound) | |
{ | |
routeValues["controller"] = "Error404"; | |
} | |
else | |
{ | |
routeValues["controller"] = "ErrorOthers"; | |
routeValues["id"] = code; | |
} | |
routeValues["action"] = "Get"; | |
request.Method = HttpMethod.Get; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Error404Controller : ApiController | |
{ | |
public object Get() | |
{ | |
throw new Exception("找不到此API"); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ErrorOthersController : ApiController | |
{ | |
public object Get(int id) | |
{ | |
return new HttpStatusCodeResult(id); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
config.Services.Replace(typeof(IHttpControllerSelector), new HttpNotFoundAwareDefaultHttpControllerSelector(config)); | |
config.Services.Replace(typeof(IHttpActionSelector), new HttpNotFoundAwareControllerActionSelector()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment