How to improve the messaging experience
This post is part of Issue 5’s answer
Messaging means that you really care about messages. But looking at our example, do we really care about them?
You might say yes, because we define a CLR message that acts as the argument type for our [WebMethod]. But do we really care about the message on the wire? Definitely not, but let’s proof it:
[WebMethod]
[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
public Issue5RespMsg DoSomething(Issue5ReqMsg reqMsg)
The above signature accepts the following message format on the wire:
<soap:Body>
<reqMsg xmlns="uri:isssue5/wsdl">
<something xmlns="uri:isssue5/types">6</something>
</reqMsg>
</soap:Body>
So far so good, but guess what happens if we alter the name of the argument to MyReqMsg:
[WebMethod]
[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
public Issue5RespMsg DoSomething(Issue5ReqMsg MyReqMsg)
Although we don’t change the methods signature and therefore don’t break any CLR related dependencies we’re breaking the messaging contract! Strange eh, but here’s the message that the [WebMethod] accepts now:
<soap:Body>
<MyReqMsgxmlns="uri:isssue5/wsdl">
<something xmlns="uri:isssue5/types">6</something>
</MyReqMsg>
</soap:Body>
It’s pretty obvious that the decoupling between the internal programming and the external messaging model needs some improvement. You may argue that if you’re using SoapParameterStyle.Wrapped instead of SoapParameterStyle.Bare this problem wouldn’t exist. This is right, but you would still bind the [WebMethod]’s name to the message which isn’t much better than binding it to the name of an argument.
To really decouple these two programming models you have to define additional .NET attributes to control the way [WebMethod] exposes its messaging behavior and capabilities. To do so, we simply specify the name for the generated message element. It’s important to do this for the request as well as the response message.
[WebMethod]
[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
[return: XmlElement("Issue5RespMsg")]
public Issue5RespMsg DoSomething (
[XmlElement("Issue5ReqMsg")] Issue5ReqMsg MyReqMsg)
{
}
By doing so, the accepted request and generated response messages looks the following:
Request message:
<soap:Body>
< Issue5ReqMsgxmlns ="uri:isssue5/wsdl">
<something xmlns="uri:isssue5/types">6</something>
</Issue5ReqMsg>
</soap:Body>
Response message:
<soap:Body>
< Issue5RespMsgxmlns ="uri:isssue5/wsdl">
<something xmlns="uri:isssue5/types">6</something>
</Issue5RespMsg>
</soap:Body>
Now, we’ve really decoupled the messaging from the internal programming model.
The last post in this answer series is going to discuss how this could be achieved even smarter. Stay tuned…