This post originated from an RSS feed registered with .NET Buzz
by Scott Hanselman.
Original Post: Doc/Literal/Bare in XML Web Services - my thoughts on all this.
Feed Title: Scott Hanselman's ComputerZen.com
Feed URL: http://radio-weblogs.com/0106747/rss.xml
Feed Description: Scott Hanselman's ComputerZen.com is a .NET/WebServices/XML Weblog. I offer details of obscurities (internals of ASP.NET, WebServices, XML, etc) and best practices from real world scenarios.
Apparently Craig
Andera and Tim
Ewald were recently working on an MSDN code rewrite and were talking about
building doc/literal/bare Web Services vs. doc/literal/wrapped.
I'm a little confused by their respective posts, as they appear to say too different
things. (Coming up on Fox, When Smart People Disagree!) They were both
in the same house, coding the same stuff, but Craig's conclusion about how to use
SoapParameterStyle.Bare is very different than Tim's (and mine).
Tim suggests that getting an AddResponse type "for free" when writing code like this:
//SDH: This is bad, avoid it [WebMethod]
[return: XmlElement("sum")]
public int Add(int x, int y) { return x + y; }
is lame, and I agree. The generared AddResponse type is totally magic, coming
(by magic) from the Method name, which is a little too tightly-coupled for my tastes.
Instead, your functions should take as parameters and return as reponses formal types
that you control. Then you can use the [SoapDocumentMethod(ParameterStyle
= SoapParameterStyle.Bare)] attribute to avoid any extra automagically-added wrapped
elements. This is purely a coding convention, it's not expressed in WSDL.
//SDH: This is not bad, embrace it. [WebMethod]
[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
[return: XmlElement("AddResponse")]
public AddResponse Add(AddRequest req)
{
AddResponse resp = new AddResponse();
resp = req.x + req.y;
return resp;
}
Tim's right on with this. We do the same thing at Corillian with our code-generation
stuff (maybe I'll present on it sometime.) You can reuse the Request and Response
messages this way, as well as take and return base classes.
However, Craig had a different view. He simply added the bare attribute to the
method call:
//SDH: This is bad, think twice
[WebMethod]
[SoapDocumentMethod(ParameterStyle=SoapParameterStyle.Bare)]
public int Add(int x, int y) { return x + y; }
Which is a non-WS-I
Basic Profile compliant Web Service, as it has more than one child node under
<soap:Body>. Craig muses "To
me, this just seems like nicer XML; more like how I would do it if I were just using
XmlWriter and raw sockets." I totally disagree with that statement, as XML Web
Services are decidedly NOT about that level of abstraction. If you like talking
with XmlWriter and raw sockets, why not yank the <soap:envelope> and those pesky
namespaces? ;) If so, there's already a
spec for you.
Additionally this places even more pressure on the HTTP SOAPAction header,
which was always a bad idea. Fundamentally (at least in my World View)
SOAP messages should be transport neutral and that's what wsa:Action is for.
So, conclusion? Be explicit. Use Request and Response messages
as ins and outs for your Web Services, call them out and use SoapParameterStyle.Bare
to avoid the extra wrapping element. Tim's list
of reasons why is excellent.