Wout

I have three classes: A, B and C. A and B use the XmlSchemaProviderAttribute to define some specific schema. A uses the XmlReflectionImporter to get B's schema. Class B is nothing special, but has a ref to C. The resulting schema is missing the definition for C however (when dumping the schema's to the console). This seems to be a problem with the XmlReflectionImporter. I suspect this is a bug, could anyone at MS investigate Note that C does appear when C doesn't use the XmlSchemaProviderAttribute. Also C does appear when using it and just requesting XSD to make an xsd of class B.

Wout

Here's some code to reproduce (used in context of web services where I'm trying to avoid having property setters, just to satisfy the XmlSerializer, it would be awesome if you guys just added a .NET attribute to be able to serialize a property that only has a getter, I've run into this issue a lot by now):

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace XmlReflectionImporterTest {
    class Constants {
        public const string Namespace = "http://www.somenamespace.com/";
        public const string XmlNameSpace = "http://www.w3.org/2001/XMLSchema";
    }

    [XmlSchemaProvider("ProvideSchema")]
    public class A {
        private B b;

        public static XmlQualifiedName ProvideSchema(XmlSchemaSet schemaSet) {
            XmlSchemas schemas = new XmlSchemas();

            XmlReflectionImporter importer = new XmlReflectionImporter(Constants.Namespace);
            XmlSchemaExporter exporter = new XmlSchemaExporter(schemas);

            XmlTypeMapping bMapping = importer.ImportTypeMapping(typeof(B));
            exporter.ExportTypeMapping(bMapping);

            XmlTypeMapping cMapping = importer.ImportTypeMapping(typeof(C));
            exporter.ExportTypeMapping(cMapping);

            foreach (XmlSchema s in schemas) {
                Console.WriteLine("[");
                s.Write(Console.Out);
                Console.WriteLine("]");
                Console.WriteLine();
            }

            XmlSchema schema = schemas[Constants.Namespace];
            if (schema == null) {
                schema = new XmlSchema();
                schema.TargetNamespace = Constants.Namespace;
                schema.ElementFormDefault = XmlSchemaForm.Qualified;
                schemas.Add(schema);
            }

            XmlSchemaComplexType aType = new XmlSchemaComplexType();
            aType.Name = "A";
            schema.Items.Add(aType);

            XmlSchemaSequence sequence = new XmlSchemaSequence();
            aType.Particle = sequence;

            XmlSchemaElement blElement = new XmlSchemaElement();
            blElement.Name = "B";
            blElement.SchemaTypeName = new XmlQualifiedName(bMapping.XsdTypeName, bMapping.XsdTypeNamespace);
            sequence.Items.Add(blElement);

            foreach (XmlSchema s in schemas) {
                schemaSet.Add(s);
                if (
                    (s.TargetNamespace != null) &&
                    (s.TargetNamespace.Length > 0) &&
                    (s.TargetNamespace != Constants.Namespace)
                ) {
                    XmlSchemaImport import = new XmlSchemaImport();
                    import.Namespace = s.TargetNamespace;
                    schema.Includes.Add(import);
                }

            }

            return new XmlQualifiedName("A", Constants.Namespace);
        }
    }

    public class B {
        private C c;

        public C C {
            get { return c; }
            set { c = value; }
        }
    }

    [XmlSchemaProvider("ProvideSchema")]
    public class C : IXmlSerializable {
//    public class C {
        private double d;

        public double D {
            get { return d; }
            set { d = value; }
        }

        public static XmlQualifiedName ProvideSchema(XmlSchemaSet schemaSet) {
            XmlSchema schema = new XmlSchema();
            schema.TargetNamespace = Constants.Namespace;
            schema.ElementFormDefault = XmlSchemaForm.Qualified;

            XmlSchemaComplexType cType = new XmlSchemaComplexType();
            cType.Name = "C";
            schema.Items.Add(cType);

            XmlSchemaSequence sequence = new XmlSchemaSequence();
            cType.Particle = sequence;

            XmlSchemaElement dElement = new XmlSchemaElement();
            dElement.Name = "D";
            dElement.SchemaTypeName = new XmlQualifiedName("string", Constants.XmlNameSpace);
            sequence.Items.Add(dElement);

            schemaSet.Add(schema);
            return new XmlQualifiedName(
                    "C",
                    Constants.Namespace);
        }

        #region IXmlSerializable Members

        public XmlSchema GetSchema() {
            throw new Exception("The method or operation is not implemented.");
        }

        public void ReadXml(XmlReader reader) {
            throw new Exception("The method or operation is not implemented.");
        }

        public void WriteXml(XmlWriter writer) {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion
    }

    class Program {
        static void Main(string[] args) {
            XmlSchemaSet xss = new XmlSchemaSet();
            try {
                A.ProvideSchema(xss);

                foreach (XmlSchema s in xss.Schemas()) {
                    s.Write(Console.Out);
                    Console.WriteLine();
                    Console.WriteLine();
                }
            } catch (MissingMethodException e) {
                Console.WriteLine(e.ToString());
            }
        }
    }
}




Re: ASMX Web Services and XML Serialization Problem with mixing XmlReflectionImporter and XmlSchemaProviderAttribute.

Elena Kharitidi

This a known usability problem, which is not documented either, basically you have to compile XmlSchemas object before enumerating the schemas:

XmlSchemaElement blElement = new XmlSchemaElement();

blElement.Name = "B";

blElement.SchemaTypeName = new XmlQualifiedName(bMapping.XsdTypeName, bMapping.XsdTypeNamespace);

sequence.Items.Add(blElement);

schemas.Compile(null, false);

foreach (XmlSchema s in schemas) {

schemaSet.Add(s);

if (

(s.TargetNamespace != null) &&

(s.TargetNamespace.Length > 0) &&

(s.TargetNamespace != Constants.Namespace)

) {

XmlSchemaImport import = new XmlSchemaImport();

import.Namespace = s.TargetNamespace;

schema.Includes.Add(import);

}

}

Thanks,

elena





Re: ASMX Web Services and XML Serialization Problem with mixing XmlReflectionImporter and XmlSchemaProviderAttribute.

Wout

Elena,

Awesome, that does make it work! I had given up hope on this one, every time I've asked a hard question so far I did not get a useful answer. You have proven to me that there are still people out there that care, I appreciate it. (Would you be available for a little bit of consulting to see whether our web service/XML serialization is designed properly Shoot me an e-mail at wout at iconbuildings dot com if there's such an option).

Now onto the other issues I had :-)

Wout