2012-01-12 17 views
5

का उपयोग करके बुलाए जाने वाले डब्ल्यूसीएफ रेस्ट के लिए दोषों को कैसे संभालें/पार्स करें मैं डब्लूसीएफ आरईएसटी सेवा क्लाइंट के भीतर दोषों को सही तरीके से संभालने में रूचि रखता हूं। इसलिए जैसे WebClient, WebRequest, या HttpWebRequest में से किसी का उपयोग करते समय:वेब क्लाइंट

try 
    { 
     HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri); 
     req.Method = "GET"; 
     HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); 
     // ...process... 
    } 
    catch (WebException wex) 
    { 
     string exMessage = wex.Message; 
     if (wex.Response != null) 
     { 
     using (StreamReader r = new StreamReader(wex.Response.GetResponseStream())) 
      exMessage = r.ReadToEnd(); 

     // the fault xml is available here, really need to parse? and how? 
     } 
    } 

मैं फ़िडलर है कि मैं एक अच्छी तरह से स्वरूपित एक्सएमएल "दोष" संदेश (या तो डिफ़ॉल्ट हो रही है में देख सकते हैं क्योंकि includeExceptionDetailInFaults = सच है, या एक कस्टम गलती IErrorHandler :: ProvideFault के माध्यम से)। हालांकि, केवल 500 आंतरिक त्रुटि WebException फेंक दिया जा रहा है।

मुझे क्लाइंट पर फॉल्टएक्सप्शन फेंक दिया जाएगा या कम से कम फाल्ट को पार्स करने में सक्षम होंगे। हम "सेवा संदर्भ" का उपयोग नहीं कर रहे हैं इसलिए कोई प्रॉक्सी नहीं है (अगर आरईएसटी डब्ल्यूसीएफ क्लाइंट के लिए ऐसा करने का बेहतर तरीका है तो कृपया मुझे सही करें)। क्या उस वास्तविक गलती (टीओएलएक्सप्शन) या यहां तक ​​कि विशिष्ट प्रकार के लिए शुरुआती बिंदु के बावजूद उस गलती को पार्स करने का एक सामान्य तरीका है? धन्यवाद! degorolls से जवाब पर

भवन:

public SomeContract ThrowErrorTest() 
{ 
    try 
    { 
     return TryCatchExtractAndRethrowFaults<SomeContract>(() => 
     { 
      // Call web service using WebClient, HttpWebRequest, etc. 
      return SomeContract; 
     });     
    } 
    catch (FaultException<CustomFault> fexCustom) 
    { 
     Dbg.WriteLine(fexCustom.Message); 
    } 
    catch (FaultException fex) 
    { 
     Dbg.WriteLine(fex.Message); 
    } 
    catch (WebException wex) 
    { 
     Dbg.WriteLine(wex.Message); 
    } 
    catch (Exception ex) 
    { 
     Dbg.WriteLine(ex.Message); 
    } 
    return null; 
}   

static public T TryCatchExtractAndRethrowFaults<T>(Func<T> doWebRequest) 
{ 
    try 
    { 
     return doWebRequest(); 
    } 
    catch (WebException wex) 
    { 
     FaultException fe = ConvertWebExceptionIntoFault(wex); 
     if (fe != null) 
      throw fe; 
     throw;  // not a fault, just re-throw 
    } 
} 

static protected FaultException ConvertWebExceptionIntoFault(WebException wex) 
{ 
    if (wex.Response == null) 
     return null; 

    XmlDictionaryReader xdr = XmlDictionaryReader.CreateTextReader(
     wex.Response.GetResponseStream(), 
     new XmlDictionaryReaderQuotas()); 

    Message msg = Message.CreateMessage(MessageVersion.None, "ParseFaultException", xdr); 

    // If the start element of the message is "Fault" convert it into a FaultException 
    // 
    using (MessageBuffer msgBuffer = msg.CreateBufferedCopy(65536)) 
     using (Message msgCopy = msgBuffer.CreateMessage()) 
      using (XmlDictionaryReader reader = msgCopy.GetReaderAtBodyContents()) 
       if (reader.IsStartElement("Fault")) 
       { 
        // Must make a copy for the converter 
        msg.Close(); 
        msg = msgBuffer.CreateMessage(); 
        return ConvertMessageToFault(msg); 
       } 

    return null; 
} 

