您的位置:首页 > 编程语言 > ASP

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|CopyCode
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|CopyCode
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

ExceptionFilters

RegisteringExceptionFilters

HttpError

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
WebApiConfig
class,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.OneadvantageofusingHttpErroristhatitgoesthroughthesamecontent-negotiationandserializationprocessasanyotherstrongly-typedmodel.

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,seeModelValidationinASP.NETWebAPI.

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;}}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: