I've seen a few people asking about this one on various forums etc, and unfortunately none of them seem to have an answer which is a bit frustrating, but I think I've actually worked this one out, and hopefully this should make a few people happy :-)
A soap exception is returned from the web service but no where in it is the custom fault message you threw
The fault message I wished to return is as follows:
ErrorMessage = "Unable to add user to System X. Please contact you Systems Administrator.";
Below is a sample of the soap message returned to my client, the error i get is highlighted in red:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soap:Header>
<wsa:Action>http://schemas.xmlsoap.org/ws/2004/03/addressing/fault</wsa:Action>
<wsa:MessageID>uuid:03f81957-5a36-4436-ab4e-8aae9488e90b</wsa:MessageID>
<wsa:RelatesTo>uuid:1fb88687-13af-49bf-be6d-6ead0f27c084</wsa:RelatesTo>
<wsa:To>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous</wsa:To>
<wsse:Security>
<wsu:Timestamp wsu:Id="Timestamp-92947608-325b-48d0-8ebc-3a703a80dfc0">
<wsu:Created>2007-05-31T12:36:05Z</wsu:Created>
<wsu:Expires>2007-05-31T12:41:05Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</soap:Header>
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Failed ---> An exception is thrown by the Orchestration schedule</faultstring>
<detail />
</soap:Fault>
</soap:Body>
</soap:Envelope>
No matter what you seem to do you get this "An exception is thrown by the Orchestration schedule" error message.
This one took a bit of fiddling to work out but the solution is below.
Solution
While I was trying to work out what was happening here, I kind of guessed it must be somewhere between the port and the code coming out of the web service where my message was disappearing, I ended up disassembling (with Reflector) the following assembly:
Microsoft.BizTalk.WebServices.ServerProxy.dll
In theServerProxy class there is a method called DeserializeResponseMessage, in here I found the following code snippet:
if (this.respMsgContext.Read(FaultNameProperty.Name.Name, FaultNameProperty.Name.Namespace) != null)
{
XmlNode orchestrationErrorMessage = this.GetOrchestrationErrorMessage(response);
XmlNode detail = new XmlDocument().CreateNode(XmlNodeType.Element, SoapException.DetailElementName.Name, SoapException.DetailElementName.Namespace);
detail.InnerXml = orchestrationErrorMessage.OuterXml;
string message = resManager.GetString("OrchestrationOperationFault", CultureInfo.CurrentCulture);
string text5 = resManager.GetString("OrchestrationDataDump", CultureInfo.CurrentCulture);
string text6 = message + text5 + detail.OuterXml; TraceLogger.TraceLog.TraceMessage(1, text6);
throw new SoapException(message, SoapException.ServerFaultCode, base.Context.Request.Url.AbsoluteUri, detail);
}
I read this to mean that if the FaultName context property is set on the message then this code above will execute and it will create a detail section in the soap fault where it will add my fault message. Im guessing that this wasn’t being set and therefore it was executing other code which just returns a SoapException without any custom stuff.
I've never seen any tutorials or documentation on this so I gave it a try.
In the message construct shape where I created the fault message I adjusted the code so it looked like the following snippet:
ErrorMessage = "Unable to add user to System X. Please contact you Systems Administrator.";
ErrorMessage(BTS.FaultName) = "Fault";
As you can now see I've set the context property. I think it can be set to anything that isnt null for this to work, but I just set it to "Fault" in this case.
When I reran the original test the soap message I received at the client now looked as follows, my fault message is highlighted in red:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soap:Header>
<wsa:Action>http://schemas.xmlsoap.org/ws/2004/03/addressing/fault</wsa:Action>
<wsa:MessageID>uuid:aec1480b-c184-4de5-84ee-1032103b7f30</wsa:MessageID>
<wsa:RelatesTo>uuid:a1f072bd-0c3d-43d8-8412-1d3381355722</wsa:RelatesTo>
<wsa:To>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous</wsa:To>
<wsse:Security>
<wsu:Timestamp wsu:Id="Timestamp-f802be51-b781-4f6a-a76f-b8aa322d9245">
<wsu:Created>2007-05-31T12:57:54Z</wsu:Created>
<wsu:Expires>2007-05-31T13:02:54Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</soap:Header>
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>An exception is thrown by the Orchestration schedule</faultstring>
<faultactor>http://localhost/Acme/IntegrationService.asmx</faultactor>
<detail>
<string>Unable to add user to System X. Please contact you Systems Administrator.</string>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
The client would still receive the same exception message as before provided by BizTalk, but now if they inspect the detail section of the soap fault they will be able to get access to my error message.
I hope you find this useful and if you have any thoughts or feedback on this please let me know