views:

502

answers:

2

.NET

I have a web service, one of the data members of a message implements IXmlSerializable, when I do "Add Service Reference" that member becomes a DataSet.

I am trying to pass a serialized Expression<TDelegate> as a parameter to the web service.

Q: How do I make a DataSet out of the IXmlSerializable instance on the client side?

+2  A: 

In general, custom serialization (via IXmlSerializable) over either SOAP or WCF is a bad idea. If you are using assembly-sharing with WCF (i.e. rather than proxy generation, you ship the DTO assembly to the client) then it can work, but it still violates SOA/mex etc. Actually, I'm surprised it doesn't just give you XmlElement or similar, but heh!

I would simply map your existing (IXmlSerializable) object model into simple types that can use the standard serialization (i.e. no IXmlSerializable).

BTW; have you looked at ADO.NET Data Services? This already handles Expression over the wire (although not as a value). For passing as values, MetaLinq.

Marc Gravell
+1  A: 

I realize this is an older question, but for future readers here is what I discovered:

Objects that implement IXmlSerializable need to have a schema defined in order for them to work with the wsdl, otherwise the .Net framework doesn't know how to define the contract because the serialization is custom.

To specify the schema you are not supposed to use the GetSchema method in the IXmlSerializable interface, rather use the XmlSchemaProvider attribute (msdn link). You can read more about in Microsoft's article Enrich Your XML Serialization With Schema Providers In The .NET Framework inthe schema providers section.

You can find examples on both the XmlSchemaProvider attribute page and the article, I recommend storing your schemas in .xsd files and reading them in like in the examples. Writing the schema through code is cumbersome at best.

Once I implemented the schema provider the serialization worked as expected. If your WCF service is IIS hosted refer to this question on how to get the proper IIS directory via reflection http://stackoverflow.com/questions/2427822/can-i-use-reflection-to-find-the-bin-configuration-folder-in-asp-net-instead-of.

Example from the Microsoft article:

[XmlRoot(ElementName="product_root", DataType="product_type", 
    Namespace="http://SchemaProvider.Example.org/Product.xsd",
    IsNullable = false)]
[XmlSchemaProviderAttribute("GetSchemaFile")]
public class Product : IXmlSerializable
{ 
    public static XmlSchemaComplexType GetSchemaFile(
        System.Xml.Schema.XmlSchemaSet xs)
    {
        string xsdFile = Directory.GetCurrentDirectory() + 
            "\\Product.xsd";
        XmlSerializer schemaSerializer = 
            new XmlSerializer(typeof(XmlSchema));
        XmlSchema schema = 
            (XmlSchema)schemaSerializer.Deserialize(
                XmlReader.Create(xsdFile));
        xs.Add(schema);

        // target namespace
        string tns = "http://SchemaProvider.Example.org/Product.xsd";  
        XmlQualifiedName name = 
            new XmlQualifiedName("product_type", tns);
        XmlSchemaComplexType productType = 
            (XmlSchemaComplexType) schema.SchemaTypes[name];

        return productType;
    } 

    ...
}
vfilby