Doc/Literal/Bare

Craig spent last week at the house, working with me and other members of my team at a little coding off-site. One of the things we talked about was building doc/literal Web services that are bare. Craig wrote it up yesterday (what else would he do on a Sunday afternoon?) and put the squeeze on me to post my thoughts in response to the comments from Rich. So, here goes...

Doc/literal Web services describe their input and output message formats entirely in terms of schema. When ASMX generates a WSDL definition for a [WebMethod], its default behavior is to create an element whose name reflects the name of the operation. Craig used this example:

[WebMethod]
[return: XmlElement("sum")]
public int Add(int x, int y) { return x + y; }

The schema definition of the request and messages for this operation looks like this:

<xs:element name="Add">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="x" type="xs:int" />
      <xs:element name="y" type="xs:int" />
    </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="AddResponse">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="sum" type="xs:int" />
    </xs:sequence>
  </xs:complexType>
</xs:element>

The outer Add/AddResponse element is generated from the method name and it's content model is generated from the parameter list/return value. This type of service is described as doc/literal/wrapped because the operation name defines the outer wrapper element for both the request and response messages.

I never write my services this way.

Instead, I write services that are doc/literal/bare. Bare services differ from wrapped services in that the operation name has no impact on the structure of the message carried in an envelope's body. You make a service bare setting the [SoapDocumentMethod] attribute's ParameterStyle property to SoapParameterStyle.Bare. Here is an example:

public class Add
{
  public int x;
  public int y;
}

public class AddResponse
{
  public int sum;
}

public class Math
{
  [WebMethod]
  [SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
  [return: XmlElement("AddResponse")]
  public AddResponse Add(Add req)
  {
    AddResponse resp = new AddResponse();
    resp = req.x + req.y;
    return resp;
  }
}

In this case, the schemas for the input and output messages are generated entirely off the Add and AddResponse types. The Add method only binds the two together as the input/output of an operation in the generated WSDL portType. Here is a schema fragment for the messages:

<xs:element name="Add">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="x" type="xs:int" />
      <xs:element name="y" type="xs:int" />
    </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="AddResponse" type="tns:AddResponse" />
<xs:complexType name="AddResponse">
  <xs:sequence>
    <xs:element name="sum" type="xs:int" />
  </xs:sequence>
</xs:complexType>

If you look closely, you'll see that these definitions are identical to the ones above (except for the use of an explicit named type for the response message, but that's irrelevant here.) So what is the point of introducing these "message types"?

1) They provide the most natural mapping to how XML messaging actually works. I design my services starting with XML and message exchanges, going to XSD and WSDL, then to code. This is the most natural projection into code that I could come up within, given the limitations of ASMX.

2) I now have a type that represents a message. This is better than a signature that represents a message because I can use it in other places. Perhaps I want to queue messages for async processing. Or store them in a file or a database. Or... your guess is as good as mine.

3) If I want to, I can process the entire message body as XML. This isn't possible with a wrapped service, where the dispatching process consumes the outer wrapper element before your code gets called.

4) I can build operations that accept multiple message formats by marking the single input or output argument with multiple [XmlElement] attributes and typing the argument as object or any common base type (or marking it with [XmlAnyElement] and typing it as XmlElement). This provides lots of flexibility. For instance, you could use it to handle two message formats representing different message versions with a breaking change (if it was a non-breaking change, you could model it with one message using a range of techniques I'll post about at some point.) Note that this technique doesn't work with the ASMX WSDL generator. In general, the dispatcher is smarter than the WSDL generator. If you are willing to write WSDL by hand, you gain a lot of freedom.

5) You can implement IXmlSerializable as a way to stream the body of your messages. This interface is even better in Whidbey.

