Blog Home  Sign In RSS 2.0 Atom 1.0 CDF  

  def Softwaremaker() :
         return "William Tay", "<Challenging Conventions />"

  knownType_Serialize, about = Softwaremaker()
 

 Thursday, May 05, 2005
« Geek Extrodinaire: WS-Inteview with MSDN... | Main | Quoted in the press: An Open (OSS) Question »

Fellow Microsoft Regional Director and a software legend, Rocky Lhotka posted an interesting entry on Message-based WebMethod "overloading" here.

In it, he recommends (and I quote) that service methods use a request/response or just request method signature: 

   response = f(request)

or

   f(request)

 "request" and "response" are both messages, defined by a type or schema (with a little "s", not necessarily XSD).

The actual procedure, f, is then implemented as a Message Router, routing each call to an appropriate handler method depending on the specific type of the request message.

I couldnt agree more. While easier to comprehend, the practice of passing parameters to a Web Method call often sends the wrong messages across as (W3C) SOAP as just another RPC. Ultimately, if you have no idea and dont even want to grok the innards of the XMLSerializer, you would really think you are passing method parameters across or worse, think that you are ferrying objects across the wire.

Therefore, I firmly believe that it is for the good of all if you explicity specify that you are expecting a XMLDocument / XMLElement / XMLNode and you will dispatch the same on your endpoint. What you do at your implementation (whether it is serializing from a type to deserializing from one) is placed squarely at the mercy of the tools in your hand or the knowledge in your head.

With the current state of tools (or lack there-of) today, I sit on the same camp as Aaron Skonnard and Christian Weyer (plus others, I believe) as I believe firmly in the contract-first approach. Good devs should dig what is going on as close to the wire as possible, at least once. Then they can use all the wizards and helpers they want. This will help them understand better what is going on if they should need to troubleshoot later (leaky abstractions) or find other ways to improve performance.

This is just something that my team and me here have gathered over the years esp when I have got many developers out there working on the same solution offshore in different countries.

While I agree that not many people out there enjoy or want to grok the angle brackets and that the lack of tools out there is hugely to be blamed, tools make a productive developer but not necessarily a proficient one.

Until today, I still come across developers that still think Web Services are still about transferring an object across the wire. Having terms like "Web References" and "proxies", even deemed to be more abstract and dev-friendly, does potray the wrong ideas across.

I have always recommended younger developers who are interested in learning about Web Services / ASMX and SOAP to try out the (just-now-defunct) Microsoft SOAP Toolkit first before moving on. I find that to be a great interesting way to learn about XML SOAP Services as abstractions are kept to a minimum. Another great SOAP Toolkit in the face of Microsoft's non-supporting stance of its own is Simon Fell's PocketSOAP.

Another fellow Regional Director, Bill Wagner (who authored an very impressive book "Effective C#") posted his solution to Rocky's post here. I have used the same sort of approach that Bill had documented before and it is good and does serve its purpose. However (and please correct me if I am wrong), it bounds the message contracts and datatypes tightly to the WSDL. If I am going to add a third Request / Response pair of classes, it will render my initial WSDL invalid (unless of course, if I am willing to add an additional endpoint)

I worked on a project before which specify that (newer) datatypes are to be added in phases and therefore, we had to decouple the XSD from the WSDL (which is in accordance with one of the best practice of WSDL Deployments -- modular and the separation of concerns). Oh, by the way, this is practiced in Indigo.

I don't know if there is a way to decouple the XSDs from the WSDL in VS2003 today. Even if there is, I am guessing it is a difficult hack at best. So, what I did was to create the XSDs for each datatype as they come along and do a XSD import in my WSDL. At my message exchange contract, I used an open content type with xsd:any. Thereafter, I author my own WSDL with the help of Christian's and Thinktecture's WSContractFirst. Since the message and the datatype XSDs are all imported, the wsdl actually has a small footprint now. With the wsdl /server switch, xsd:any becomes an XMLElement type. For abstraction within my service, I changed it to an object in my implementation detail.

Note: .NET 1.1's WSDL.exe /server switch, in my mind, is still fairly limited and comes with a couple of annoying things I didn't like BUT I will expand this in detail later.

[System.Xml.Serialization.XmlTypeAttribute([Namespace]:="urn:softwaremaker-n
et.swmstoreexchangemessages"]> _
Public Class Response
  Public Result As Result
End Class

[System.Xml.Serialization.XmlTypeAttribute([Namespace]:="urn:softwaremaker-n
et.swmstoreexchangemessages")] _
Public Class Result
  [System.Xml.Serialization.XmlElement(ElementName:="Book",
Type:=GetType(BookType),
Namespace:="urn:softwaremaker-net.swmstoreextendedtypes"), _
  System.Xml.Serialization.XmlElement(ElementName:="CD",
Type:=GetType(CDType),
Namespace:="urn:softwaremaker-net.swmstoreextendedtypes"), _
  System.Xml.Serialization.XmlElement(ElementName:="Anything",
Type:=GetType(AnyType),
Namespace:="urn:softwaremaker-net.swmstoreextendedtypes")] _
  Public Any As Object
End Class

  Public Function
ProcessRequest([System.Xml.Serialization.XmlElementAttribute([Namespace]:="u
rn:softwaremaker-net.swmstoreexchangemessages")] ByVal Request As Object) As [System.Xml.Serialization.XmlElementAttribute("Response",
[Namespace]:="urn:softwaremaker-net.swmstoreexchangemessages")] Response
   '...
   End Function

Once the consumer points to my wsdl (I turned off documentation of asmx by default), all the XSDs are imported by VS2003 as well (and that is a good thing). The xsd:any is still an XMLElement over at their end and we leave it as it is since we cannot control what they do there. The consumer can choose to deal with the raw XML if they want to OR do an xsd.exe imported.xsd /c and let the XMLSerializer do its (limited) magic .

In this sense, no matter how many more datatypes I add or remove, my wire-contract remains the same. I just let the endpoints serialize / deserialize the open-content xml (xsd:any). In my project I had mentioned earlier, I have one asmx endpoint servicing multiple consumers each sending different messages that conforms to different XSDs (For example, GroupA sends BookType and GroupB sends the CDType as well as a GroupC next time that sends a type that is unknown to me today). The thing I need to take care of is to send the appropriate datatype xsd to the appropriate groups so they can serialize / deserialize into the appropriate types. As you can see from the code snippet above, at my asmx, I will just add any new datatypes that come along.

While, this may seem like too much compared to Bill's solution above, it was necessary to decouple the datatypes from my wsdl in that project and the XSD Editor (codenamed: daVinci ?) in VS.NET2003 was the best tool I had in hand at that time. Developers are too comfortable with objects. This is obviously natural with the decade-long evolution of Object-Orientation and the power of abstractions the OO tools and languages bring today.

However, other factors like time, extensibility, standardization make abstractions expensive...and among others, these are all factors that make up the principles of the move towards Service-Orientation. Now, if we have to make and designed services to be explicit, this means that devs need to know they are explicity invoking a service across the wire, how far can the tools go to hide all the plumbings and yet not hide the fact that the service is on the other side and not just a mere shadow copy of a remoting object that seems to reside on the same application domain.

Will Service-Orientation fail to hit the mainstream because of this ? I dont know. I guess only time will tell.

Thursday, May 05, 2005 2:22:18 AM (Malay Peninsula Standard Time, UTC+08:00)  #    Disclaimer 
  • Blog reactions