C# Generated SOAP Client Custom Converter - c#

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.

Related

Consume SOAP webservice with GET instead of POST

I need to call an external SOAP webservice over HTTP.
I have the WSDL file and added it in Visual Studio via 'Add service reference'. Visual studio then added a number of files, in the reference file i can find this:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="Service.IService")]
public interface IService {
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Function", ReplyAction="http://tempuri.org/IService/FunctionResponse")]
namespace.Service.ExecuteFunctionResponse ExecuteFunction(namespace.Service.FunctionRequest request);
}
With additionaly the async version of this call and the objects for sending an receiving, etc.
To call the service I added the folowing code:
BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("the address");
serviceChannel = new ServiceClient(binding, endpointAddress).ChannelFactory.CreateChannel();
Response response = serviceChannel.ExecuteFunction(new Request(...));
This results in me getting an exception, error 405 method not allowed.
So it appears I must use a HTTP GET request instead of the default POST request. But i cannot find where this can be altered in with this way of working.
So, where can i set the HTTP method for this call to a webservice?
SOAP services are using HTTP POST because they exchange XML messages (which tend to be complex) and cannot be transferred in a query string.
Are you sure that you must use HTTP GET? Maybe the error you are receiving "405 method not allowed" is caused by some bad configuration.
I would double check the SOAP endpoint URL is set correctly and check that there are no additional security requirements needed.
EDIT
In past, there was a practice to create ASP.NET Web Services which would accept GET as well. But they wouldn't expect XML messages. Instead, you would have to pass all parameters in a querystring. For example: https://foo.bar/service.asmx/Func?param1=X&param2=Y (where param1 and param2 are the expected parameters).
This way it is possible to call a WebService without a need for WSDL and using GET method. You can achieve it by using HttpClient for example.
The downside of this approach is that you will have to deal with plain data instead of objects.
I hope it might help.

Write Custom message for large request in WCF

I limited my WCF service to allow requests up to 1 MB. This is done via binding configuration in web.config. This is working fine and client is getting 413 error code back in response. The only problem is the response body is empty. I want to include custom message in response body but I don't find a way to do it as .NET handles it automatically.
Let me know if anyone know how to add custom message in response of large requests.

.Net code to catch an HTTP 500 error response from an .asmx web service

Is there a way to catch the HTTP 500 error returned by an .asmx web service from a .Net client?
Using .Net 4.5 (VS2015), the .Net client code consumes the .asmx web service and calls it using the code below:
var client = new WebserviceApi.MyServiceSoapClient();
var response = client.MyWebServiceMethod();
If the .asmx web service returns an HTTP 500 error with a SOAP message containing the error message details, the "response" variable is set to null.
Using Fiddler, the traffic shows the HTTP 500 response from the .asmx web service. The response contains a SOAP XML message with details on the error.
No exception is thrown or caught in the .Net client code, execution continues as normal.
This means there is no information for the client to pick up regarding the nature of the exception. All the client code can do is check if "response" is null, but the exception message is not available to the client code.
Is there any way to force the .Net client code to throw an exception if the .asmx web service returns an HTTP 500 response so that the error message can be checked/logged?
I had a similar problem for axis (java) web service. They were throwing exceptions that didn't appear on my side even though the response was really a HTTP 500.
I can't say for sure this will solve your case, but I solved mine overriding the GetWebResponse method and throwing the exception by myself when needed.
I did it by changing the web service client code generated by Visual Studio after adding Web Reference (generated file name is: Reference.cs, sometimes it's not visible in solution, you have to click 'Show All files' on top of the solution pane and then unfold your web service reference files.
internal class ChangedWebServiceClient : SomeSoapService
{
protected override WebResponse GetWebResponse(WebRequest request)
{
var response = base.GetWebResponse(request);
if (response != null)
{
var responseField = response.GetType().GetField("_base", BindingFlags.Instance | BindingFlags.NonPublic);
if (responseField != null)
{
var webResp = responseField.GetValue(response) as HttpWebResponse;
if (webResp != null)
{
if (webResp.StatusCode.Equals(HttpStatusCode.InternalServerError))
throw new WebException(
"HTTP 500 - Internal Server Error happened here. Or any other message that fits here well :)");
}
}
}
return response;
}
}
After researching this a bit, it appears that all errors thrown from ASMX are in the form of the SoapException class, so a try catch with that class should be enough to handle that error.
Further reading on ASMX exception handling
SoapException Class
nivlam also propsed a good solution to reading raw request data from ASMX and SOAP over on this answer and you could probably get error codes from there.
I had a similar problem some years ago. The problem with the HTTP 500 status code is that the service call doesn't reach the server. So you can't debug it. The solution that worked for me was making sure the parameters had the exact same schema as that of the web methods defined. Any mismatch in the data contracts may cause the HTTP 500 Internal Server Error.

WCF Service Trace shows UriFormatException

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.

Handle unknown soap message from WCF

I have a client generated using SVCUTIL from WSDL + XSD in C# .net console app. All fine but for some logical error handling purpose, client may receive a response message, which is not defined in WSDL hence deserialization & will fail but method does not throw exception but returns null.
Is there any generic way to handle this situation or I define a fault/error message xsd(for soap message returned by server) and in case of null response, handle/deserialize the message.
PS: My remote service can not throw a fault exception for logical errors.(yeah a bit of blockage there).
WSDL is contract. It is same like if you have two objects and defined interface between them. If the first object calls the operation on the second object it expects return value defined by interface. If we would use some non-strongly typed language the second object would be able to return different type of return value and the first object would fail because of unexpected error.
Programming languages have approach to solve this - in case of .NET you would use object type as return value and you would always have to manually investigate what type did you receive and how to handle the return value. In case of WCF we also have such high level type - System.ServiceModel.Channels.Message but you really don't want to use it because in such case you will have to build SOAP request manually and parse incoming responses manually.
As a side note in web services single request type has always single response type and zero or more error types (which are SOAP faults). If you have a service which returns different response types on single request type such service is not "valid" web service and cannot be described by WSDL. Because of that it also cannot be in strongly typed way provided by auto-generated WCF proxy.

Categories

Resources