6) You can completely decouple the action URI, the qname of the element in the body, and the operation name. This has two benefits. First, you can use one message format with multiple actions. For instance, a MathRequest message could work with both an Add and a Subtract action. (Richard noted in response to Craig's post that reliance on the soapAction HTTP header to identify the intent of your message was not a good idea. I agree: I use the wsa:Action SOAP header instead. WS-Addressing - or parts of it - really are just missing pieces from SOAP.) Second, operation name is no longer relevant. If you look closely at specs like WS-Eventing, you'll see that they describe the world solely in terms of message formats and action URIs, not WSDL operatio names (yes, there is a WSDL for WS-Eventing, but it's non-normative.) This degree of flexibility is very very useful.


Posted Jun 29 2004, 02:32 PM by tim-ewald

Comments

David wrote re: Doc/Literal/Bare
on 06-29-2004 3:15 PM
I prefer bare as well. But I don't think it works with Axis, and I also don't think it is allowed to WS-I Basic Profile 1.0. Can you comment on these issues? Thanks, David
Simon Fell > Its just code wrote Doc/Literal/Bare
on 06-29-2004 7:11 PM
Tim has a post about Doc/Literal/Bare style web services in .NET over on his new blog. For the PocketSOAPers out there, this is exactly what the PocketSOAP WSDL wizard will generate.
Tim wrote re: Doc/Literal/Bare
on 06-30-2004 5:58 AM
I don't know if it works with Axis, I'll try to find out. The WS-I Basic Profile does not address wrapped vs. bare directly. However, it does require that the body of the Envelope have a single child element. If you map your messages to types and implement operations with one input argument and a return value, then you'll meet this criteria. If you have multiple arguments (as Craig did in his original example), you'll end up with multiple children of the body, which the BP doesn't like. There is potentially also an issue around what the BP calls "operation signatures". It's a requirement that every operation in a given binding have a unique qname for the child of body. So having two operations with the same body but different action URIs (as I described in 6 above) is disallowed within a single binding. I argued hard against that requirement at the time, but lost. It has a pretty profound impact on some designs. :-(

Tim-

JIS wrote Doc/Literal/Bare
on 06-30-2004 8:06 AM
JIS wrote Doc/Literal/Bare
on 06-30-2004 8:39 AM
David wrote re: Doc/Literal/Bare
on 06-30-2004 2:16 PM
Tim, thanks for clarifying that! And what a pitty that you were not more successfull...
David wrote re: Doc/Literal/Bare
on 06-30-2004 2:17 PM
Oh, and if I remember correctly, Axis uses the name of the top element in body to dispatch the method, and not the SOAPAction, which is why you were sort of limited at some point if you wanted to interop with them. Although their point of view seems to be in BP-I now...
Credit wrote re: Doc/Literal/Bare
on 07-01-2004 4:14 PM
Bare is the only way to go!
CraigBlog wrote re: I Like It Bare
on 07-02-2004 10:15 AM
Stefan Tilkov's Random Stuff wrote Doc/Literal/Bare
on 07-03-2004 1:14 PM
Doc/Literal/Bare...
CraigBlog wrote Busted
on 07-07-2004 5:25 AM
CraigBlog wrote I Like It Bare
on 07-07-2004 5:27 AM
RS wrote re: Doc/Literal/Bare
on 07-14-2004 1:14 PM
You said " I design my services starting with XML and message exchanges, going to XSD and WSDL, then to code. ".

I thought the most natural way to do the programming is to think about your problem domain, design your objects model and then code. Why we should worry about how this object going to look on the wire or will it will produce pretty XML. These details should be taken care by tools, Library (WSE )etc.Specailly when i know my service will live in Windows world.

May be this is a right way for you do the work as you may be writing the tools which the rest of the world will use, I am wondering do you think the 98%, the rest of developer should wonder about there objects on wire? Is our expectation to have a abstraction from the wire format to my Objects is too much asking?

Starting from XML and reaching to code seems backwards or is it year 2000 way of programming and OOPS is out, XML is in.
you've been HAACKED wrote Why Should I Care About The Wire Format In SOAP?
on 07-23-2004 2:44 PM
At Your Service wrote I refuse to let the angle brackets fall where they may!
on 07-23-2004 3:36 PM
At Your Service wrote I refuse to let the angle brackets fall where they may!
on 07-23-2004 3:53 PM
Sergio wrote re: Doc/Literal/Bare
on 08-12-2004 9:49 PM
RS:

XML in SOA is data contract, schema contract. Not serialization of business objects.

That's why it is important to desing the XML as a base for service contracts. Then, design the appropiate object model to deal with that. By the way, this object model should be decoupled with your business model, because web services live in the Service Layer, not Business Layer.

At leas it is how I see it.
At Your Service wrote Comments on WS-I profiling XSD
on 09-02-2004 9:41 AM
... wrote re: Doc/Literal/Bare
on 01-31-2009 9:28 PM

Nice site really!

fzlsbi wrote re: Doc/Literal/Bare
on 03-22-2009 2:50 PM

cE2NDR  <a href="gznzsmsawbpk.com/.../a>, [url=http://sutctknxvwtw.com/]sutctknxvwtw[/url], [link=http://jyreqlwijfbi.com/]jyreqlwijfbi[/link], http://uwzavfkpbyzu.com/

tpbtpwjpr wrote re: Doc/Literal/Bare
on 03-25-2009 5:40 PM

wxJyDz  <a href="frvhxvsdzktf.com/.../a>, [url=http://ezjfqrakjzng.com/]ezjfqrakjzng[/url], [link=http://jhwsmupqjzab.com/]jhwsmupqjzab[/link], http://ahxqbptubhwl.com/

tymratwr wrote re: Doc/Literal/Bare
on 04-18-2009 9:03 AM

EwyhI6  <a href="vuxoenrlejui.com/.../a>, [url=http://qczzrxdihnxk.com/]qczzrxdihnxk[/url], [link=http://qymldsghbuto.com/]qymldsghbuto[/link], http://gupsijncfqak.com/

areisvjdw wrote re: Doc/Literal/Bare
on 06-02-2009 7:40 AM

yFDp04  <a href="aukmiahimlfb.com/.../a>, [url=http://lpgfxnnpescs.com/]lpgfxnnpescs[/url], [link=http://vqzkvjxfdpxn.com/]vqzkvjxfdpxn[/link], http://ndodypqkkned.com/

hxdkwpcgesb wrote re: Doc/Literal/Bare
on 06-04-2009 10:55 AM

iAVACA  <a href="gkbicesenwlp.com/.../a>, [url=http://xnzfpqfzgqjy.com/]xnzfpqfzgqjy[/url], [link=http://ictjhabxeadg.com/]ictjhabxeadg[/link], http://zahouaaeplzk.com/

Add a Comment

(required)  
(optional)
(required)  
Remember Me?