• WCF系列教程之WCF客户端调用服务


    1、创建WCF客户端应用程序需要执行下列步骤

    (1)、获取服务终结点的服务协定、绑定以及地址信息

    (2)、使用该信息创建WCF客户端

    (3)、调用操作

    (4)、关闭WCF客户端对象

    二、操作实例

    1、WCF服务层搭建:新建契约层、服务层、和WCF宿主,添加必须的引用(这里不会的参考本人前面的随笔),配置宿主,生成解决方案,打开Host.exe,开启服务。具体的代码如下:

    ICalculate.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.ServiceModel;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace IService
    {
        [ServiceContract]
        public interface ICalculate
        {
            [OperationContract]
            int Add(int a, int b);
        }
    }

    IUserInfo.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace IService
    {
        [ServiceContract]
        public interface IUserInfo
        {
            [OperationContract]
            User[] GetInfo(int? id);
        }
    
        [DataContract]
        public class User
        {
            [DataMember]
            public int ID { get; set; }
            [DataMember]
            public string Name { get; set; }
            [DataMember]
            public int Age { get; set; }
            [DataMember]
            public string Nationality { get; set; }  
        }
    }

    注:必须引入System.Runtime.Serialization命名空间,应为User类在被传输时必须是可序列化的,否则将无法传输

    Calculate.cs

    using IService;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Service
    {
        public class Calculate : ICalculate
        {
            public int Add(int a, int b)
            {
                return a + b;
            }
        }
    }

    UserInfo.cs

    using IService;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Service
    {
        public class UserInfo : IUserInfo
        {
            public User[] GetInfo(int? id)
            {
                List<User> Users = new List<User>();
                Users.Add(new User { ID = 1, Name = "张三", Age = 11, Nationality = "China" });
                Users.Add(new User { ID = 2, Name = "李四", Age = 12, Nationality = "English" });
                Users.Add(new User { ID = 3, Name = "王五", Age = 13, Nationality = "American" });
    
                if (id != null)
                {
                    return Users.Where(x => x.ID == id).ToArray();
                }
                else
                {
                    return Users.ToArray();
                }
            }
        }
    }

    Program.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Service;
    using System.ServiceModel;
    
    namespace Host
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (ServiceHost host = new ServiceHost(typeof(Calculate)))
                {
                    host.Opened += delegate { Console.WriteLine("服务已经启动,按任意键终止!"); };
                    host.Open();
                    Console.Read();
                }
            }
        }
    }

    App.Config

    <?xml version="1.0"?>
    <configuration>
      <system.serviceModel>
    
        <services>
          <service name="Service.Calculate" behaviorConfiguration="mexBehavior">
            <host>
              <baseAddresses>
                <add baseAddress="http://localhost:1234/Calculate/"/>
              </baseAddresses>
            </host>
            <endpoint address="" binding="wsHttpBinding" contract="IService.ICalculate" />
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
          </service>
        </services>
    
        <behaviors>
          <serviceBehaviors>
            <behavior name="mexBehavior">
              <serviceMetadata httpGetEnabled="true"/>
              <serviceDebug includeExceptionDetailInFaults="true"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    </configuration>

    ok,打开Host.exe

    服务开启成功!

    2、新建名为Client的客户端控制台程序,通过添加引用的方式生成WCF客户端

    确保Host.exe正常开启的情况下,添加对服务终结点地址http://localhost:6666/UserInfo/的引用,,设置服务命名空间为UserInfoClientNS

    点击确定完成添加,生成客户端代理类和配置文件代码后,

    开始Client客户端控制台程序对WCF服务的调用,Program.cs代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Client.UserInfoClientNS;
    
    namespace Client
    {
        class Program
        {
            static void Main(string[] args)
            {
                UserInfoClient proxy =new UserInfoClient();
                User[] Users = proxy.GetInfo(null);
                Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}","ID","Name","Age","Nationality");
                for(int i=0;i<Users.Length;i++)
                {
                      Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}",
                        Users[i].ID.ToString(),
                        Users[i].Name.ToString(),
                        Users[i].Age.ToString(),
                        Users[i].Nationality.ToString());
                }
    
                Console.Read();
            }
            
        }
    }

     

    ok,第一种客户端添加引用的方式测试成功

    3、新建名为Client1的客户端控制台程序,通过svcutil.exe工具生成客户端代理类的方式生成WCF客户端,在VS2012 开发人员命令提示中输入以下命令:

    (1)、定位到当前客户端所在的盘符

    (2)、定位当前客户端所在的路径

    (3)、svcutil http://localhost:8000/OneWay/?wsdl /o:OneWay.cs      这里是OneWay,你本地是什么就是什么

    (4)、生成客户端代理类,生成成功之后,将文件添加到项目中

    ok,生成成功!

    (5)、将生成的文件包括到项目中,引入System.Runtime.Serialization命名空间和System.ServiceModel命名空间

    (6)、确保服务开启的情况下,开始调用,Program.cs代码如下:

    UserInfoClient proxy = new UserInfoClient();
                User[] Users = proxy.GetInfo(null);
                Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}", "ID", "Name", "Age", "Nationality");
                for (int i = 0; i < Users.Length; i++)
                {
                    Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}",
                      Users[i].ID.ToString(),
                      Users[i].Name.ToString(),
                      Users[i].Age.ToString(),
                      Users[i].Nationality.ToString());
                }
    
                Console.Read();

    ok,服务调用成功,说明使用svcutil工具生成WCF客户端的方式可行。

    4、通过添加对Service程序集的引用,完成对WCF服务端的调用,新建一个Client2客户端控制台程序

    先添加下面三个引用

    using IService;
    using System.ServiceModel;
    using System.ServiceModel.Channels;

    (1)、Program.cs代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using IService;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.Text;
    using System.Threading.Tasks;
    
    
    
    namespace Client2
    {
        class Program
        {
            static void Main(string[] args)
            {
                EndpointAddress address = new EndpointAddress("http://localhost:6666/UserInfo/");
                WSHttpBinding binding = new WSHttpBinding();
                ChannelFactory<IUserInfo> factory = new ChannelFactory<IUserInfo>(binding, address);
                IUserInfo channel = factory.CreateChannel();
    
    
                User[] Users = channel.GetInfo(null);
                Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}", "ID", "Name", "Age", "Nationality");
                for (int i = 0; i < Users.Length; i++)
                {
                    Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}",
                      Users[i].ID.ToString(),
                      Users[i].Name.ToString(),
                      Users[i].Age.ToString(),
                      Users[i].Nationality.ToString());
                }
    
                ((IChannel)channel).Close();
                factory.Close();
                Console.Read();
            }
        }
    }

    ok,调用成功!

    三、归纳总结

    通过上面的代码判断WCF客户端调用服务存在以下特点:

    1、WCF服务端可客户端通过使用托管属性、接口、方法对协定进行建模。若要连接到服务端的服务,则需要获取该服务协定的类型信息.获取协定的类型信息有两种方式:

    (1)、通过Svcutil工具,在客户端生成代理类的方式,来获取服务端服务的服务协定的类型信息

    (2)、通过给项目添加服务引用的方式

    上面两种方式都会从服务端的服务中下载元数据,并使用当前你使用的语言,将其转换成托管源代码文件中,同时还创建一个您可用于配置 WCF 客户端对象的客户端应用程序配置文件.

    2、WCF客户端是表示某个WCF服务的本地对象,客户端可以通过该本地对象与远程服务进行通信。因此当你在服务端创建了一个服务端协定,并对其进行配置后,客户端就可以通过生成代理类的方式(具体生成代理类的方式,上面已经提了)和服务端的服务进行通信,WCF 运行时将方法调用转换为消息,然后将这些消息发送到服务,侦听回复,并将这些值作为返回值或 out 参数(或 ref 参数)返回到 WCF 客户端对象中.(有待考证);

    3、创建并配置了客户端对象后,请创建一个 try/catch 块,如果该对象是本地对象,则以相同的方式调用操作,然后关闭 WCF 客户端对象。 当客户端应用程序调用第一个操作时,WCF 将自动打开基础通道,并在回收对象时关闭基础通道。 (或者,还可以在调用其他操作之前或之后显式打开和关闭该通道。)。不应该使用 using 块来调用WCF服务方法。因为C# 的“using”语句会导致调用 Dispose()。 它等效于 Close(),当发生网络错误时可能会引发异常。 由于对 Dispose() 的调用是在“using”块的右大括号处隐式发生的,因此导致异常的根源往往会被编写代码和阅读代码的人所忽略。 这是应用程序错误的潜在根源

  • 相关阅读:
    mybatis中的配置文件的约束
    win10下PHP开发环境搭建
    装饰器的理解
    在iis上添加woff字体文件读取
    转发:使用sql命令查询视图中所有引用的基础表
    转:C4项目中验证用户登录一个特性就搞定
    转载:NSobject官方介绍
    thinkphp生命周期
    array_intersect_assoc — 带索引检查计算数组的交集
    array_flip — 交换数组中的键和值
  • 原文地址:https://www.cnblogs.com/GreenLeaves/p/6859012.html
Copyright © 2020-2023  润新知