开发者

What attribute to use for serializing collections in WCF?

I have a class with a generic collection as a property that I'm serializing with WCF:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    TestObject Load();
}

[DataContract]
public class TestObject
{
    [DataMember]
    public Collection<object> Properties = new Collection<object>();
}

It works fine until I add another collection as an item in the collection (indicated by the "bad line" comment)

public class Service1 : IService1
{
    public TestObject Load()
    {
        var obj = new TestObject();

        // bad line
        obj.Properties.Add(new Collection<object>());

        return obj;
    }
}

at which I get the exception:

System.ServiceModel.CommunicationException: The remote server returned an error: NotFound.

If I remove the TestObject class and just return a Collection, then adding another collection to the collection strangely enough works fine:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    Collection<object> Load();
}

public class Service1 : IService1
{
    public Collection<object> Load()
    {
        Collection<o开发者_如何学Gobject> coll = new Collection<object>();

        coll.Add(DateTime.Now);
        coll.Add(new Collection<object>() { DateTime.Now, new Collection<object>() });
        coll.Add("sdf");
        coll.Add(99);

        return coll;
    }
}

I've tried replacing the Collection with a List or an ArrayList. I've tried creating my own derived class from Collection. I've tried using combinations of DataContract, KnownType, ServiceKnownType and CollectionDataContract attributes, but I'm either using them incorrectly or I have another problem.

So is there a way to add collections to my collection in the first example by either applying an attribute or using a derived class? Or is there any way to do this at all?


The problem with the first example is that Collection<object> is equivalent to object[] - an array of arbitrary values. You need to tell WCF what kind of values the collection can contain (by using [KnownTypeAttribute] on the data contract, or [ServiceKnownTypeAttribute] on the service contract) - even if this kind of value is Collection<object>. The code below works when I add a [KnownType(Collection<object>)] on the data contract.

public class StackOverflow_5189844_751090
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        TestObject Load();
    }
    [DataContract]
    [KnownType(typeof(Collection<object>))]
    public class TestObject
    {
        [DataMember]
        public Collection<object> Properties = new Collection<object>();
    }
    public class Service1 : IService1
    {
        public TestObject Load()
        {
            var obj = new TestObject();

            // bad line
            obj.Properties.Add(new Collection<object>());

            return obj;
        }
    }
    static Binding GetBinding()
    {
        BasicHttpBinding result = new BasicHttpBinding();
        //Change binding settings here
        return result;
    }
    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service1), new Uri(baseAddress));
        host.AddServiceEndpoint(typeof(IService1), GetBinding(), "");
        host.Open();
        Console.WriteLine("Host opened");

        var factory = new ChannelFactory<IService1>(GetBinding(), new EndpointAddress(baseAddress));
        var proxy = factory.CreateChannel();
        Console.WriteLine(proxy.Load());

        ((IClientChannel)proxy).Close();
        factory.Close();

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}

In the second case, since Collection is part of the operation contract, it's considered to be a part of the known types for that operation, so it doesn't need to be added explicitly. And primitive types (string, numbers, DateTime) also don't need to be explicitly declared, they're already "known" by WCF.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