Search code examples
wcf

How to return a list of a defined type WCF service


I have defined the data contract as follows:

[DataContract]
public class TestResult
{
    [DataMember]
    public string[] NegResponses { get; set; }

    [DataMember]
    public bool Pass { get; set; }

    [DataMember]
    public string Request { get; set; }

    [DataMember]
    public string Response { get; set; }
}

Is it possible to return a list of the above type in the operation contract as follows:

    [OperationContract]
    [FaultContract(typeof(TestFault))]
    List<TestResult> Tester(string nodeCaption);

And what else I have to look into to return a list of a type that has been defined ?

By the way I guess I am not using svcutil and instead using channel factory as follows:

        private static readonly ITestService TestClient;

        // initialize a channel factory
        var channelFactory = new ChannelFactory<ITestService>(new NetTcpBinding(SecurityMode.None), endPoint);

        // Create a channel
        TestClient = channelFactory.CreateChannel();

Solution

  • The client-side and the server-side should share the same service contract and data contract. This is fundamental that we could consume the service on the client-side. Here is an example, wish it is useful to you.
    Server-side.

    class Program
        {
            static void Main(string[] args)
            {
                Uri uri = new Uri("http://localhost:21011");
                BasicHttpBinding binding = new BasicHttpBinding();
                using (ServiceHost sh = new ServiceHost(typeof(MyService), uri))
                {
                    sh.AddServiceEndpoint(typeof(IService), binding, "");
                    ServiceMetadataBehavior smb;
                    smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
                    if (smb == null)
                    {
                        smb = new ServiceMetadataBehavior()
                        {
                            HttpGetEnabled=true
                        };
                        sh.Description.Behaviors.Add(smb);
                    }
                    Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
                    sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");
    
                    sh.Opened += delegate
                    {
                        Console.WriteLine("Service is ready");
                    };
                    sh.Closed += delegate
                    {
                        Console.WriteLine("Service is clsoed");
                    };
                    sh.Open();
                    Console.ReadLine();
                    //pause
                    sh.Close();
                    Console.ReadLine();
                }
            }
        }
        [ServiceContract]
        public interface IService
        {
            [OperationContract]
            List<Product> SayHello();
        }
        public class MyService : IService
        {
            public List<Product> SayHello()
            {
                return new List<Product>()
                {
                    new Product()
                    {
                        ID=1,
                        Name="Apple"
                    },
                    new Product()
                    {
                        ID=2,
                        Name="Pear"
                    }
                };
            }
        }
    
        [DataContract(Namespace = "MyNamespace")]
        public class Product
        {
            [DataMember]
            public int ID { get; set; }
            [DataMember]
            public string Name { get; set; }
    }
    

    Client-side (Console application,we call the service with ChannelFactory).

    class Program
        {
            static void Main(string[] args)
            {
                BasicHttpBinding binding = new BasicHttpBinding();
                Uri uri = new Uri("http://10.157.13.69:21011");
                ChannelFactory<IService> factory = new ChannelFactory<IService>(binding, new EndpointAddress(uri));
                IService service = factory.CreateChannel();
                try
                {
                    var result = service.SayHello();
                    foreach (var item in result)
                    {
                        Console.WriteLine($"ID:{item.ID}\n,Name:{item.Name}");
                    }
                }
                catch (Exception)
                {
                    throw;
                }
            }
        }
        [ServiceContract]
        public interface IService
        {
            [OperationContract]
            List<Product> SayHello();
        }
        [DataContract(Namespace = "MyNamespace")]
        public class Product
        {
            [DataMember]
            public int ID { get; set; }
            [DataMember]
            public string Name { get; set; }
    }
    

    Data Contract should be decorated with Namespace property, this will guarantee that the serialization and deserialization process properly). Actually, the service contract also needs a namespace to represent the practical method name, which will be used to addressing the method on the server-side. but there is a default value in the namespace.

    http://tempuri.org

    Feel free to let me know if there is anything I can help with.