views:

210

answers:

3

I am currently building a new version of webservice that my company already provides. The current webservice has an input parameter of type string. In that string an entire xml doc is passed. We then validate that string against an xsd (the same xsd given to the consumer). It looks something like this:

[WebMethod]
public bool Upload(string xml)
{
    if (ValidateXML(xml))
    {
        //Do something
    }
}

I am building the next version of this service. I was under the impression that passing an XML doc as a string is not the correct way to do this. I was thinking that my service would look something like this:

[WebMethod]
public bool Upload(int referenceID, string referenceName, //etc...)
{
    //Do something
}

This issue that I am having is that in actuality there are a large amount of input parameters and some of them are complex types. For example, the Upload Method needs to take in a complex object called an Allocation. This object is actually made up of several integers, decimal values, strings, and other complex objects. Should I build the webservice like so:

[WebMethod]
public bool Upload(int referenceID, string referenceName, Allocation referenceAllocation)
{
    //Do something
}

Or is there a different way to do this?

Note: this Allocation object has a hierarchy in the xsd that was provided for the old service.

Could it be that the original service only took in xml to combat this problem? Is there a better way to take in complex types to a webservice?

Note: This is a C# 2.0 webservice.

+1  A: 

I would probably use the XSD with "xsd.exe" tool to create a XML Serializable object. Then you can deal with objects instead of string parameters. It also gives you the ability to not change the signatures of the WebService.

If you change the XSD to add another parameter all you will need to do is recreate the class again using XSD.exe tool. Make good use of partial classes here. Separate your auto generated class from your business logic. This way you can recreate the the class definition if the XSD changes as many times as you want, but not touch your business logic.

XML Serialization in the .NET Framework

If you were using 3.5, you could also use LINQ to XML to quickly parse out your XML parameters.

Stan R.
Does it matter that I do not know what coding language the consumer is using? I have some clients using Java and others using .NET
Jon
As long as *your code* expects a specific XML it will come in as an xml string, then you can do whatever you want with it. i.e. deserialize it back to your object. If all of your clients follow the XSD you provided then its not an issue.
Stan R.
Yes, provide your clients with WSDL and XSD and don't parse the XML yourself!LINQ to XML is definitely an overkill here (and not available in .NET 2.0). (De)serializing objects like response and request classes for the Web methods in the original question shouldn't take more than applying attributes like *[XmlRoot]*, *[XmlElement]*, and *[XmlArrayItem]* in the right places.
azheglov
A: 

As long as your complex types are in some way XmlSerializable, then you shouldn't have any problems just using those complex types. Let the framework do the heavy lifting for you. It will generate an appropriate WSDL and the data will get serialized all by itself rather than you having to worry about validation and serialization.

[Serializable] is your friend.

Justin Niessner
Does it matter that I do not know what coding language the consumer is using? I have some clients using Java and others using .NET
Jon
Nope...as long as the language calls your service with the valid XML, your service should work fine.
Justin Niessner
A: 

Jon, to answer your follow-up question first: If your clients are on multiple platforms (or at least, not all on .NET), the best approach is the so-called "WSDL-first". Define the service interface in WSDL - that's where services and methods will be defined - WSDL will reference a set of XSDs defining the data-holding objects passed to and returned from those methods. You can generate C# or Java code from WSDL/XSDs.

Back to your original question. For the same of maintainability, the best practice is to defined Request and Response classes for each web methods and never pass strings, bools, integers directly. For example,

// in your Web service class
[WebMethod]
public UploadResponse Upload( UploadRequest request ) {
    ...
}
...

[Serializable]
public class UploadResponse {
  public bool IsSuccessful {
    get { ... }
    set { ... }
  }
}

[Serializable]
public class UploadRequest {
  public Allocation ReferenceAllocation {
    get { ... }
    set { ... }
  }
  // define other request properties
  // ...
}

If you defined SOAP bindings in your WSDL file, UploadRequest object is extracted from the SOAP message and deserialized. By the time the control reaches your WebMethod implementation, you have a deserialized UploadRequest object in memory with all of its properties set.

To have a method like this: public bool Upload(string xml) in a [WebService] class and parse XML inside the method implementation is definitely something you should consider moving away from.

azheglov