0

I have a third party WSDL file and XML Schema which I use to create the web service client. At large the WSDL looks as follows:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
                  xmlns:tns="http://sample.com/" 
                  xmlns:types="http://sample.com/types" 
                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                  xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
                  xmlns:ns="http://smaple.com/types" 
                  name="Sample" 
                  targetNamespace="http://sample.com/">
    <wsdl:types>
        <xsd:schema targetNamespace="http://sample.com/types" 
                xmlns="http://sample.com/types">
            <xsd:include schemaLocation="Sample.xsd"/>
            <xsd:element name="testReq" type="TestRequestMessage">
            </xsd:element>
      <xsd:element name="testRes" type="TestResponseMessage">
      </xsd:element>
        </xsd:schema>
    </wsdl:types>
    <wsdl:message name="TestReqMessage">
        <wsdl:part name="testReq" element="types:testReq"/>
    </wsdl:message>
    <wsdl:message name="TestResMessage">
        <wsdl:part name="testRes" element="types:testRes"/>
    </wsdl:message>
    <wsdl:portType name="Test_portType">
        <wsdl:operation name="TestOp">
            <wsdl:input message="tns:TestReqMessage"/>
            <wsdl:output message="tns:TestResMessage"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="Test_Binding" type="tns:Test_portType">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="TestOp">
            <soap:operation soapAction="urn:#TestOp" style="document"/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="Test_XMLService">
        <wsdl:port name="Test-port" binding="tns:Test_Binding">
            <soap:address location="http://dummy.sample.com/Test-port"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

This is the XML schema:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
            xmlns="http://sample.com/types" 
            xmlns:altova="http://www.altova.com/xml-schema-extensions" 
            targetNamespace="http://sample.com/types" 
            elementFormDefault="qualified">
    <!-- -->
    <!--Root elements -->
    <!-- -->
    <xsd:element name="TestRequestMessageElement" type="TestRequestMessage">
        <xsd:annotation>
            <xsd:documentation>Request</xsd:documentation>
        </xsd:annotation>
    </xsd:element>
  <xsd:element name="TestResponseMessageElement" type="TestResponseMessage">
    <xsd:annotation>
      <xsd:documentation>Response</xsd:documentation>
    </xsd:annotation>
  </xsd:element>
    <!-- -->
    <!--Complex types -->
    <!-- -->
  <xsd:complexType name="TestResponseMessage">
    <xsd:sequence>
      <xsd:element name="el1" type="Element1">
      </xsd:element>
      <xsd:element name="el2" type="Element2">
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>
    <xsd:complexType name="TestRequestMessage">
        <xsd:sequence>
            <xsd:element name="el1" type="Element1">
            </xsd:element>
            <xsd:element name="el2" type="Element2">
            </xsd:element>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="Element2">
        <xsd:sequence>
            <xsd:element name="no1">
                <xsd:simpleType>
                    <xsd:restriction base="xsd:integer">
                        <xsd:minInclusive value="0"/>
                        <xsd:maxInclusive value="9"/>
                    </xsd:restriction>
                </xsd:simpleType>
            </xsd:element>
            <xsd:element name="no2">
                <xsd:simpleType>
                    <xsd:restriction base="xsd:integer">
                        <xsd:minInclusive value="0"/>
                        <xsd:maxInclusive value="99999999"/>
                    </xsd:restriction>
                </xsd:simpleType>
            </xsd:element>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="Element1">
        <xsd:sequence>
            <xsd:element name="no3" minOccurs="0">
            </xsd:element>
            <xsd:element name="date1" type="xsd:dateTime" minOccurs="0">
            </xsd:element>
        </xsd:sequence>
    </xsd:complexType>
</xsd:schema>

I used svcutil to generate classes from the WSDL file with the following command: svcutil Sample.wsdl Sample.xsd.

What I now want to do in my application is validate the object instances of these types before passing them on to a web service. I tried to do that by serializing such an instance using XmlSerializer and performing validation using the XmlReader:

TestRequestMessage msg = new TestRequestMessage();
msg.el1 = new ...

using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(schemaName))
{
    XmlSchema schema = XmlSchema.Read(stream, SchemaValidationHandler);
    XmlSchemaSet schemas = new XmlSchemaSet();
    schemas.Add(schema);

    using (MemoryStream memStream = new MemoryStream())
    {
        XmlSerializer ser = new XmlSerializer(typeof(RequestMessage));
        ser.Serialize(memStream, msg);
        memStream.Position = 0;

        bool errors = false;

        XmlReaderSettings settings = new XmlReaderSettings();
        settings.Schemas = schemas;
        settings.ValidationType = ValidationType.Schema;
        settings.ValidationEventHandler += (o, e) => {
            // act on validation error
        };

        using (XmlReader reader = XmlReader.Create(memStream, settings)) {
            while (reader.Read()) {}
        }

The problem now is that the validation does not fail, even if I don't set all required properties or set some invalid values according to schema restrictions.

Having a closer look at the generated classes I realized that the root elements are not in the namespace they should be.

Funny enough if I run xsd.exe Sample.xsd the generated classes are put in the correct namespace, i.e. the XmlRootAttribute is set with the correct name and namespace in contrast to the generated code using svcutil.

What I also tried to do is reuse the generated classes from the xsd.exe tool in my svcutil command using the reference switch. But this resulted in errors saying that the System.Runtime.dll could not be found.

However what I'd like to do is create the client code including the necessary type classes with svcutil. How can I do that correctly?

Any help is greatly appreciated.

Marc
  • 23
  • 9
  • 1
    If your root element is in the wrong namespace, the validator will think it's just some unknown element and not try to validate its contents. You can turn on warnings to catch this problem, see [XML validation and namespaces in .NET](https://stackoverflow.com/q/15428265/3744182), [Partial XML file validation using XSD](https://stackoverflow.com/a/37012935/3744182) and [XDocument.Validate is always successful](https://stackoverflow.com/q/17232575/3744182). – dbc Nov 06 '20 at 23:28
  • As to why `svcutil` generated classes with the wrong namespace, we would need to see a [mcve]. – dbc Nov 06 '20 at 23:28
  • Thanks for your hint. I did some more checking and edited my question with some sample wsdl and xsd content with which you can reproduce the problem. – Marc Nov 08 '20 at 18:56

0 Answers0