Synchronous web services calls and Faults

In my last post I described how I improved latency between a two way WCF basic HTTP receive location and two way WCF custom SQL send location by removing the orchestration binding them together. I will call this a messaging only scenario. Since Salvatori’s post where he describes a messaging only scenario for the first time there has been another post by Wout who describes in simple terms how to go about implementing this pattern. This post will talk about what happens if the send location raises a fault and my unsuccessful attempts to transform this fault to another message.

I was prompted to publish my experiences in this area because Hedberg recently published a post where he describes how to transform a SOAP fault into another message.

My example above has propagate fault enabled on the WCF custom send location. On generating a SQL error with a raiserror in the stored procedure this fault gets passed out as the response and is relayed back to the original caller.

<s:Fault xmlns:s=”http://schemas.xmlsoap.org/soap/envelope/“><faultcode xmlns:a=”http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher“>a:InternalServiceFault</faultcode><faultstring xml:lang=”en-NZ”>The server was unable to process the request due to an internal error.  For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the &lt;serviceDebug&gt; configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.</faultstring></s:Fault>

 On ticking include exception detail in faults I get;

<s:Fault xmlns:s=”http://schemas.xmlsoap.org/soap/envelope/“><faultcode xmlns:a=”http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher“>a:InternalServiceFault</faultcode><faultstring xml:lang=”en-NZ”>&lt;SOAP:Envelope xmlns:SOAP=”http://schemas.xmlsoap.org/soap/envelope/” SOAP:encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/“&gt;&lt;SOAP:Body&gt;&lt;SOAP:Fault&gt;&lt;faultcode&gt;Microsoft BizTalk Server Negative Acknowledgment &lt;/faultcode&gt;&lt;faultstring&gt;An error occurred while processing the message, refer to the details section for more information &lt;/faultstring&gt;&lt;faultactor&gt;mssql://.//OQR?&lt;/faultactor&gt;&lt;detail&gt;&lt;ns0:NACK Type=”NACK” xmlns:ns0=”http://schema.microsoft.com/BizTalk/2003/NACKMessage.xsd“&gt;&lt;NAckID&gt;{94F5EC8F-D42A-44CB-B444-4BAD5A78EF30}&lt;/NAckID&gt;&lt;ErrorCode&gt;0xc0c0167a&lt;/ErrorCode&gt;&lt;ErrorCategory&gt;0&lt;/ErrorCategory&gt;&lt;ErrorDescription&gt;System.Data.SqlClient.SqlException: Test WCF errors

 Server stack trace: “Stack trace omitted for clarity” </faultstring><detail><ExceptionDetail xmlns=”http://schemas.datacontract.org/2004/07/System.ServiceModel” xmlns:i=”http://www.w3.org/2001/XMLSchema-instance“><HelpLink i:nil=”true” /><InnerException i:nil=”true” /><Message>&lt;SOAP:Envelope xmlns:SOAP=”http://schemas.xmlsoap.org/soap/envelope/” SOAP:encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/“&gt;&lt;SOAP:Body&gt;&lt;SOAP:Fault&gt;&lt;faultcode&gt;Microsoft BizTalk Server Negative Acknowledgment &lt;/faultcode&gt;&lt;faultstring&gt;An error occurred while processing the message, refer to the details section for more information &lt;/faultstring&gt;&lt;faultactor&gt;mssql://.//OQR?&lt;/faultactor&gt;&lt;detail&gt;&lt;ns0:NACK Type=”NACK” xmlns:ns0=”http://schema.microsoft.com/BizTalk/2003/NACKMessage.xsd“&gt;&lt;NAckID&gt;{94F5EC8F-D42A-44CB-B444-4BAD5A78EF30}&lt;/NAckID&gt;&lt;ErrorCode&gt;0xc0c0167a&lt;/ErrorCode&gt;&lt;ErrorCategory&gt;0&lt;/ErrorCategory&gt;&lt;ErrorDescription&gt;System.Data.SqlClient.SqlException: Test WCF errors

 Server stack trace:

  “Trace omitted for clarity”

 </StackTrace><Type>Microsoft.BizTalk.Adapter.Wcf.Runtime.BizTalkNackException</Type></ExceptionDetail></detail></s:Fault>

 All good but now I decided to try to map the fault to my desired response with an error code in the response like this;I put this map as an outbound map on the receive port.I then get an error on the receive port like;

The Messaging Engine failed while executing the outbound map for the response message going to source URL:”/BizTalkWcfCreateQuoteDetailsService/WcfCreateQuoteDetailsService.svc” with the Message Type “http://schemas.xmlsoap.org/soap/envelope/#Fault”. Details:”Root element is missing.”

