none
Proper "Body path expression" for WCF Faults RRS feed

  • Question

  • I'm calling an in-house WCF web service that has the following responses:

    The Success Response:

    <WriteBackTaskTrackingResponse xmlns="http://tempuri.org/">
      <WriteBackTaskTrackingResult xmlns:a="http://schemas.datacontract.org/2004/07/DeltaTurnTrackService.ServiceReference" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:WriteBackStatus>SUCCEEDED</a:WriteBackStatus>
        <a:WriteBackStatusSpecified>true</a:WriteBackStatusSpecified>
      </WriteBackTaskTrackingResult>
    </WriteBackTaskTrackingResponse>

    and a BusinessFault:

    <BusinessFaultType xmlns="http://schemas.datacontract.org/2004/07/DeltaTurnTrackService.ServiceReference" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <FaultDetailedInfo>
        <AdditionalInfo>Node: E002_Node05_JVM01 Svc: EnterpriseDataUtility.writeBackTaskTracking() backend request: N/A</AdditionalInfo>
        <DebugInfo i:nil="true" />
        <ErrorCode />
        <ErrorMessage>Input error(s):
    |
    |'schedDprtOrArrTs' is invalid. It must be a valid date in the following format: 'yyyy-MM-dd HH:mm:ss'. </ErrorMessage>
        <ResponseInfo i:nil="true" />
        <StackTraceInfo> Stack Trace:
    |java.lang.Exception
    ||etc...
    |
    |</StackTraceInfo>
      </FaultDetailedInfo>
    </BusinessFaultType>

    I have a couple of test files, one that should give a good response, and one that has a bad date which causes the BusinessFault.

    According to this page (http://msdn.microsoft.com/en-us/library/bb246117.aspx), I should build an XPATH soemthing like this:

    /*[local-name()='Fault']/*[local-name()='Detail']/* | /*[local-name()='DivideResponse']

    First, I think they made a typo, the Detail should have been lowercase.

    To be able to catch the BusienssFault (and also a SystemFault), the following works:

    /*[local-name()='Fault']/*[local-name()='detail']/* | //*[local-name()='BusinessFaultType'] | //*[local-name()='SystemFaultType'] | //*[local-name()='WriteBackTaskTrackingResponse']

    With this, I am able to catch faults.

    But the bad news is, it doesn't let the successful messages through.

    I get an error like this:

       System.Exception: Microsoft.XLANGs.Core.XlangSoapException: An error occurred while processing the message, refer to the details section for more information

       Message ID: {72260F1D-9024-4134-8B93-BF07AE6D8D37}  Instance ID: {1CEDCFE5-2D10-4B87-A682-16185E72D3D8}  
       Error Description: System.InvalidOperationException:
       Unable to find match for inbound body path expression
       "/*[local-name()='Fault']/*[local-name()='detail']/* | //*[local-name()='BusinessFaultType'] | //*[local-name()='SystemFaultType'] | //*[local-name()='WriteBackTaskTrackingResponse']" in message.     
       at Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfMarshaller.CreateBizTalkMessageStream(Message wcfMessage, IAdapterConfigInboundMessageMarshalling config)    
       at Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfMarshaller.CreateBizTalkMessage(IBaseMessageFactory messageFactory, IAdapterConfigInboundMessageMarshalling marshallingConfig, Message wcfMessage)     
       at Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfClient`2.RequestCallback(IAsyncResult result)       
       at Microsoft.BizTalk.XLANGs.BTXEngine.BTXPortBase.VerifyTransport(Envelope env, Int32 operationId, Context ctx)     
       at Microsoft.XLANGs.Core.Subscription.Receive(Segment s, Context ctx, Envelope& env, Boolean topOnly)     
       at Microsoft.XLANGs.Core.PortBase.GetMessageIdForSubscription(Subscription subscription, Segment currentSegment, Context cxt, Envelope& env, CachedObject location)     
       at QT.DeltaTurnTrack.Export.DeltaTurnTrackingExtrac.segment2(StopConditions stopOn)     
       at Microsoft.XLANGs.Core.SegmentScheduler.RunASegment(Segment s, StopConditions stopCond, Exception& exp)

    When I go look at the message parts in the suspended message, it shows the request message, not the response message.

    I was able to process the success messages by specifying //*[1] as the xpath, but this didn't work for the Faults.

    Thanks,
    Neal Walters

     


    Monday, July 15, 2013 3:21 PM

Answers

  • Just tried this again, and it works.

    /*[local-name()='Fault']/*[local-name()='detail']/* | /*[local-name()='WriteBackTaskTrackingResponse']

    I am almost sure I ran this yesterday, and it did not work for both test cases (the success and the error).

    Neal

    Monday, July 15, 2013 9:20 PM

All replies

  • Set the Inbound BizTalk message body to Envelope and verify the success message is coming back as expected.
    Monday, July 15, 2013 4:44 PM
  • As I said in my original post, I know the good message works, because when I use this xpath: //*[1]

    I see the correct XML in my trace.  I have even used Stylus Studio to verify the above XPath against that message, and it seems to match fine.

    Neal 


    Monday, July 15, 2013 4:47 PM
  • I am suggesting you take the opportunity to look at the entire Envelope after Channel processing because that's what hits the filter in the bridge adapter.

    It shouldn't be any different but since that's what the filter is applied too, it might be worth checking out.

    Monday, July 15, 2013 5:12 PM
  • If I put xpath: //*[1], that should give me the top element (which I enclosed in my original post). How is that different than getting the envelope you are referring to?  It sounds like that would be the exact same results as my Body Path being set to //*[1] (the first node or element).  I just realized that is verbose, I could have just put "/" for the xpath, which returns the root element. 

    An in fact, that is the same result I get when I just re-ran and selected the "Envelope" option you recommended:

    <WriteBackTaskTrackingResponse xmlns="http://tempuri.org/">
      <WriteBackTaskTrackingResult xmlns:a="http://schemas.datacontract.org/2004/07/DeltaTurnTrackService.ServiceReference" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:WriteBackStatus>SUCCEEDED</a:WriteBackStatus>
        <a:WriteBackStatusSpecified>true</a:WriteBackStatusSpecified>
      </WriteBackTaskTrackingResult>
    </WriteBackTaskTrackingResponse>

    What do you suggest next?

    Neal

    Monday, July 15, 2013 6:32 PM
  • Let me add to that that the orchestration does not blow up when I specify envelope and send a successful message.  Thus, I'm not sure how I would see the <soap:envelope>.  (I don't have message tracking turned on.)  In the orchestration, if I get the success message, I write it to a SQL xml column, and that is what I pasted in the prior message.

    When I drop a message that causes an error, the orchestration end with this error (since the Fault message is no longer recognized properly):

    The instance completed without consuming all of its messages. The instance and its unconsumed messages have been suspended.

    Neal



    • Edited by Neal Walters Monday, July 15, 2013 7:42 PM cover the negative case
    Monday, July 15, 2013 7:38 PM
  • An in fact, that is the same result I get when I just re-ran and selected the "Envelope" option you recommended:

    That's not the expected behavior.  Don't know what to tell you there.

    As for why '/' or '//*' or such doesn't work for the faults, all I have is a theory.  The xpath query is not a 'condition' but a 'selector'.  As such, it's not short-circuited.  So, in the case of a fault, likely the first and last (your '//*[1]') predicates match thus a node-set is returned, not a single node as would be required.  The actual error may be swallowed.

    Note the sample in the referenced article uses specific matches for each possible result.

    Monday, July 15, 2013 8:01 PM
  • Sorry, but you never seem to get what I'm saying.  The faults are working fine, it's the real success message that is failing.
    Neal

    Monday, July 15, 2013 8:33 PM
  • I was able to process the success messages by specifying //*[1] as the xpath, but this didn't work for the Faults.

    Please clarity, that expression does work for the faults?
    Monday, July 15, 2013 8:58 PM
  • Just tried this again, and it works.

    /*[local-name()='Fault']/*[local-name()='detail']/* | /*[local-name()='WriteBackTaskTrackingResponse']

    I am almost sure I ran this yesterday, and it did not work for both test cases (the success and the error).

    Neal

    Monday, July 15, 2013 9:20 PM
  • Hi,

    Do you have any difference when you tried above code ?

    Regards,


    Chen Yu
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, July 16, 2013 9:14 AM
    Moderator