Exception Handling in ASP.NET Web API
2013-07-25 13:45
567 查看
publicstaticvoidRegisterGlobalFilters(GlobalFilterCollectionfilters) { filters.Add(newHandleErrorAttribute()); filters.Add(newSystem.Web.Mvc.AuthorizeAttribute()); }
ttributeintheASP.NETWebAPI.
CustomAuthorizeAttribute
inASP.NETWEBAPIyoucanextend"AuthorizeAttribute"toimplementcustomauthorizationfiltertocontroltheaccesstotheapplication.Ihaveoverriddenthe"
OnAuthorization"methodtocheckcustomauthorizationrules.Inthisimplementation,Iamassumingthatuserwillsendandreceivethedatathrough"HTTPheaders".
Followingiscodeexamplehowtoimplementit.
Collapse|
publicclassCustomAuthorize:System.Web.Http.AuthorizeAttribute { publicoverridevoidOnAuthorization( System.Web.Http.Controllers.HttpActionContextactionContext) { base.OnAuthorization(actionContext); if(actionContext.Request.Headers.GetValues("authenticationToken")!=null) { //getvaluefromheader stringauthenticationToken=Convert.ToString( actionContext.Request.Headers.GetValues("authenticationToken").FirstOrDefault()); //authenticationTokenPersistant //itissavedinsomedatastore //iwillcomparetheauthenticationTokensentbyclientwith //authenticationTokenpersistindatabaseagainstspecificuser,andactaccordingly if(authenticationTokenPersistant!=authenticationToken) { HttpContext.Current.Response.AddHeader("authenticationToken",authenticationToken); HttpContext.Current.Response.AddHeader("AuthenticationStatus","NotAuthorized"); actionContext.Response=actionContext.Request.CreateResponse(HttpStatusCode.Forbidden); return; } HttpContext.Current.Response.AddHeader("authenticationToken",authenticationToken); HttpContext.Current.Response.AddHeader("AuthenticationStatus","Authorized"); return; } actionContext.Response= actionContext.Request.CreateResponse(HttpStatusCode.ExpectationFailed); actionContext.Response.ReasonPhrase="Pleaseprovidevalidinputs"; } }
CustomHandleExceptionattribute:
ToimplementcustomHandleExceptionattributeyouneedtoextend"
ExceptionFilterAttribute",andoverride"
OnException"method.
Youcanfindtheexamplebelow:
Collapse|
publicclassHandleExceptionAttribute:ExceptionFilterAttribute { publicoverridevoidOnException(HttpActionExecutedContextactionExecutedContext) { if(actionExecutedContext.Exception!=null) { varexception=actionExecutedContext.Exception; varresponse=newHttpResponseMessage(); response.StatusCode=HttpStatusCode.InternalServerError; response.ReasonPhrase=exception.Message; actionExecutedContext.Result=response; } } }
ThisarticledescribeserrorandexceptionhandlinginASP.NETWebAPI.
HttpResponseException
WhathappensifaWebAPIcontrollerthrowsanuncaughtexception?Bydefault,mostexceptionsaretranslatedintoanHTTPresponsewithstatuscode500,InternalServerError.TheHttpResponseExceptiontypeisaspecialcase.ThisexceptionreturnsanyHTTPstatuscodethatyouspecifyintheexceptionconstructor.Forexample,thefollowingmethodreturns404,NotFound,iftheidparameterisnotvalid.
publicProductGetProduct(intid){Productitem=repository.Get(id);if(item==null){thrownewHttpResponseException(HttpStatusCode.NotFound);}returnitem;}
Formorecontrolovertheresponse,youcanalsoconstructtheentireresponsemessageandincludeitwiththeHttpResponseException:
publicProductGetProduct(intid){Productitem=repository.Get(id);if(item==null){varresp=newHttpResponseMessage(HttpStatusCode.NotFound){Content=newStringContent(string.Format("NoproductwithID={0}",id)),ReasonPhrase="ProductIDNotFound"}thrownewHttpResponseException(resp);}returnitem;}
ExceptionFilters
YoucancustomizehowWebAPIhandlesexceptionsbywritinganexceptionfilter.AnexceptionfilterisexecutedwhenacontrollermethodthrowsanyunhandledexceptionthatisnotanHttpResponseExceptionexception.TheHttpResponseExceptiontypeisaspecialcase,becauseitisdesignedspecificallyforreturninganHTTPresponse.ExceptionfiltersimplementtheSystem.Web.Http.Filters.IExceptionFilterinterface.ThesimplestwaytowriteanexceptionfilteristoderivefromtheSystem.Web.Http.Filters.ExceptionFilterAttributeclassandoverridetheOnExceptionmethod.
ExceptionfiltersinASP.NETWebAPIaresimilartothoseinASP.NETMVC.However,theyaredeclaredinaseparatenamespaceandfunctionseparately.Inparticular,theHandleErrorAttributeclassusedinMVCdoesnothandleexceptionsthrownbyWebAPIcontrollers.
HereisafilterthatconvertsNotImplementedExceptionexceptionsintoHTTPstatuscode501,NotImplemented:
namespaceProductStore.Filters{usingSystem;usingSystem.Net;usingSystem.Net.Http;usingSystem.Web.Http.Filters;publicclassNotImplExceptionFilterAttribute:ExceptionFilterAttribute{publicoverridevoidOnException(HttpActionExecutedContextcontext){if(context.ExceptionisNotImplementedException){
context.Response=newHttpResponseMessage(HttpStatusCode.NotImplemented);}}}}
TheResponsepropertyoftheHttpActionExecutedContextobjectcontainstheHTTPresponsemessagethatwillbesenttotheclient.
RegisteringExceptionFilters
ThereareseveralwaystoregisteraWebAPIexceptionfilter:Byaction
Bycontroller
Globally
Toapplythefiltertoaspecificaction,addthefilterasanattributetotheaction:
publicclassProductsController:ApiController{[NotImplExceptionFilter]publicContactGetContact(intid){thrownewNotImplementedException("Thismethodisnotimplemented");}}
Toapplythefiltertoalloftheactionsonacontroller,addthefilterasanattributetothecontrollerclass:
[NotImplExceptionFilter]publicclassProductsController:ApiController{//...}
ToapplythefiltergloballytoallWebAPIcontrollers,addaninstanceofthefiltertotheGlobalConfiguration.Configuration.Filterscollection.ExeptionfiltersinthiscollectionapplytoanyWebAPIcontrolleraction.
GlobalConfiguration.Configuration.Filters.Add(newProductStore.NotImplExceptionFilterAttribute());
Ifyouusethe"ASP.NETMVC4WebApplication"projecttemplatetocreateyourproject,putyourWebAPIconfigurationcodeinsidethe
WebApiConfigclass,whichislocatedintheApp_Startfolder:
publicstaticclassWebApiConfig{publicstaticvoidRegister(HttpConfigurationconfig){config.Filters.Add(newProductStore.NotImplExceptionFilterAttribute());//Otherconfigurationcode...}}
HttpError
TheHttpErrorobjectprovidesaconsistentwaytoreturnerrorinformationintheresponsebody.ThefollowingexampleshowshowtoreturnHTTPstatuscode404(NotFound)withanHttpErrorintheresponsebody:publicHttpResponseMessageGetProduct(intid){Productitem=repository.Get(id);if(item==null){varmessage=string.Format("Productwithid={0}notfound",id);HttpErrorerr=newHttpError(message);returnRequest.CreateResponse(HttpStatusCode.NotFound,err);}else{returnRequest.CreateResponse(HttpStatusCode.OK,item);}}
Inthisexample,ifthemethodissuccessful,itreturnstheproductintheHTTPresponse.Butiftherequestedproductisnotfound,theHTTPresponsecontainsanHttpErrorintherequestbody.Theresponsemightlooklikethefollowing:
HTTP/1.1404NotFoundContent-Type:application/json;charset=utf-8Date:Thu,09Aug201223:27:18GMT
Content-Length:51{"Message":"Productwithid=12notfound"}
NoticethattheHttpErrorwasserializedtoJSONinthisexample.OneadvantageofusingHttpErroristhatitgoesthroughthesame
InsteadofcreatingtheHttpErrorobjectdirectly,youcanusetheCreateErrorResponsemethod:
publicHttpResponseMessageGetProduct(intid){Productitem=repository.Get(id);if(item==null){varmessage=string.Format("Productwithid={0}notfound",id);returnRequest.CreateErrorResponse(HttpStatusCode.NotFound,message);}else{returnRequest.CreateResponse(HttpStatusCode.OK,item);}}
CreateErrorResponseisanextensionmethoddefinedintheSystem.Net.Http.HttpRequestMessageExtensionsclass.Internally,CreateErrorResponsecreatesanHttpErrorinstanceandthencreatesanHttpResponseMessagethatcontainstheHttpError.
HttpErrorandModelValidation
Formodelvalidation,youcanpassthemodelstatetoCreateErrorResponse,toincludethevalidationerrorsintheresponse:publicHttpResponseMessagePostProduct(Productitem){if(!ModelState.IsValid){returnRequest.CreateErrorResponse(HttpStatusCode.BadRequest,ModelState);}//Implementationnotshown...}
Thisexamplemightreturnthefollowingresponse:
HTTP/1.1400BadRequestContent-Type:application/json;charset=utf-8Content-Length:320{"Message":"Therequestisinvalid.","ModelState":{"item":["Requiredproperty'Name'notfoundinJSON.Path'',line1,position14."],"item.Name":["TheNamefieldisrequired."],"item.Price":["ThefieldPricemustbebetween0and999."]}}
Formoreinformationaboutmodelvalidation,see
AddingCustomKey-ValuestoHttpError
TheHttpErrorclassisactuallyakey-valuecollection(itderivesfromDictionary<string,object>),soyoucanaddyourownkey-valuepairs:publicHttpResponseMessageGetProduct(intid){Productitem=repository.Get(id);if(item==null){varmessage=string.Format("Productwithid={0}notfound",id);varerr=newHttpError(message);err["error_sub_code"]=42;returnRequest.CreateErrorResponse(HttpStatusCode.NotFound,err);}else{returnRequest.CreateResponse(HttpStatusCode.OK,item);}}
UsingHttpErrorwithHttpResponseException
ThepreviousexamplesreturnanHttpResponseMessagemessagefromthecontrolleraction,butyoucanalsouseHttpResponseExceptiontoreturnanHttpError.Thisletsyoureturnastrongly-typedmodelinthenormalsuccesscase,whilestillreturningHttpErrorifthereisanerror:publicProductGetProduct(intid){Productitem=repository.Get(id);if(item==null){varmessage=string.Format("Productwithid={0}notfound",id);thrownewHttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound,message));}else{returnitem;}}
相关文章推荐
- Global exception handling in asp.net core webapi
- Handling HTTP 404 Error in ASP.NET Web API
- Content Negotiation in ASP.NET Web API
- HMAC authentication in ASP.NET Web API
- Exception handling with custom error pages in ASP.NET using C#.
- Adding the Test API in The ASP.NET Web API Help Page
- Simple way to implement caching in ASP.NET Web API
- Tracing in ASP.NET Web API
- Exception Handling in Asp.net MVC
- Log message Request and Response in ASP.NET WebAPI
- Content Negotiation in ASP.NET Web API
- [转]Getting started with ASP.NET Web API OData in 3 simple steps
- Model Validation in ASP.NET Web API
- ASP.NET MVC 4 WebAPI. Support Areas in HttpControllerSelector
- Manual JSON serialization from DataReader in ASP.NET Web API
- File Upload using jQuery AJAX in ASP.NET Web API or Http handler (AJAX上传文件通过Web API或 http handler)
- Model Validation in ASP.NET Web API By Mike Wasson|July 20, 2012 268 of 294 people found this helpful
- ASP.Net Web API 输出缓存 转载 -- Output caching in ASP.NET Web API
- Authentication and Authorization in ASP.NET Web API
- Adding the Test API in The ASP.NET Web API Help Page