I'm trying to make a WCF service that will be consumed by other parties by passing a SOAP request to the service. The client requires me to handle a set of FaultExceptions that could happen during the interaction.
This includes that if the client send a malformed Uri in the SOAP request [wsa:To] element, that is if the client for example send a request contains the following:
<wsa:To>http//:this.is.invalid/address</wsa:To>
I should be able to throw a specific FaultException. I tried to implement the IDispatchMessageInspector to capture the SOAP request before it reach the operation but when the client send a request contains a bad Uri like in the above example, the AfterReceiveRequest is not called and so I can NOT handle this type of error.
I couldn't find the error until I've enabled the trace logging for my WCF service and I'm the error
System.UriFormatException, System, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089<br><br>with the description
<br><br>Handling an exception. Exception details:
System.UriFormatException: Invalid URI: The URI scheme is not valid.
The question is how and where can I catch this exception in the Code? Thanks in advance,
The soap header wsa:To should contain the address of the intended receiver of the message. WCF client-side framework enforces this by using the service endpoint address as the value for the wsa:To header element. I'm not sure whether the WCF service-side framework enforces validation of this element since it has already ready received the soap message.
You're seeing the 400 HTTP error because the WCF client is attempting to sent a soap message to an invalid service endpoint. To properly test an invalid wsa:To value you need code that will create the soap XML with an invalid wsa:To value but sent to the correct service endpoint.
If WCF doesn't validate this value, you're approach of using an implementation of the IDispatchMessageInspector should work. Otherwise, if WCF throws an exception before the IDispatchMessageInspector implementation is called then you may need to implement a IErrorHandler endpoint behavior to catch this kind of "in the plumbing" exception. See this great blog post for information on how to implement and configure it.
Related
We have a generated client endpoint for a SOAP webservice. Since the web service doesn't have any predefined error messages for the xml when an error occurs the error message is just slapped before the xml and that throws an exception while parsing the response.
Is there any possible way to manipulate the response so we can actually read the message and throw a custom exception for the error message.
In WCF you can use the ambient OperationContext.Current instance.
var context = OperationContext.Current;
var header = new MessageHeader<string>("test");
context.OutgoingMessageHeaders.Add(header.GetUntypedHeader(typeof(string).Name, typeof(string).Namespace));
If you can't use WCF check out the generated SOAP XML and tug it in manually in your program.
I'm calling a SOAP web service using WCF. When the server gots error or turns into maintenance state, it replies with a HTML document. With WCF client an TargetInvocationException will be thrown because the reply is not a soap message.
I want to intercept the HTTP response and do some process (logging for exemple) when the server turns into abnormal state. I tried the IClientMessageInspector with IEndpointBehavior, when the server replies well (even Soap Fault), the method IClientMessageInspector.AfterReceiveReply fires and i can catch the message.
But when the server replies with a HTML document (where i need that method fired), that method did not fired. i just got TargetInvocationException and within that exception i can not get the original http reponse.
Does any one faced the same problem and maybe a solution for this ?
Thanks.
I have an existing soap client who communicates with a soap service without using the soap action attribute. Now, we have recently substituted this soap service with a C# WCF Service which requires a soap action by default.
When I import the WSDL again, there is no problem. But, I don't want to regenerate the soap client because of backward compatible reasons. This afternoon I found an article with solves my problem: http://spikesoftware.azurewebsites.net/?p=151#comment-396784
The problem now is that my C# client can't invoke most of the soap actions. I can't find out the reason why this is not working anymore.
The error I received is the following:
Message:
System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]
: Error in deserializing body of request message for operation
'GetWorkshops'. OperationFormatter encountered an invalid Message
body. Expected to find node type 'Element' with the name
'GetWorkshops' and namespace 'http://tempuri.org/'. Found node type
'Element' with name 'GetWorkshops_V2' and namespace
'http://tempuri.org/'
The operation contract for these two methods like this:
[OperationContract(Action = "GetWorkshops", Name = "GetWorkshops")]
WorkshopResponse GetWorkshops(<some parameters>)
[OperationContract (Action = "GetWorkshops_V2", Name = "GetWorkshops_V2")]
WorkshopResponse_V2 GetWorkshopsV2(<some parameters>)
Can someone help me?
You can try out a couple of things,
Please use wsHttpBinding instead of basicHttpBinding
Generate a client proxy using svcutil
When I send a SOAP request to my service in the IIS locally, everything works fine.
When I send a SOAP request to the same service that running on IIS on another host, everything works fine.
But when another programmer sends a SOAP request to my service, he generally gets the right response except one method in the service that returns:
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Server was unable to process request. ---> Object reference not set to an instance of an object.</faultstring>
<detail />
</soap:Fault>
I need to understand why he is receiving this error.
His SOAP request is exactly the same as SOAP Request yet mine works and his does not.
The "Object reference" error is the hardest to troubleshoot if you don't know exactly where the error is occurring. Be sure to test for null values, as the most obvious cause for this error is an object not being initialized or a variable having a null value when it's expected to contain an object or a value.
Also, be sure that you're following best practices for error handling. Try to catch the errors at the earliest possible level unless you intentionally intend to let a higher-level error handler catch the error. The fact that you're getting this error means that the error handling is not sufficient.
Finally, I'd strongly recommend including some sort of logging mechanism for your error handlers. Save the errors to the Event Log, or a database, or even email them - anything, so that you can tell exactly where the error is. Do NOT display the error back to the user.
There are several options for this. Asp.Net Health Monitoring works fine in web services as well as standard asp.net sites. There's also ELMAH, or you can write your own code to do this.
If you follow these guidelines, you won't be in a situation where you don't understand how the error is happening. You'll have the information you need to troubleshoot properly, and your apps will be more solid.
Thanks guys for all your help. I solved the problem.
The 'SoapAction' field in the soap request had the wrong URI
I recommend using a HTTP sniffer. The http sniffer will show the SOAP properties.
The "SOAPAction" property should have something like : http://tempuri.org/YourServiceMethodName
Perhaps I'm overlooking something, but can client WCF not handle a server response that isn't a 200? For example, I'm trying to consume a service that returns a 400 when you asked for something naughty, but the body of the response is still a perfectly good and consumable SOAP message. It does the same for requested data that doesn't exist, returning a 404 but still having good hints about what the problem is. The WCF proxy seems to just puke and I can't get at the underlying body of the message.
Is that really how it rolls?
The only way to do this is to capture the protocol exception and then manually unserialize the envelope. The channel is hard coded to always throw a fault anytime an non 200 web response.