參考頁面:
http://www.yuanjiaocheng.net/webapi/create-crud-api-1-delete.html
http://www.yuanjiaocheng.net/webapi/Consume-web-api.html
http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-get.html
http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-post.html
http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-put.html
注:本文是【ASP.NET Web API系列教程】的一部分,如果您是第一次看本系列教程,請先看前面的內容。
本文引自:http://www.asp.net/web-api/overview/web-api-routing-and-actions/exception-handling
By Mike Wasson | March 12, 2012
作者:Mike Wasson | 日期:2012-3-12
This article describes error and exception handling in ASP.NET Web API.
本文描述ASP.NET Web API中的錯誤與異常處理:
What happens if a Web API controller throws an uncaught exception? By default, most exceptions are translated into an HTTP response with status code 500, Internal Server Error.
如果一個Web API控制器拋出一個未捕捉異常,會發生什麼?默認地,大多數異常都會被轉化成一個帶有狀態碼“500 – 內部服務器錯誤”的HTTP響應。
The HttpResponseException type is a special case. This exception returns any HTTP status code that you specify in the exception constructor. For example, the following method returns 404, Not Found, if the id parameter is not valid.
HttpResponseException(HTTP響應異常)類型是一種特殊的情況。這種異常會返回你在異常構造器中指定的任何HTTP狀態碼。例如,在以下方法中,如果id參數非法,會返回“404 — 未找到”。
public Product GetProduct(int id) { Product item = repository.Get(id); if (item == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } return item; }
For more control over the response, you can also construct the entire response message and include it with the HttpResponseException:
為了對響應進行更多控制,你也可以構造整個響應消息,並用HttpResponseException來包含它:
public Product GetProduct(int id) { Product item = repository.Get(id); if (item == null) { var resp = new HttpResponseMessage(HttpStatusCode.NotFound) { Content = new StringContent(string.Format("No product with ID = {0}", id)), ReasonPhrase = "Product ID Not Found" } throw new HttpResponseException(resp); } return item; }
You can customize how Web API handles exceptions by writing an exception filter. An exception filter is executed when a controller method throws any unhandled exception that is not an HttpResponseException exception. The HttpResponseException type is a special case, because it is designed specifically for returning an HTTP response.
通過編寫一個異常過濾器(exception filter),你可以定制Web API如何處理異常。當一個控制器拋出一個非HttpResponseException異常的未處理異常時,會執行一個異常過濾器。HttpResponseException類型一個特殊的情況,因為它是專門設計用來返回一個HTTP響應的。
Exception filters implement the System.Web.Http.Filters.IExceptionFilter interface. The simplest way to write an exception filter is to derive from the System.Web.Http.Filters.ExceptionFilterAttribute class and override the OnException method.
異常過濾器實現System.Web.Http.Filters.IExceptionFilter接口。編寫異常過濾器最簡單的方式是通過System.Web.Http.Filters.ExceptionFilterAttribute類進行派生,並重寫其OnException方法。
Exception filters in ASP.NET Web API are similar to those in ASP.NET MVC. However, they are declared in a separate namespace and function separately. In particular, the HandleErrorAttribute class used in MVC does not handle exceptions thrown by Web API controllers.
ASP.NET Web API中的異常過濾器要比ASP.NET MVC中的簡單些。然而,這兩者是在不同的命名空間中聲明的,且是功能獨立的。特別是MVC中使用的HandleErrorAttribute類不會處理Web API控制器中拋出的異常。
Here is a filter that converts NotImplementedException exceptions into HTTP status code 501, Not Implemented:
以下是將NotImplementedException異常轉換成HTTP狀態碼“501 — 未實現”的一個過濾器:
namespace ProductStore.Filters { using System; using System.Net; using System.Net.Http; using System.Web.Http.Filters; public class NotImplExceptionFilterAttribute : ExceptionFilterAttribute { public override void OnException(HttpActionExecutedContext context) { if (context.Exception is NotImplementedException) { context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented); } } } }
The Response property of the HttpActionExecutedContext object contains the HTTP response message that will be sent to the client.
HttpActionExecutedContext對象的Response屬性含有將發送給客戶端的HTTP響應消息。
There are several ways to register a Web API exception filter:
以下是注冊Web API異常過濾器的幾種方式:
To apply the filter to a specific action, add the filter as an attribute to the action:
要把過濾運用於特定的動作,在動作上添加該過濾器的注解屬性:
public class ProductsController : ApiController { [NotImplExceptionFilter] public Contact GetContact(int id) { throw new NotImplementedException("This method is not implemented"); } }
To apply the filter to all of the actions on a controller, add the filter as an attribute to the controller class:
要把過濾器運用於一個控制器的所有動作,在控制器上添加該過濾器的注解屬性:
[NotImplExceptionFilter] public class ProductsController : ApiController { // ... }
To apply the filter globally to all Web API controllers, add an instance of the filter to the GlobalConfiguration.Configuration.Filters collection. Exeption filters in this collection apply to any Web API controller action.
要全局性地把過濾器運用於所有Web API控制器,將該過濾器的一個實例添加到GlobalConfiguration.Configuration.Filters集合。這個集合中的異常過濾器會運用於任何Web API控制器動作。
GlobalConfiguration.Configuration.Filters.Add( new ProductStore.NotImplExceptionFilterAttribute());
If you use the "ASP.NET MVC 4 Web Application" project template to create your project, put your Web API configuration code inside the WebApiConfig class, which is located in the App_Start folder:
如果用的是“ASP.NET MVC 4 Web應用程序”項目模板創建的項目,要把你的Web API配置代碼被放在WebApiConfig類中,它位於App_Start文件夾:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Filters.Add(new ProductStore.NotImplExceptionFilterAttribute()); // Other configuration code(其它配置代碼)... } }
The HttpError object provides a consistent way to return error information in the response body. The following example shows how to return HTTP status code 404 (Not Found) with an HttpError in the response body:
HttpError對象為在響應體中返回錯誤消息提供了相應的方式。以下示例演示了如何用HttpError在響應體中返回HTTP狀態碼“404 — 未找到”:
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); } }
In this example, if the method is successful, it returns the product in the HTTP response. But if the requested product is not found, the HTTP response contains an HttpError in the request body. The response might look like the following:
在這個例子中,如果該方法成功,它會在HTTP響應中返回產品。但如果所請求的產品未找到,則HTTP響應會在請求體中包含一個HttpError。該響應看上去大致像這樣:
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" }
Notice that the HttpError was serialized to JSON in this example. One advantage of using HttpError is that it goes through the same content-negotiation and serialization process as any other strongly-typed model.
注意,在這個例子中,HttpError會被序列化成JSON。使用HttpError的一個好處是,與其它強類型模型一樣,會進行同樣的“內容協商”(本系列化教程的第6.2小節 — 譯者注)和序列化過程。
Instead of creating the HttpError object directly, you can use the CreateErrorResponse method:
替代直接創建HttpError對象的一種辦法是,你可以使用CreateErrorResponse方法:
public HttpResponseMessage GetProduct(int id) { Product item = repository.Get(id); if (item == null) { var message = string.Format("Product with id = {0} not found", id); return Request.CreateErrorResponse(HttpStatusCode.NotFound, message); } else { return Request.CreateResponse(HttpStatusCode.OK, item); } }
CreateErrorResponse is an extension method defined in the System.Net.Http.HttpRequestMessageExtensions class. Internally, CreateErrorResponse creates an HttpError instance and then creates an HttpResponseMessage that contains the HttpError.
CreateErrorResponse是在System.Net.Http.HttpRequestMessageExtensions類中定義的一個擴展方法。本質上,CreateErrorResponse會創建一個HttpError實例,然後創建一個包含該HttpError的HttpResponseMessage。
For model validation, you can pass the model state to CreateErrorResponse, to include the validation errors in the response:
對於模型驗證,你可以把模型狀態傳遞給CreateErrorResponse,以便在響應中包含驗證錯誤:
public HttpResponseMessage PostProduct(Product item) { if (!ModelState.IsValid) { return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState); } // Implementation not shown(未列出實現代碼)... }
This example might return the following response:
此例可能會返回以下響應:
HTTP/1.1 400 Bad Request Content-Type: application/json; charset=utf-8 Content-Length: 320 { "Message": "The request is invalid.", "ModelState": { "item": [ "Required property 'Name' not found in JSON. Path '', line 1, position 14." ], "item.Name": [ "The Name field is required." ], "item.Price": [ "The field Price must be between 0 and 999." ] } }
For more information about model validation, see Model Validation in ASP.NET Web API.
關於模型驗證的更多信息,參閱“ASP.NET Web API中的模型驗證”(本系列教程的第6.4小節 — 譯者注)。
The HttpError class is actually a key-value collection (it derives from Dictionary<string, object>), so you can add your own key-value pairs:
HttpError類實際上是一個“鍵-值”集合(它派生於Dictionary<string, object>),因此你可以添加自己的“鍵-值”對:
public HttpResponseMessage GetProduct(int id) { Product item = repository.Get(id); if (item == null) { var message = string.Format("Product with id = {0} not found", id); var err = new HttpError(message); err["error_sub_code"] = 42; return Request.CreateErrorResponse(HttpStatusCode.NotFound, err); } else { return Request.CreateResponse(HttpStatusCode.OK, item); } }
The previous examples return an HttpResponseMessage message from the controller action, but you can also use HttpResponseException to return an HttpError. This lets you return a strongly-typed model in the normal success case, while still returning HttpError if there is an error:
前面的例子是從控制器動作返回一個HttpResponseMessage消息,但你也可以使用HttpResponseException來返回一個HttpError。這讓你能夠在正常成功情況下返回強類型模型,而在有錯誤時,仍返回HttpError。
public Product GetProduct(int id) { Product item = repository.Get(id); if (item == null) { var message = string.Format("Product with id = {0} not found", id); throw new HttpResponseException( Request.CreateErrorResponse(HttpStatusCode.NotFound, message)); } else { return item; } }
看完此文如果覺得有所收獲,請給個推薦