WCF学习
相关链接
http://www.cnblogs.com/iamlilinfeng/p/4083827.html
http://www.cnblogs.com/iamlilinfeng/archive/2012/10/01/2706353.html
1、项目目录
主目录
服务库目录
三种宿主目录
两种客户端访问方式
代码见StudyNoteOfCsharp项目。
2、WCF开发步骤
2.1、定义和现实服务协定,在WcfServiceLibrary1服务库项目里
namespace WcfServiceLibrary1 { // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。 [ServiceContract] public interface IService1 { [OperationContract] int Add(int a, int b); [OperationContract] int Multiply(int a, int b); } }
namespace WcfServiceLibrary1 { // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的类名“Service1”。 public class Service1 : IService1 { int IService1.Add(int a, int b) { return a + b; } int IService1.Multiply(int a, int b) { return a * b; } } }
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> </appSettings> <system.web> <compilation debug="true" /> </system.web> <!-- 部署服务库项目时,必须将配置文件的内容添加到 主机的 app.config 文件中。System.Configuration 不支持库的配置文件。--> <system.serviceModel> <services> <service name="WcfServiceLibrary1.Service1"> <host> <baseAddresses> <add baseAddress = "http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary1/Service1/" /> </baseAddresses> </host> <!-- Service Endpoints --> <!-- 除非完全限定,否则地址将与上面提供的基址相关 --> <endpoint address="" binding="basicHttpBinding" contract="WcfServiceLibrary1.IService1"> <!-- 部署时,应删除或替换下列标识元素,以反映 用来运行所部署服务的标识。删除之后,WCF 将 自动推断相应标识。 --> <identity> <dns value="localhost"/> </identity> </endpoint> <!-- Metadata Endpoints --> <!-- 元数据交换终结点供相应的服务用于向客户端做自我介绍。 --> <!-- 此终结点不使用安全绑定,应在部署前确保其安全或将其删除--> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> <behaviors> <serviceBehaviors> <behavior> <!-- 为避免泄漏元数据信息, 请在部署前将以下值设置为 false --> <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/> <!-- 要接收故障异常详细信息以进行调试, 请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息--> <serviceDebug includeExceptionDetailInFaults="False" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
此项目里调用wcf服务没有用到上面app.config里的配置,所以用处不大
2.2、将wcf服务寄宿到winform程序、console控制台程序、或是web程序里
寄宿到winform程序里
winform项目app.config
<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <!--下面是加上去的--> <system.serviceModel> <services> <service name="WcfServiceLibrary1.Service1"> <host> <baseAddresses> <add baseAddress="http://localhost:8081/Service1"/> </baseAddresses> </host> <endpoint address="" binding="wsHttpBinding" contract="WcfServiceLibrary1.IService1"></endpoint> </service> </services> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="True"/> <serviceDebug includeExceptionDetailInFaults="False"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
winform界面
代码如下
namespace WcfServiceWinformHost { public partial class Form1 : Form { //host的地址和service在app.config里设置了 ServiceHost host = new ServiceHost(typeof(WcfServiceLibrary1.Service1)); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { this.Text = "wcf服务监听已经开启"; host.Open(); } private void button2_Click(object sender, EventArgs e) { host.Close(); this.Text = "wcf服务监听已经停止"; } } }
但“开始监听”时,在浏览器里输入http://localhost:8081/Service1会看到wcf服务已经启动,客户端程序引用http://localhost:8081/Service1地址的服务就可以。
寄宿到console控制台
app.config配置如下,但配置是无效的,在Program.cs程序里没有用app.config里的配置
<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <system.serviceModel> <bindings> <wsHttpBinding> <binding name="WSHttpBinding_IService1" /> </wsHttpBinding> </bindings> <client> <endpoint address="http://localhost:8081/Service1" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1" contract="ServiceWinformReference1.IService1" name="WSHttpBinding_IService1"> <identity> <userPrincipalName value="SHENGYU\Administrator" /> </identity> </endpoint> </client> </system.serviceModel> </configuration>
主程序代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ServiceModel; using System.ServiceModel.Description; using WcfServiceLibrary1; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { // Step 1 Create a URI to serve as the base address. Uri baseAddress = new Uri("http://localhost:8733/WcfServiceLibrary1/Service1/"); // Step 2 Create a ServiceHost instance ServiceHost selfHost = new ServiceHost(typeof(Service1), baseAddress); try { // Step 3 Add a service endpoint. selfHost.AddServiceEndpoint(typeof(IService1), new WSHttpBinding(), "Service1"); // Step 4 Enable metadata exchange. ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; selfHost.Description.Behaviors.Add(smb); // Step 5 Start the service. selfHost.Open(); Console.WriteLine("The service is ready."); Console.WriteLine("Press <ENTER> to terminate service."); Console.WriteLine(); Console.ReadLine(); // Close the ServiceHostBase to shutdown the service. selfHost.Close(); } catch (CommunicationException ce) { Console.WriteLine("An exception occurred: {0}", ce.Message); selfHost.Abort(); } } } }
可以看到,宿主程序将wcf服务发布到了http://localhost:8733/WcfServiceLibrary1/Service1/而不是app.config里的http://localhost:8081/Service1,客户端程序要引用 http://localhost:8733/WcfServiceLibrary1/Service1/就能访问服务
寄宿到web网站上,wcf将寄宿到iis上
此时服务可以写在wcf服务应用程序里
web.config配置如下
<?xml version="1.0" encoding="utf-8"?> <configuration> <appSettings> <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> </appSettings> <system.web> <compilation debug="true" targetFramework="4.5" /> <httpRuntime targetFramework="4.5"/> </system.web> <system.serviceModel> <behaviors> <serviceBehaviors> <behavior> <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false --> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/> <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 --> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> <protocolMapping> <add binding="basicHttpsBinding" scheme="https" /> </protocolMapping> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> </system.serviceModel> <system.webServer> <modules runAllManagedModulesForAllRequests="true"/> <!-- 若要在调试过程中浏览 Web 应用程序根目录,请将下面的值设置为 True。 在部署之前将该值设置为 False 可避免泄露 Web 应用程序文件夹信息。 --> <directoryBrowse enabled="true"/> </system.webServer> </configuration>
定义和现实服务协定
namespace WcfServiceWebHost { // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。 [ServiceContract] public interface IService1 { [OperationContract] int Subtract(int a, int b); } }
namespace WcfServiceWebHost { // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“Service1”。 // 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 Service1.svc 或 Service1.svc.cs,然后开始调试。 public class Service1 : IService1 { public int Subtract(int a, int b) { return a - b; } } }
web运行后的地址为:http://localhost:7234/Service1.svc,在客户端调用时只要引用此地址上的服务就可
3、客户端调用
console控制台客户端调用console控制台服务宿主程序里的wcf服务
在console控制台客户端引用服务,服务地址是http://localhost:8733/WcfServiceLibrary1/Service1/
console控制台客户端程序代码如下:
namespace WcfServiceConsoleClient { class Program { static void Main(string[] args) { ServiceWcfServiceConsoleHostReference1.Service1Client client = new ServiceWcfServiceConsoleHostReference1.Service1Client(); do { var a = int.Parse(Console.ReadLine()); var b = int.Parse(Console.ReadLine()); var result = client.Multiply(a, b); Console.WriteLine("Multiply({0},{1}) = {2}", a, b, result); } while (Console.ReadLine() != "exit"); client.Close(); } } }
运行console控制台宿主程序WcfServiceConsoleHost.exe
运行console控制台客户端程序WcfServiceConsoleClient.exe
console控制台客户端调用winform服务宿主程序里的wcf服务
在console控制台客户端引用服务,服务地址是http://localhost:8081/Service1,即winform宿主程序app.config里配置的地址(其实地址也可以像上面console控制台宿主上样写在程序里而不写在app.config里)
console控制台客户端代码如下:
namespace WcfServiceConsoleClient { class Program { static void Main(string[] args) { ServiceWcfServiceWinformHostReference1.Service1Client client = new ServiceWcfServiceWinformHostReference1.Service1Client(); do { var a = int.Parse(Console.ReadLine()); var b = int.Parse(Console.ReadLine()); var result = client.Add(a, b); Console.WriteLine("Add({0},{1}) = {2}", a, b, result); } while (Console.ReadLine() != "exit"); client.Close(); } } }
运行winform宿主程序,启动服务
运行console控制台客户端程序WcfServiceConsoleClient.exe
console控制台客户端调用web服务宿主程序里的wcf服务
在console控制台上引用web服务宿主端http://localhost:7234/Service1.svc的服务
确保web端开启
console控制台客户端代码如下:
namespace WcfServiceConsoleClient { class Program { static void Main(string[] args) { ServiceWcfServiceWebHostReference1.Service1Client client = new ServiceWcfServiceWebHostReference1.Service1Client(); do { var a = int.Parse(Console.ReadLine()); var b = int.Parse(Console.ReadLine()); var result = client.Subtract(a, b); Console.WriteLine("Subtract({0},{1}) = {2}", a, b, result); } while (Console.ReadLine() != "exit"); client.Close(); } } }
运行console控制台客户端程序WcfServiceConsoleClient.exe
winform客户端调用winform服务端的wcf服务
winform客户端代码和界面如下
namespace WcfServiceWinformClient { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { //ServiceWinformHostReference1引用的是WcfServiceWinformHost项目里app.config里baseAddress的地址 ServiceWinformHostReference1.Service1Client client = new ServiceWinformHostReference1.Service1Client(); textBox3.Text=client.Add(int.Parse(textBox1.Text), int.Parse(textBox2.Text)).ToString(); } private void button2_Click(object sender, EventArgs e) { ServiceWinformHostReference1.Service1Client client = new ServiceWinformHostReference1.Service1Client(); textBox3.Text = client.Multiply(int.Parse(textBox1.Text), int.Parse(textBox2.Text)).ToString(); } } }
运行客户端,调用wcf的加法和乘法方法界面如下
总结:wcf步骤为
1、写服务接口和实现服务
2、写宿主程序,可以是console控制台、winform、web等等应用程序,并调用服务类,配置好wcf,可以用app.config或是web.config来配置,也可以写在程序里,记录好配置后的服务url地址
3、启用宿主程序,在浏览器上确保服务url地址能访问
4、写客户端程序,程序引用宿主的服务url地址,调用服务里的方法
宿主程序在配置wcf时,可能用以下的代码方式
Uri baseAddress = new Uri("http://localhost:8733/WcfServiceLibrary1/Service1/"); // Step 2 Create a ServiceHost instance ServiceHost selfHost = new ServiceHost(typeof(Service1), baseAddress);
baseAddress用来设置服务的地址,ServiceHost类将地址和服务类关联起来
也可以用config配置文件来配置
<system.serviceModel> <services> <service name="WcfServiceLibrary1.Service1"> <host> <baseAddresses> <add baseAddress="http://localhost:8081/Service1"/> </baseAddresses> </host> <endpoint address="" binding="wsHttpBinding" contract="WcfServiceLibrary1.IService1"></endpoint> </service> </services> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="True"/> <serviceDebug includeExceptionDetailInFaults="False"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>
然后在程序里直接调用:
//host的地址和service在app.config里设置了 ServiceHost host = new ServiceHost(typeof(WcfServiceLibrary1.Service1));
认识wcf中的“A\B\C",A指address,就是配置文件里baseaddress的地址,说明去哪里访问服务,B指binding,说明能用什么方式去访问,如wsHttpBinding,C指Contract描述了Service能提供的各种服务。Contract有四种,包括Service Contract, Data Contract, Fault Contract和Message Contract