WCF:Windows Communication Foundation
什么是WCF by MSDN:http://msdn.microsoft.com/zh-cn/library/ms731082.aspx
入门教程 by MSDN:http://msdn.microsoft.com/zh-cn/library/ms734712.aspx
WCF 是用于构建面向服务的应用程序的框架。借助WCF,可以将数据作为异步消息从一个服务终结点发送至另一个服务终结点。面向服务的体系结构(SOA)依赖WEB服务发送和接受数据。
照着入门教程写一个简单的程序迅速了解编码步骤。
服务公开一个或多个终结点,每个终结点公开一个或多个服务操作。终结点包含的信息:服务的位置;一个绑定;一个协定(服务公开的接口,即功能)。
1. 定义WCF服务协定(就是接口)
新建C#控制台程序Service,添加System.ServiceModel的引用。
每个接口都要应用ServiceContractAttribute属性,接口中要公开的每个方法都要应用OperationContractAttribute属性。
创建一个接口,并定义方法。
2. 实现WCF协议
创建一个实现类实现第一步的接口。
3. 承载和运行基本的WCF服务。
为服务配置基址:创建一个URI
承载服务:创建ServiceHost实例
启动元数据交换:ServiceMetadataBehavior
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace Microsoft.ServiceModel.Samples
{
class Program
{
//Define a service contract
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
//Create the method declaration for the contract
[OperationContract]
double Add(double n1, double n2);
[OperationContract]
double Substract(double n1, double n2);
[OperationContract]
double Multiply(double n1, double n2);
[OperationContract]
double Divide(double n1, double n2);
}
/// <summary>
/// Create service class that implements the service contract
/// </summary>
public class CalculatorService : ICalculator
{
#region ICalculator Members
// Implement functionality for the service operations.
double ICalculator.Add(double n1, double n2)
{
double result = n1 + n2;
Console.WriteLine("Received Add({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
double ICalculator.Substract(double n1, double n2)
{
double result = n1 - n2;
Console.WriteLine("Received Substract({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
double ICalculator.Multiply(double n1, double n2)
{
double result = n1 * n2;
Console.WriteLine("Received Multiply({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
double ICalculator.Divide(double n1, double n2)
{
double result = n1 / n2;
Console.WriteLine("Received Divide({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
#endregion
}
static void Main(string[] args)
{
// Create a URI to serve as the base address
Uri baseAddress = new Uri("http://localhost:8000/ServiceModelSamples/Service");
// Hosting procedure: Create ServiceHost
ServiceHost selfHost = new ServiceHost(typeof(CalculatorService), baseAddress);
try
{
// Hosting procedure: Add a service endpoint
selfHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "CalculatorService");
// Hosting procedure: Enable metadata exchange
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
// Hosting procedure: Start the service
selfHost.Open();
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
// Shutdown the service
selfHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("An exception occured: {0}", ce.Message);
selfHost.Abort();
}
}
}
}
编译,运行service.exe(需要admin权限)。在IE中输入http://localhost:8000/ServiceModelSamples/Service。得到一个HTML页面,告诉你创建了一个服务,现在需要一个客户端来连接。
4. 创建WCF客户端
创建新的C#控制台项目Client,添加引用System.ServiceModel.dll。
运行服务(Service.exe),打开VS2010 命令行,cd到Client:
Client>Svcutil.exe /language:cs /out:generateProxy.cs /config:app.config http://localhost:8000/ServiceModelSamples/Service
Svcutil.exe:ServiceModel元数据实用工具。
/out:客户端代理文件的名称
/config:客户端配置文件的名称。(默认是Output.config)
将在Client目录下生成的两个文件generateProxy.cs app.config加入到Client项目中。
generateProxy.cs
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.269
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://Microsoft.ServiceModel.Samples", ConfigurationName="ICalculator")]
public interface ICalculator
{
[System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Add", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/AddResponse")]
double Add(double n1, double n2);
[System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Substract", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/SubstractResponse")]
double Substract(double n1, double n2);
[System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Multiply", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/MultiplyResponse")]
double Multiply(double n1, double n2);
[System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Divide", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/DivideResponse")]
double Divide(double n1, double n2);
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface ICalculatorChannel : ICalculator, System.ServiceModel.IClientChannel
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class CalculatorClient : System.ServiceModel.ClientBase<ICalculator>, ICalculator
{
public CalculatorClient()
{
}
public CalculatorClient(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
public CalculatorClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public CalculatorClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public CalculatorClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public double Add(double n1, double n2)
{
return base.Channel.Add(n1, n2);
}
public double Substract(double n1, double n2)
{
return base.Channel.Substract(n1, n2);
}
public double Multiply(double n1, double n2)
{
return base.Channel.Multiply(n1, n2);
}
public double Divide(double n1, double n2)
{
return base.Channel.Divide(n1, n2);
}
}
5. 配置基本WCF客户端
app.config。重点是<endpoint>值。
使用配置文件配置服务:http://msdn.microsoft.com/zh-cn/library/ms733932.aspx
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ICalculator" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8000/ServiceModelSamples/Service/CalculatorService"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICalculator"
contract="ICalculator" name="WSHttpBinding_ICalculator">
<identity>
<userPrincipalName value=user_name@domain_name />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
6. 使用WCF客户端
创建WCF客户端实例,从生成的代理调用服务操作。
using System;
using System.ServiceModel;
namespace Client
{
class Program
{
static void Main(string[] args)
{
//Create an endpoint address and an instance of the WCF client
CalculatorClient client = new CalculatorClient();
// Call the service operations.
// Call the Add service operation.
double value1 = 100.00D;
double value2 = 15.99D;
double result = client.Add(value1, value2);
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
// Call the Subtract service operation.
value1 = 145.00D;
value2 = 76.54D;
result = client.Substract(value1, value2);
Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);
// Call the Multiply service operation.
value1 = 9.00D;
value2 = 81.25D;
result = client.Multiply(value1, value2);
Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);
// Call the Divide service operation.
value1 = 22.00D;
value2 = 7.00D;
result = client.Divide(value1, value2);
Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
//Close the connection and clean up resources.
client.Close();
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
}
}
}
运行Service.exe和Client.exe:
A Guide to Designing and Building RESTful Web Services with WCF3.5