Question

In a Web Service context, I have the following class which inherit from the class Mammal. The Mammal class is defined in a proxy. I cannot change the definition of that class. Because I need to add some methods to the class Mammal on the client side, I inherited Mammal and created Giraffe.

namespace TestApplication
{  
    public class Giraffe : Mammal
    {
        public Giraffe()
        {
        }
    }
}

When I call a WebMethod which expect an object of type Mammal, I get the following exception telling me that Giraffe isn't expected.

  Error: System.InvalidOperationException: There was an error generating the XML document. ---> System.InvalidOperationException: The type Giraffe was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterPaymentRequestAuthorization.Write6_Tender(String n, String ns, Tender o, Boolean isNullable, Boolean needType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterPaymentRequestAuthorization.Write12_PaymentRequestAuthorization(String n, String ns, PaymentRequestAuthorization o, Boolean isNullable, Boolean needType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterPaymentRequestAuthorization.Write13_PaymentRequestAuthorization(Object o)
   --- End of inner exception stack trace ---

Is there a workaround that? I cannot really add the XmlInclude...

Was it helpful?

Solution

To add methods, you should be using partial classes. Try adding a second class file with (in the right namespace etc):

partial class Mammal {
    public void ExtraMethod() {...}
}

The partial keyword tells the compiler to allow the class to be split over multiple files - ideal for code-generation scenarios. It does, however, demand the partial keyword in every file; the members are simply combined (except for partial methods in C# 3.0 which have their own subtle behaviour). I hope that wsdl.exe (or whatever) includes this!

OTHER TIPS

If you just want to add methods to a class you cannot change, just create extension methods.

public static class MammalExt {
public static void ExtraMethod(this Mammal mammal) {...}}

Though if mammal is a proxy generated class it should be a partial class.

You have to use XmlInclude. It's your only choice. You have to tell the serializer what class you'll be serializing, since it has to generate the code to do the serialization.

It just struck me while writing this, that you might get away with having Giraffe implement IXmlSerializable, but that's even more work.

The right answer is indeed to use a partial class. When you open the client project and generate a Web Reference, Visual Studio parses the WSDL and generates a class called Mammal for you. This class is only visible to the client project, so you don't have to worry about the server side of things.

Say you have a Web Reference called MyWebService. Then there will be a class called MyWebService.Mammal. To add members to this class, all you need to do is create a new source file containing this:

namespace MyWebService {
    public partial class Mammal {
        public void ExtraMethod() { ... }
    }
}

When you call a method on your web service that returns a Mammal, the Web Reference code will create a new instance of your "improved" Mammal class, and copy the values from the xml on the wire to the instance.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top