What does this mean? At this stage i saw Hedburg’s blog and thought it might be because the “namespace prefixes are incorrect for reserved namespaces”. Thus I followed his lead and used custom xslt to do the transform. My custom XSLT was ;

<?xml version=”1.0″ encoding=”utf-16″?>
  <xsl:stylesheet xmlns:xsl=”http://www.w3.org/1999/XSL/Transform”
                    xmlns:msxsl=”urn:schemas-microsoft-com:xslt”
                    xmlns:var=”http://schemas.microsoft.com/BizTalk/2003/var”
                    exclude-result-prefixes=”msxsl var s0 userCSharp” version=”1.0″
                    xmlns:s0=”http://schemas.xmlsoap.org/soap/envelope/”
                    xmlns:xml =”http://www.w3.org/XML/1998/namespace”
                    xmlns:ns0=”http://schemas.microsoft.com/Sql/2008/05/ProceduresResultSets/dbo/sp_CreateQuoteDetails”
                    xmlns:ns1=”http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo”
                    xmlns:userCSharp=”http://schemas.microsoft.com/BizTalk/2003/userCSharp”>
  <xsl:output omit-xml-declaration=”yes” method=”xml” version=”1.0″ />
  <xsl:template match=”/”>
    <xsl:apply-templates select=”/s0:Fault” />
  </xsl:template>
  <xsl:template match=”/s0:Fault”>
    <xsl:variable name=”var:v1″ select=”userCSharp:StringConcat(&quot;4004&quot;)” />
    <ns1:sp_CreateQuoteDetailsResponse>
      <ns1:ReturnValue>
        <xsl:value-of select=”$var:v1″ />
      </ns1:ReturnValue>
    </ns1:sp_CreateQuoteDetailsResponse>
  </xsl:template>
  <msxsl:script language=”C#” implements-prefix=”userCSharp”><![CDATA[
public string StringConcat(string param0)
{
   return param0;
}

]]></msxsl:script>
</xsl:stylesheet>

I fired up the test again and still got the same exception on the map.

OK I thought I’ll try to use the XSLT transform in Hedburgh’s blog to transform my SOAP 1.1 to SOAP 1.2 message. On trying this I got a different exception namely; Object reference not set to an instance of an object. I  fixed this error by changing the XSLT to;

<?xml version=”1.0″ encoding=”utf-16″?>
<xsl:stylesheet xmlns:xsl=”http://www.w3.org/1999/XSL/Transform”
                xmlns:msxsl=”urn:schemas-microsoft-com:xslt”
                xmlns:var=”http://schemas.microsoft.com/BizTalk/2003/var”
                exclude-result-prefixes=”msxsl var s0″ version=”1.0″
                xmlns:s0=”http://schemas.xmlsoap.org/soap/envelope/”
                xmlns:xml=”http://www.w3.org/XML/1998/namespace”
                xmlns:tns=”http://www.w3.org/2003/05/soap-envelope”>
  <xsl:output omit-xml-declaration=”yes” method=”xml” version=”1.0″ />
  <xsl:template match=”/”>
    <xsl:apply-templates select=”/s0:Fault” />
  </xsl:template>
  <xsl:template match=”/s0:Fault”>
    <tns:Fault>
      <tns:Code>
        <tns:Value>
          tns:MustUnderstand
        </tns:Value>
      </tns:Code>
      <tns:Reason>
        <tns:Text xml:lang=”en-NZ”>
          <xsl:value-of select=”faultstring/text()” />
        </tns:Text>
      </tns:Reason>
      <xsl:if test=”faultactor”>
        <tns:Role>
          <xsl:value-of select=”faultactor/text()” />
        </tns:Role>
      </xsl:if>
      <xsl:for-each select=”detail”>
        <tns:Detail>
          <xsl:value-of select=”./text()” />
        </tns:Detail>
      </xsl:for-each>
    </tns:Fault>
  </xsl:template>
</xsl:stylesheet>

On firing up the test again I get the same error I got with my transform in the first place.

 So I am now stuck. I am using BizTalk 2006 R2 and maybe this only works in BizTalk 2009? Has anyone out there got any clue why the above does not work and i get this exception;

The Messaging Engine failed while executing the outbound map for the response message going to source URL:”/BizTalkWcfCreateQuoteDetailsService/WcfCreateQuoteDetailsService.svc” with the Message Type “http://schemas.xmlsoap.org/soap/envelope/#Fault”. Details:”Root element is missing.”

  • mbrimble

    Watch this space. It seems that the WCF SQL adapter is a special case.

BizTalk360
BizTalk Server

Over 500+ customers across
30+ countries depend on BizTalk360

Learn More
Serverless360
Azure

Manage and monitor serverless
components effortlessly

Learn More
Atomicscope
Business Users

Monitor your Business Activity in iPaaS
or Hybrid integration solutions

Learn More

Back to Top