Throwing SoapException between WS_Receive and WS_Response
I have a state machine workflow that has a WebServiceInput and a WebServiceOutput. According to the documents, any unhandle exceptions thrown between a WS_In and a WS_Out will return a SoapFault.
A soap fault is being returned to the consumer of the web service. However, in one of my activities I am explicitly creating a SoapException and building the Detail property of the SoapException. After the SoapException is created, I throw it, and dont handle it. When the soap fault is returned to the caller of the web method, the xml contents of the detail section of the SoapException are gone.
If I throw a SoapException from some code in a normal web service and use the soap toolkit to see the contents of the soap fault, the <Detail> element of the soap fault is as expected (i.e. it contains whatever i put in it). However, when I run this same logic in a workflow, the details that should be in the soap fault are gone.
Is this expected?
This is just silly. I have tried over and over again to get additional information put into the defail section of the soap fault that is sent out from a workflow.
I have tried the following approaches:
- explicitly throwing a soap exception from a code action between a WS Input and WS Output activity, passing a valid xml node in the detail argument for the soap exception constructor
- explicitly throwing a soap exception from a code action between a WS Input and WS Output activity, passing a valid xml node in the detail argument for the soap exception constructor AND using the innerException
- using a soap fault activity, setting the Fault == a manually created soap exception
- using a soap fault activity, setting the Fault == a handled exception
In all of the cases above, the soap fault comes back with an empty details section.
I was under the impression that soap faults could be used by .NET and OTHER platforms (i.e. J2EE) to determine why a given service failed. I was also under the impression that the details section was where the additional information regarding what went wrong should go.
In my scenario, I invoke a web method that starts a workflow. In a code activity, the workflow communicates with an outside party via System.Net.WebClient, and does an HttpPost. I get a response back from the outside party and then inspect the data comming back. In some instances the outside party will reject my request. I need to terminate the workflow and pass the response from the outside party back to the consumer of my workflow. I was trying to put the response into the detail section of the soap fault that should be sent from the workflow.
This scenario works fine when I am using web services that are NOT tied to workflow.
I have attached a copy of what is comming back in my soap fault:
<?xml version="1.0" encoding="utf-8" ?>
- <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"> <faultcode>soap:Server</faultcode>
<faultstring>Server was unable to process request. > Workflow terminated unexpectedly while processing the current request. > Partner System has actively rejected the order. See the Partner System Response XML for more details</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
Where is the detail?
No, I dont have this problem when doing this from a "normal" asp.net web service.
I followed the guidelines for throwing exceptions from web services provided by microsoft and I have no issues wrapping exception details into SoapExceptions and having the details displayed in the soap fault.
Here is the soap fault returned from my "normal" web site.
<?xml version="1.0" encoding="utf-8" ?>
- <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"> <faultcode>soap:Client</faultcode>
<faultstring>System.Web.Services.Protocols.SoapException: Unable to perform the requested division, the remainder must == 0. at Service.DivideValues(Int32 numerator, Int32 denominator) in C:\NTDWorkingFolder\Utilities\SoapExceptions\SoapExceptionSample\TestServices\App_Code\Service.vb:line 36</faultstring>
<faultactor>http://localhost:1041/TestServices/Service.asmx</faultactor>
<Numerator xmlns="http://www.mycompany.com">3</Numerator>
<Denominator xmlns="http://www.mycompany.com">2</Denominator>
- <DateTimeInfo xmlns="http://www.mycompany.com"> <LocalTime>8/2/2006 12:14:43 PM</LocalTime>
</DateTimeInfo>
<UtcTime xmlns="http://www.mycompany.com">8/2/2006 4:14:43 PM</UtcTime>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
Obviously, I am trying to do more complex operations in the workflow. The very strange thing is that when debugging the workflow, in the faulting handler for my WS_Fault activity, I am actually building a soap exception and setting the Fault property of the WS_Fault activtiy to the new soap exception. After I set the Fault property, I am able to use the immediate window to access the detail member of the soap fault associated with the WS_Fault activity and the outer xml does exist in the Fault property of the WS_Fault activity.
So, I hacked my way through this. I took the exception message from all inner exceptions and appended them to my SoapExceptionMessage.
This is such a hack. The details property of the SoapException that I am throwing should be copied to and returned in the SoapFault that is generated.
The runtime is obviously taking the data from the Message property and putting that information into the SoapFault. Why cant the runtime check to see if the exception is of type SoapException and pull the details section from the user thrown SoapException and put it into the SoapFault?
Is there anyway for a developer to override the SoapFault that is generated when a workflow terminates in between a WebServiceInput and WebServiceOutput?
How are the other developers out there handling soap faults that are being thrown from workflows exposed as web services?
I know there are a lot of really smart people on this forum, surely someone has some advice?