views:

491

answers:

2

I'm creating a web service with a variety of classes, many of which can contain references to other classes. Sometimes these "sub classes" have the same name (e.g. Customer and Customer), but are actually different, so I've placed these in different namespaces (e.g. MyRoot.Sub1, MyRoot.Sub2, etc.)

When I build the service, the generated WSDL places all of these classes at the top level, without specifying any delineation by sub-namespace. Therefore, it will define two versions of "Customer". Curiously, it doesn't complain during the build process.

When I host the service and try to reference it with a browser, I get the following error:

The top XML element 'Customer' from namespace 'RE: http://...' references distinct types MyRoot.Sub1.Customer and MyRoot.Sub2.Customer. Use XML attributes to specify another XML name or namespace for the element or types.

I looks like I could use XmlTypeAttribute TypeName to provide an unique class name, but this makes documentation quite a hassle, as everything's going to have two names. Considering the differentiation is already specified by the namespaces, is there any way to utilize that information? I haven't tried using TypeName="Sub1.Customer", etc., but none of the examples that I've seen use this notation, so I'm skeptical.

Is there something else obvious that I'm missing?

A: 

You are going to have to use the XmlType attribute to disambiguate the two Customer classes. The only value you will need to set is the namespace so that each Customer is in its own XML namespace.

See the following example:

namespace NS1
{
    [XmlType(Namespace="com.me.ns1")]
    public class Customer
    {
        public string FirstName;
        public string LastName;
    }
}

namespace NS2
{
    [XmlType(Namespace = "com.me.ns2")]
    public class Customer
    {
        public string Name;
    }
}

namespace WebService1
{
    [WebService(Namespace = "http://tempuri.org/")]
    public class Service1 : System.Web.Services.WebService
    {

        [WebMethod]
        public NS2.Customer HelloWorld(NS1.Customer customer)
        {
            return new NS2.Customer() { Name = customer.FirstName + " " + customer.LastName } ;
        }
    }
}

Disclaimer: just an example and not generally recommended coding practices. :)

Tuzo
Thanks. Right now the class has [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)], so I'll try adding that namespace attribute and see what happens. (Hopefully namespace and anonymous [added by XSD.EXE] aren't incompatible.) I find that MSDN's coverage of these attributes is a bit terse. ;)
Mike Hanson
You can add the Namespace parameter along with the AnonymousType parameter but it appears that the AnonymousType parameter will be ignored. i.e. the generated type will not be an XSD anonymous type.
Tuzo
So is there a problem with using the namespace attribute in this way, or does your disclaimer refer to the overall chunk of code in this example?
Mike Hanson
No, nothing to do with the attributes -- that is OK. More like having all namespaces jammed together (in one file) and having public instance variables. And the namespace naming is bad...
Tuzo
I tried this, and it fixes the "references distinct types" error, but the classes are still being derived at the top level. Instead of using ServiceRef.Sub1.Customer and ServiceRef.Sub2.Customer, one class appears as simply Customer and the other is Customer1. Also, I had to set the namespace for both the XmlRoot and XmlType attributes.
Mike Hanson
A: 

SOAP doesn't support hierarchical namespaces, so I've determined that there are only two solutions:

  • Ensure that the different classes are uniquely named across all methods in the Web Service
  • Break the single web service into multiple services, so that each has its own implicitly distinct namespace.

Since the latter option requires more administration (both in the code and within IIS), I decided to give the classes unique names. I may still end up breaking the service into multiples (for organization or load handling), but that's optional if the class names are unique.

Mike Hanson