views:

1683

answers:

1

Hi,

Background: I'm in the process of creating a web service using ASP.NET 2.0. This web service provides another interface to an existing web form which contains selection boxes dynamically populated from a database.

My first draft of the web service accepted a string for each of these and then ensured that it was valid, throwing back an error if it wasn't. However the consumer of the web service has asked, since the possible values aren't likely to change all that often, that we provide enumerated values in the WSDL.

I am reluctant to create an enumeration with my web service code, so I have instead altered the generated WSDL file and instructed my web service to use that instead of inspecting my classes to generate it.

WSDL:

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://example.org/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://example.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"&gt;
  <wsdl:types>
 <s:schema elementFormDefault="qualified" targetNamespace="http://example.org/"&gt;
   <s:element name="MyMethod">
  <s:complexType>
    <s:sequence>
   <s:element minOccurs="0" maxOccurs="1" name="myClass" type="tns:MyClass" />
    </s:sequence>
  </s:complexType>
   </s:element>
   <s:complexType name="MyClass">
  <s:sequence>
    <s:element minOccurs="0" maxOccurs="1" name="MyString" type="tns:MyStringPossibleValues" />
  </s:sequence>
   </s:complexType>
   <s:element name="MyMethodResponse">
  <s:complexType />
   </s:element>
   <s:simpleType name="MyStringPossibleValues">
  <s:restriction base="s:string">
    <s:enumeration value="alpha" />
    <s:enumeration value="bravo" />
  </s:restriction>
   </s:simpleType>
 </s:schema>
  </wsdl:types>
  <wsdl:message name="MyMethodSoapIn">
 <wsdl:part name="parameters" element="tns:MyMethod" />
  </wsdl:message>
  <wsdl:message name="MyMethodSoapOut">
 <wsdl:part name="parameters" element="tns:MyMethodResponse" />
  </wsdl:message>
  <wsdl:portType name="ExternalAccessSoap">
 <wsdl:operation name="MyMethod">
   <wsdl:input message="tns:MyMethodSoapIn" />
   <wsdl:output message="tns:MyMethodSoapOut" />
 </wsdl:operation>
  </wsdl:portType>
  <wsdl:portType name="ExternalAccessHttpGet" />
  <wsdl:portType name="ExternalAccessHttpPost" />
  <wsdl:binding name="ExternalAccessSoap" type="tns:ExternalAccessSoap">
 <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
 <wsdl:operation name="MyMethod">
   <soap:operation soapAction="http://example.org/MyMethod" style="document" />
   <wsdl:input>
  <soap:body use="literal" />
   </wsdl:input>
   <wsdl:output>
  <soap:body use="literal" />
   </wsdl:output>
 </wsdl:operation>
  </wsdl:binding>
  <wsdl:binding name="ExternalAccessSoap12" type="tns:ExternalAccessSoap">
 <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
 <wsdl:operation name="MyMethod">
   <soap12:operation soapAction="http://example.org/MyMethod" style="document" />
   <wsdl:input>
  <soap12:body use="literal" />
   </wsdl:input>
   <wsdl:output>
  <soap12:body use="literal" />
   </wsdl:output>
 </wsdl:operation>
  </wsdl:binding>
</wsdl:definitions>

Webservice:

namespace Example.Service
{
    [WebService(Namespace = "http://example.org/")]
    [WebServiceBinding(
        ConformsTo = WsiProfiles.BasicProfile1_1,
        Location="ExternalAccess.wsdl",
        Name="ExternalAccessSoap",
        Namespace = "http://example.org/")]
    [ToolboxItem(false)]
    public class ExternalAccess : System.Web.Services.WebService
    {
        public class MyClass
        {
            public string MyString;
        }

        [WebMethod]
        [SoapDocumentMethod(
            Action = "http://example.org/MyMethod",
            RequestNamespace = "http://example.org/",
            Binding="ExternalAccessSoap")]
        public void MyMethod(MyClass myClass)
        {
        }
    }
}

The problem: As the WSDL specifies an enumeration for MyString and the code specified a string type, ASP.NET does not manage to map the fields correctly.

Is there an attribute I can use to instruct the deserialiser to populate the string field with the value of the enumeration?

Regards,

Matt

+1  A: 

Having gone through the process of creating a soap extension to do this for me I discovered that MyString wasn't actually being sent to my web service.

This was because the test application for this service was built in .NET also and, when building the request object, the MyStringSpecified property of the generated proxy class was overlooked. This then prevented the enumerated value being sent as part of the SOAP request.

When this property was set to true, the enumerated value was successfully assigned to the MyString field in the webservice.

Matt