static FaultException ConvertMessageToFault(Message msg) 
{ 
    EnvelopeVersion ev = msg.Version.Envelope; 
    var fault = MessageFault.CreateFault(msg, 65536); 

    if (fault.HasDetail) 
    { 
     string faultName = fault.GetReaderAtDetailContents().Name; 
     switch (faultName) 
     { 
      case "ExceptionDetail": // handle the default WCF generated fault 
       ExceptionDetail exDetail = fault.GetDetail<ExceptionDetail>(); 
       return new FaultException<ExceptionDetail>(exDetail, fault.Reason, fault.Code); 

      case "CustomFault":  // handle custom faults 
       CustomFault cstmDetail = fault.GetDetail<CustomFault>(); 
       return new FaultException<CustomFault>(cstmDetail, fault.Reason, fault.Code); 

      default: 
       throw new Exception("Unrecognized fault detail '" + faultName + 
            "' while re-constructing fault."); 
     } 
    } 
    return null; 
} 

उत्तर

6

दोष सोप प्रोटोकॉल का हिस्सा हैं और बाकी परिदृश्यों में उपलब्ध नहीं हैं। मुझे विश्वास नहीं है कि डब्ल्यूसीएफ बुनियादी ढांचे में से कोई भी बॉक्स के बाहर क्या कर रहा है इसका समर्थन करता है।

आप 500 त्रुटि के बजाय FaultException प्राप्त करने के लिए अपने WebHttp व्यवहार कॉन्फ़िगरेशन में FaultExceptionEnabled = true सेट कर सकते हैं।

हालांकि, आप ऐसा कुछ भी कर सकते हैं (मैंने इसे कुछ परीक्षण परिदृश्यों में किया है)। यह विधि गलती से अपेक्षा करने के लिए किस प्रकार की FaultDetail की अपेक्षा करने से पहले जानती है।

 bool isFault; 
     if (message.Version == MessageVersion.None) 
     { 
      //Need to determine for ourselves if this is a fault; 
      using (MessageBuffer buffer = message.CreateBufferedCopy(65536)) 
      { 
       message.Close(); 
       message = buffer.CreateMessage(); 
       using (Message message2 = buffer.CreateMessage()) 
       { 
        using (XmlDictionaryReader reader = message2.GetReaderAtBodyContents()) 
        { 
         isFault = reader.IsStartElement("Fault", "http://schemas.microsoft.com/ws/2005/05/envelope/none"); 
        } 
       } 
      } 
     } 
     else 
     { 
      // For SOAP messages this is done for us 
      isFault = message.IsFault; 
     } 

     if (isFault) 
     { 
      var fault = MessageFault.CreateFault(message, 65536); 
      MyServiceFault detail = null; 
      if (fault.HasDetail) 
      { 
       // The only thing we can possible have as detail is an MyServiceFault 
       detail = fault.GetDetail<MyServiceFault>(); 
      } 
      FaultException ex = new FaultException<MyServiceFault>(detail, fault.Reason, fault.Code); 
      throw ex; 
     } 
+0

ऐसा लगता है कि मुझे नज़दीक लगता है। MessageFault.CreateFault() पर मुझे नामस्थान के बारे में आंतरिक अपवाद शिकायत ".../लिफाफा/कोई नहीं" के बजाय ".../साबुन-लिफाफा" नहीं है। नामस्थान मुद्दे के आसपास काम करने के लिए एक अच्छा तरीका पता है? यह वास्तव में सर्वर से ".../लिफाफा/कोई नहीं" के रूप में आता है। – crokusek

+0

मैंने Message.CreateMessage() को संदेश Version में तर्क बदल दिया। MessageVersion.Default के बजाय कोई और नामस्थान समस्या ठीक कर दी। चूंकि मैं वेबएक्सप्शन से शुरू कर रहा हूं, इसलिए वेक्स से संदेश बना रहा है। रेस्पॉन्स स्ट्रीम। प्रश्न के अंत में क्या काम खत्म हो जाएगा पोस्ट करेंगे। – crokusek

+0

क्या आप FaultExceptionEnabled = true सेट करने के बाद भी WebException प्राप्त कर रहे हैं? –

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