2014-06-13 12 views
14

से समान त्रुटि प्रतिक्रियाएं, मैं एक वेब एपीआई 2 एप्लिकेशन विकसित कर रहा हूं और मैं वर्तमान में एक समान तरीके से त्रुटि resposnes प्रारूपित करने की कोशिश कर रहा हूं (ताकि उपभोक्ता यह भी जान सके कि डेटा ऑब्जेक्ट/संरचना वे त्रुटियों के बारे में अधिक जानकारी प्राप्त करने का निरीक्षण कर सकते हैं)।एएसपी.Net वेब एपीआई 2

{ 
    "Errors": 
    [ 
     { 
      "ErrorType":5003, 
      "Message":"Error summary here", 
      "DeveloperAction":"Some more detail for API consumers (in some cases)", 
      "HelpUrl":"link to the docs etc." 
     } 
    ] 
} 

यह आवेदन अपने आप में फेंक दिया अपवाद हैं (यानी अंदर नियंत्रक) के लिए ठीक काम करता है: यह मैं अब तक क्या मिल गया है है। हालांकि, यदि उपयोगकर्ता खराब यूआरआई (और 404 प्राप्त करता है) का अनुरोध करता है या गलत क्रिया का उपयोग करता है (और 405 हो जाता है) आदि, वेब एपीआई 2 एक डिफ़ॉल्ट त्रुटि संदेश को थकाता है उदा।

{ 
    Message: "No HTTP resource was found that matches the request URI 'http://localhost/abc'." 
} 

कोई त्रुटि (404, 405 आदि) और उनके ऊपर पहले उदाहरण में त्रुटि प्रतिसाद में बाहर स्वरूपण के इन प्रकार के फँसाने का कोई तरीका है?

अब तक मैं कोशिश की है:

  • कस्टम ExceptionAttribute inherting ExceptionFilterAttribute
  • कस्टम ControllerActionInvoker inherting ApiControllerActionInvoker
  • IExceptionHandler

हालांकि (वेब ​​एपीआई से 2.1 सुविधा हैंडलिंग नई वैश्विक त्रुटि) , इनमें से कोई भी दृष्टिकोण इन प्रकार की त्रुटियों को पकड़ने में सक्षम नहीं है (404, 405 इत्यादि)। इस पर कोई विचार कैसे प्राप्त किया जा सकता है?

... या, क्या मैं इस गलत तरीके से जा रहा हूं? क्या मुझे केवल अपनी विशेष शैली में एप्लिकेशन/उपयोगकर्ता स्तर की त्रुटियों के लिए त्रुटि प्रतिक्रियाएं स्वरूपित करनी चाहिए और 404 जैसी चीजों के लिए डिफ़ॉल्ट त्रुटि प्रतिक्रियाओं पर भरोसा करना चाहिए?

+1

'चाहिए मैं केवल प्रारूप के लिए कोशिश पकड़ हिट आवेदन/उपयोगकर्ता स्तर की त्रुटियों के लिए मेरी विशेष शैली में त्रुटि प्रतिक्रियाएं और 404 जैसी चीजों के लिए डिफ़ॉल्ट त्रुटि प्रतिक्रियाओं पर भरोसा करते हैं? '... मेरी राय हाँ –

+0

मैं इस दृष्टिकोण की ओर से अधिक से अधिक चल रहा हूं। आपके महान उत्तरों/टिप्पणियों के लिए धन्यवाद। –

उत्तर

8

आप DelegatingHandler अमूर्त वर्ग को ओवरराइड कर सकते हैं और ग्राहक को प्रतिक्रिया को रोक सकते हैं। इससे आप जो चाहते हैं उसे वापस करने की क्षमता देंगे।

यहां कुछ जानकारी दी गई है। http://msdn.microsoft.com/en-us/library/system.net.http.delegatinghandler(v=vs.118).aspx

यहां वेब एपी पाइपलाइन का एक पोस्टर है जो दिखाता है कि ओवरड्रिड क्या हो सकता है। http://www.asp.net/posters/web-api/asp.net-web-api-poster.pdf

अपने WebApiConfig.cs कक्षा में प्रतिक्रिया

public class MessageHandler1 : DelegatingHandler 
{ 
    protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     Debug.WriteLine("Process request"); 
     // Call the inner handler. 
     var response = base.SendAsync(request, cancellationToken); 

     Debug.WriteLine("Process response"); 
     if (response.Result.StatusCode == HttpStatusCode.NotFound) 
     { 
      //Create new HttpResponseMessage message 
     } 
     ; 
     return response; 
    } 
} 

