首页 > 代码库 > 重温WCF之消息契约(MessageContract)(六)

重温WCF之消息契约(MessageContract)(六)

对于SOAP来说主要由两部分构成Header和Body,他们两个共同构成了SOAP的信封,通常来说Body保存具体的数据内容,Header保存一些上下文信息或关键信息。比如:在一些情况下,具有这样的要求:当序列化一个对象并生成消息的时候,希望将部分数据成员作为SOAP的报头,部分作为消息的主体。比如说,我们有一个服务操作采用流的方式进行文件的上载,除了以流的方式传输以二进制表示的文件内容外,还需要传输一个额外的基于文件属性的信息,比如文件格式、文件大小等。一般的做法是将传输文件内容的流作为SOAP的主体,将其属性内容作为SOAP的报头进行传递。这样的功能,可以通过定义消息契约来实现。由此可见,MessageContract的主要作用就是给我们提供了自己来操作SOAP的一种方式。

先定义我们所需要的消息协定类。

 [MessageContract]
    public class CarMessage
    {
        [MessageBodyMember]
        public string CarName { get; set; }
        [MessageBodyMember]
        public int MakeYear { get; set; }
        [MessageBodyMember]
        public string SerType { get; set; }
    }

    [MessageContract]
    public class Person
    {
        [MessageHeader]
        public string Zip { get; set; }
        [MessageHeader]
        public string Address { get; set; }
        [MessageBodyMember]
        public int Age { get; set; }
        [MessageBodyMember]
        public string Name { get; set; }
        [MessageBodyMember]
        public string Email { get; set; }
    }

    [MessageContract]
    public class RequestMessage
    {
        [MessageHeader]
        public int maxNum;
        [MessageBodyMember]
        public string CheckName;
    }

    [MessageContract]
    public class ResponseMessage
    {
        [MessageBodyMember]
        public string Name;
        [MessageBodyMember]
        public int CheckResult;
    }

   

    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        void PostMessage(CarMessage msg);

        [OperationContract]
        Person GetPerson();

        [OperationContract]
        ResponseMessage CheckRenpin(RequestMessage rqmsg);


    

    }

    public class Service : IService
    {
        public void PostMessage(CarMessage msg)
        {
            Console.WriteLine("车子名字:{0}", msg.CarName);  
        }

        public Person GetPerson()
        {
            Person ps = new Person();
            ps.Name = "鸟人";
            ps.Age = 107;
            ps.Email = "nb@niube.com";
            ps.Zip = "990";
            ps.Address = "非洲";
            return ps;  
        }

        public ResponseMessage CheckRenpin(RequestMessage rqmsg)
        {
            ResponseMessage respMsg = new ResponseMessage();
            Random rand = new Random();
            respMsg.CheckResult = rand.Next(rqmsg.maxNum);
            respMsg.Name = rqmsg.CheckName;
            return respMsg;  
        }


       
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof(Service)))
            {
                host.AddServiceEndpoint(typeof(IService), new WSHttpBinding(), "http://127.0.0.1:8888/service1");
                ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
                behavior.HttpGetEnabled = true;
                behavior.HttpGetUrl = new Uri("http://127.0.0.1:8888/service");  //httpGetUrl客户端引用的地址
                host.Description.Behaviors.Add(behavior);
                host.Opened += delegate
                {
                    Console.WriteLine("服务已启动");
                    Console.ReadKey();
                };
                host.Open();
            }
        }
    }

 确认服务器端正常运行后,在客户端添加服务引用。
在客户端生成的代理类中,消息协定和数据协定并不一样了,服务的操作协定和服务器端我们定义的不一样了。

用这种方式序列化的实体类不能当作参数直接传递,客户端会把对象的一个参数拆分为多个属性作为参数。

接下来,我们看看消息协定包含数据协定的的例子。

 [DataContract]
    public class ArtistInfo
    {
        [DataMember]
        public string ArtistName;
        [DataMember]
        public DateTime CreateTime;
    }

    [MessageContract]
    public class Worker
    {
        [MessageHeader]
        public ArtistInfo WorkerArtist;
        [MessageBodyMember]
        public string WorkerName;
        [MessageBodyMember]
        public string WorkerNo;
        [MessageBodyMember]
        public int WorkerAge;
    }  

    [ServiceContract]
    public interface IService
    {
       
         [OperationContract]  
        void SetWorkerInformation(Worker wk);  

    }

    public class Service : IService
    {
      

        public void SetWorkerInformation(Worker wk)
        {
            Console.WriteLine("工作名字:{0}", wk.WorkerName);
            ArtistInfo info = wk.WorkerArtist;
            Console.WriteLine("工人作品创建时间:{0}", info.CreateTime.ToString("yyyy-MM-dd HH:mm:ss"));
            Console.WriteLine("工人作品名字:{0}", info.ArtistName);  
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof(Service)))
            {
                host.AddServiceEndpoint(typeof(IService), new WSHttpBinding(), "http://127.0.0.1:8888/service1");
                ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
                behavior.HttpGetEnabled = true;
                behavior.HttpGetUrl = new Uri("http://127.0.0.1:8888/service");  //httpGetUrl客户端引用的地址
                host.Description.Behaviors.Add(behavior);
                host.Opened += delegate
                {
                    Console.WriteLine("服务已启动");
                    Console.ReadKey();
                };
                host.Open();
            }
        }
    }

客户端调用:

using (ServiceClient client = new ServiceClient() )
            {
                string name = string.Empty;
               int i =  client.CheckRenpin(1, "aa", out name);
                MessageBox.Show(i+"     "+name);

                ArtistInfo info = new ArtistInfo();
                info.ArtistName = "aaa";
                info.CreateTime = DateTime.Now;
                client.SetWorkerInformation(info, 180, "张三", "no1234");
            }