Why is WSE2’s SoapClient class abstract?

Ok, so the question in the title a little misleading… I actually know why it’s abstract, but what I don’t understand why it was designed that way. It forces me to always subclass it and add my own methods, decorated with SoapMethodAttribute, just so I can send a SoapEnvelope from client to server.

What’s lame about this is that all the information I need to send is in the SoapEnvelope already. I shouldn’t need to pass it through some special method decorated with one attribute to set the SOAP action. I understand that this design is intended to simplify the strongly typed approach that Microsoft seems to be pushing, but if I’ve got an XmlDocument rarin’ to go I should be able to just construct a SoapEnvelope set it up myself and pass the DocumentElement to SetBodyObject. The problem now is, there’s no easy way to make a call to a Request-Response style web method. You can send a SoapEnvelope one way easily using a SoapSender’s Send, but uhh… that unfortunately leaves you without a response. You can also receive a SoapEnvelope easily using SoapReceiver’s Receive. The fact that you can’t SendRequestResponse with SoapClient without subclassing it (because it’s protected) just seems like a silly design decision.

In the end, I end up with a a class like this:

public sealed class MyWebServiceClient : SoapClient
{
    public MyWebServiceClient(EndpointReference endpointReference) : base(endpointReference)
    {
    }

    [SoapMethod("uri:SomeService:SomeMethod")]
    public SoapEnvelope DoSomething(SoapEnvelope requestEnvelope)
    {
        return base.SendRequestResponse(“DoSomething“, requestEnvelope);
    }
}

To call it like this:

XmlDocument document = new XmlDocument();
document.Load("somefile.xml");

SoapEnvelope envelope = new SoapEnvelope();
envelope.SetBodyObject(document.DocumentElement);

MyWebServiceClient client = new MyWebServiceClient();
client.DoSomething(envelope);

What did writing the proxy really buy me in this case? The following call that I could have written myself much more easily:

envelope.Context.Addressing.Action = new Action("uri:uri:SomeService:SomeMethod");

Leave a Reply