ओवरराइड करने के लिए हैंडलर जोड़ने के इस तरह एक हैंडलर वर्ग बनाएँ।

config.MessageHandlers.Add(new MessageHandler1()); 

अद्यतन किरण टिप्पणी में उल्लेख के रूप में आप प्रतिक्रिया वापस ग्राहक के लिए जा रहा रोकना OwinMiddleware उपयोग कर सकते हैं। यह किसी भी मेजबान पर चल रहे एमवीसी और वेब एपीआई के लिए काम करेगा।

यहां एक उदाहरण है कि प्रतिक्रिया कैसे प्राप्त करें और इसे क्लाइंट के रूप में बदल दें।

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     app.Use(typeof(MyMiddleware)); 
    } 
} 

public class MyMiddleware : OwinMiddleware 
{ 
    public MyMiddleware(OwinMiddleware next) : base(next) { } 

    public override async Task Invoke(IOwinContext context) 
    { 
     await Next.Invoke(context); 
     if(context.Response.StatusCode== 404) 
     { 
      context.Response.StatusCode = 403; 
      context.Response.ReasonPhrase = "Blah"; 
     } 
    } 
} 
+0

यह अकेले पर्याप्त नहीं होगा क्योंकि कुछ मामलों में अनुरोध वेब एपीआई रूट मैचों के कारण वेब एपीआई में भी नहीं आएंगे। (यह समस्या आईआईएस होस्टेड परिदृश्यों के लिए विशिष्ट है)। वेब एपीआई मार्गों के अंत में सभी मार्गों को पकड़कर इस समस्या को बाधित किया जा सकता है जो एक कस्टम 404 त्रुटि संदेश भेज सकता है ... अन्य संभावित समाधान एक ओविन मिडलवेयर है जो पहले पाइपलाइन में बैठता है और इस तरह आपके पास सब कुछ है आपका तर्क एक ही स्थान पर है (मैंने इसे स्वयं से नहीं खेला है, लेकिन मुझे लगता है कि यह काम करना चाहिए) –

+0

यह रूट एपीआई कॉल के लिए डेलीगेटिंग हैंडलर को हिट करेगा, भले ही रूट गलत है क्योंकि HttpRoutingDispatcher को DelegatingHandlers के बाद बुलाया जाता है। आप सही हैं, कि अगर अनुरोध एक एपीआई अनुरोध नहीं है तो यह इस हैंडलर को नहीं मारा जाएगा क्योंकि गैर एपीआई कॉल सिस्टम.Web.Mvc नेमस्पेस हैंडलर द्वारा संभाले जाते हैं। उदाहरण: http: // localhost/WebApplication1/api/अमान्य इस हैंडलर को हिट करेगा लेकिन http: // localhost/WebApplication1/अमान्य इस हैंडलर को नहीं मारा जाएगा ... मानते हैं कि सभी एपीआई कॉल http: // localhost/WebApplication1/api/ –

+0

बस स्पष्ट होने के लिए ... 'HttpRoutingDispatcher' पर रूट मिलान केवल SelfHost और इन-मेमोरी परिदृश्यों के लिए होता है ... –

2

मैं @Dan एच के रूप में एक ही तरीके से किया है

उल्लेख नीचे की तरह
public class ApiGatewayHandler : DelegatingHandler 
{ 
    protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     try 
     { 
      var response = await base.SendAsync(request, cancellationToken); 
      if (response.StatusCode == HttpStatusCode.NotFound) 
      { 
       var objectContent = response.Content as ObjectContent; 
       return await Task.FromResult(new ApiResult(HttpStatusCode.NotFound, VmsStatusCodes.RouteNotFound, "", objectContent == null ? null : objectContent.Value).Response()); 
      } 
      return response; 
     } 
     catch (System.Exception ex) 
     { 
      return await Task.FromResult(new ApiResult(HttpStatusCode.BadRequest, VmsStatusCodes.UnHandledError, ex.Message, "").Response()); 
     } 

    } 
} 

जोड़ा मार्ग और अब यह अवैध URL

config.Routes.MapHttpRoute(name: "DefaultApi",routeTemplate: "api/{controller}/{id}",defaults: new { id = RouteParameter.Optional }); 
     config.Routes.MapHttpRoute(name: "NotFound", routeTemplate: "api/{*paths}", defaults: new { controller = "ApiError", action = "NotFound" }); 
+0

कोई प्रदर्शन कमी है? –

संबंधित मुद्दे