How can I use an interface (from which classes implement) in an XML web service?
When I do so, I get a YSOD claiming the interface is not serializable. If I add the Serializable attribute to the interface's class, there's another error which hampers progress (can't remember which).
For the most part interfaces are not serializable without some work. Usually this error is encountered when the class being serialized contains an object that is using an interface as a variable, or some variation of this. For instance, a property like this would throw an error:
[Serializable]
public class TestClass
{
private ICustomInterface _iCustomInterfaceObject;
public ICustomInterface CustomInterfaceProperty
{
get { return _iCustomInterfaceObject; }
set { _iCustomInterfaceObject = value; }
}
}
For the sake of the argument (and not making me type additional validation code), let's say that you always are assigning CustomInterfaceProperty to an object that inherits from ICustomInterface (as is required when using interface types like this). Even if it is 100% sure to always be populated, it won't allow you to serialize the TestClass.
To get around this, you need to make sure the interface you are using, the one that is throwing the error, also inherits from ISerializable. That way you are promising that all of the objects inheriting from ICustomInterface also have serialization methods implemented.
Unfortunately, this is not the case when using xml serialization. If you are using the serializers found in System.Xml.Serialization then this method won't work, since, as Robert Harvey pointed out, an interface does not contain a parameterless constructor (which is required when using the xml serializers). My suggestion for now, if you are set on this method of serialization, attach the attribute [XmlIgnore] to the section in question and move on from there.
My advice is to treat the objects that go over the wire as basic data transfer objects and nothing more. You're tempted to just use your domain objects and serialize them, but as you're already seeing, normal in-memory objects can have far more complexity than can be serialized without a lot of work, and sometimes not at all.
You can also end up limiting functionality of your domain classes just to keep them serializable.
Finally, a more subtle bug to avoid, and a reason to have separate DTO's, is that you otherwise are tightly coupling your domain objects to a publicly published interface i.e. the web service itself. Versioning a web service can be a hassle, and it's easier if your service interface isn't tightly coupled to your domain classes.
I'm guessing that the other message is that you can't serialize the interface because it doesn't contain a default (parameterless) constructor.
If the underlying classes are framework classes, you might be hosed. Some of them are not marked serializable, and some of them do not have parameterless constructors.
Also, you may be getting confused between runtime serialization and XML serialization. XML Serialization is what the old ASMX web services use. It does not pay much attention to the [Serializable] attribute, but mostly just serializes the public read/write properties of public classes which have a default constructor.