Windows Communication Foundation QuickStart - Multiple Binding VS2010






4.92/5 (20投票s)
本文是关于实现简单 WCF 服务、宿主和客户端的分步演示
目录
- 引言
- 背景和参考
- 必备组件
- WCF 核心组件
- WCF 服务 - 服务器
- 宿主:WCF 服务
- WCF 客户端
- 启用多重绑定:<HTTP> <Binding><TCP Binding> 等
- 为 WCF 服务配置 IIS 托管平台
- 在 WCFClient.exe 中异步调用 WCF 服务
- 结论
引言
本文的目标;
背景和参考
读者可以通过以下参考资料来理解 Windows Communication Foundation 的概念。简而言之,WCF 服务是以下 .net 服务的变通方案。WCF 是一种将所有这些功能整合到一起的方式。
必备组件
Visual Studio 2010 和 .Net 4.0
WCF 核心组件
在 WCF 实现中,我们有三个核心组件。
上述每个组件都附带各自的配置文件。此配置文件有助于在 WCF 服务/服务器、宿主和客户端环境之间建立通信。
这些配置由定义宿主和客户端之间连接的终结点组成。终结点定义存在于宿主和客户端代码包中。现在重要的是我们理解终结点的基本概念。记住它们最简单的方法是终结点的 A B C (Address, Binding 和 Contract)。
人们可以将这个终结点与 Spring .net 框架的依赖注入设计很好地联系起来,在那里我们在配置中声明引用,并且可以在运行时初始化和调用。
WCF 服务 - 服务器
打开 VS2010,选择项目 -> 选择 WCF -> 选择 WCF 服务应用程序
1. 创建 ICustomer.cs 和 CustomerService.cs
ICustomer.cs
namespace WcfCustomerService
{
[ServiceContract]
public interface ICustomerService
{
[OperationContract]
string GetServerResponse(int value);
[OperationContract]
Customer GetCustomerDetails(int customerID);
}
[DataContract]
public class Customer
{
int m_CustomerID;
string m_CustomerName = string.Empty;
[DataMember]
public int CustomerID
{
get { return m_CustomerID; }
set { m_CustomerID = value; }
}
[DataMember]
public string CustomerName
{
get { return m_CustomerName; }
set { m_CustomerName = value; }
}
}
}
CustomerService .cs
namespace WcfCustomerService
{
public class CustomerService : ICustomerService
{
public string GetServerResponse(int value)
{
return string.Format("RESPONSE FROM WCF SERVICE :{0}", value);
}
public Customer GetCustomerDetails(int customerID)
{
Customer customer = null;
if (customerID == 1)
{
customer = new Customer();
customer.CustomerID = 1;
customer.CustomerName = "Santosh Poojari";
}
return customer;
}
}
}
2. 添加服务 Web 配置设置
下面给出的配置默认可用,可以根据我们的需要进行定制。如果选择 IIS 作为 WCF 托管平台,则此配置将发生变化。如果使用 IIS 作为托管,则需要在 WCF 服务配置文件中提及连接的终结点。我们可以在本文的后面部分探讨更多内容。
3. 测试 WCF 服务:VS2010 内置 WCFTestClient.exe
要开始测试,请构建 + 运行服务包。CTRL+F5。完成后,应用程序将成功构建,并出现测试可执行文件以测试这些服务。
双击如下所示的方法。完成后,将出现客户端测试表单,我们可以在其中轻松测试 WCF 服务,而无需任何显式宿主和客户端。
4. 故障排除:最常见的错误
确保您已更改 Customerservice 的标记 HTML 引用。如果这些标签未根据文件名更新,WCFClientTest.Exe 将引发错误。右键单击解决方案资源管理器中的 CustomerService.cs 文件,然后选择“标记”。可以根据给定的文件名更改此引用。
如果未处理这些更改,则会引发以下错误。
宿主:WCF 客户端
创建简单的控制台应用程序。选择项目 -> Windows -> 控制台应用程序
1:添加 WCF 服务包引用
添加两个引用
2:添加宿主配置 App.config 文件
通过宿主使用终结点定义到 WCF 服务的连接。宿主配置具有基地址。这对于我们的应用程序将具有多个绑定是必需的。我们将在稍后阶段详细探讨此配置,用于多个托管配置。我们只需要添加内容来自定义此托管以用于不同的绑定。
<configuration>
<system.serviceModel>
<services>
<service name="WcfCustomerService.CustomerService">
<endpoint address =""
binding="basicHttpBinding"
contract="WcfCustomerService.ICustomerService"/>
<host>
<baseAddresses>
<add baseAddress ="https://:8081/CustomerService"/>
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
一旦上述代码就绪,我们就可以很好地构建并运行控制台宿主可执行文件。操作:CTRL+F5
***构建并运行 WCFHost:输出
3. 故障排除:最常见的问题
我们配置的终结点端口可能被传输层中的其他应用程序使用,因此我们可能会遇到以下错误。补救措施是将地址端口号[XXX]更改为未使用的端口,例如 https://:XXX/ABC
WCF 客户端
为 WCF 客户端添加项目 -> 窗口控制台应用程序。
1. 配置 WCF 服务代理:元数据交换
添加服务引用(项目 -> 添加服务引用菜单)
可能会发生以下错误:WCF Host 未运行。**错误 1:下载 'https://:8081/CustomerService' 时出错。无法连接到远程服务器,因为目标计算机主动拒绝了连接 10.0.0.1:8081 元数据包含无法解析的引用:'https://:8081/CustomerService'。在 https://:8081/CustomerService 没有侦听终结点可以接受消息。这通常由不正确的地址或 SOAP 动作引起。如果存在 InnerException,请参阅它以获取更多详细信息。无法连接到远程服务器,因为目标计算机主动拒绝了连接 10.0.0.1:8081 如果服务在当前解决方案中定义,请尝试构建解决方案并再次添加服务引用。**
WCF 宿主配置中未配置元数据
***添加元数据交换
为了创建代理类或允许 VS2010 添加服务引用(项目 ➤ 添加服务引用菜单)正确创建代理类,我们需要添加元数据交换配置。这可以通过在宿主配置文件中包含 <Behaviour> 标签来实现。宿主将创建服务的元数据表示以帮助为客户端创建代理类。这与我们在 Web 服务 WSDL 中拥有的概念相同。我们还可以使用 .net 4.0 框架 SDK 工具:**svcutil.exe** 编写代理类。在现有宿主配置中,只需在 system.serviceModel 下添加行为标签,并在 services 节点下给出 behavior.configuration。
<behaviors>
<serviceBehaviors>
<behavior name="CustomerServiceMEXBehavior" >
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
完整的 WCF 宿主配置设置
<configuration>
<system.serviceModel>
<services>
<service name="WcfCustomerService.CustomerService"
behaviorConfiguration = "CustomerServiceMEXBehavior" >
<endpoint address =""
binding="basicHttpBinding"
contract="WcfCustomerService.ICustomerService"/>
<host>
<baseAddresses>
<add baseAddress ="https://:8081/CustomerService"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CustomerServiceMEXBehavior" >
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
添加上述标签后,再次右键单击 WCFClient 项目添加服务引用。输入地址 https://:8081/CustomerService 并单击“Go”按钮。引用将成功添加。
2. 主程序:客户端代码
在主程序中消耗 WCF 服务。BasicHttpBinding_ICustomerService 可以在 app.config 文件中找到。此实现的主要亮点是我们使用 HTTP 绑定消耗服务。在后面部分,我们将介绍通过 IIS 和 TCP 绑定消耗服务。
注意:如果我们将 IIS 用作托管平台,那么我们不需要像现在这样显式的宿主控制台应用程序。
using WCFClient.BasicHttpBindingService;
namespace WCFClient
{
class Program
{
static void Main(string[] args)
{
try
{
using (CustomerServiceClient customerServiceClient = new CustomerServiceClient("BasicHttpBinding_ICustomerService"))
{
Console.WriteLine("***** Console Based WCF Client Started *****");
Customer customer = customerServiceClient.GetCustomerDetails(1);
Console.WriteLine("***** Consume WCF Service *****");
Console.WriteLine("HTTP Binding WCF Service Response :{0}", customer.CustomerName);
Console.ReadLine();
}
}
catch (Exception ex)
{
Console.WriteLine("HTTP Binding WCF Service Response ERROR:{0}", ex);
}
}
}
}
3.WCF 客户端配置设置 App.config
一旦我们成功添加服务引用,此配置将默认创建。
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ICustomerService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://:8081/CustomerService" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_ICustomerService" contract="BasicHttpBindingService.ICustomerService"
name="BasicHttpBinding_ICustomerService" />
</client>
</system.serviceModel>
</configuration>
现在构建并运行 WCFClient 控制台应用程序。CTRL+F5。通过上述步骤和故障排除,我们能够创建 WCF 服务、WCF 托管引擎和 WCF 客户端。
***WCF 服务 -WCF 宿主-WCF 客户端层快照
***运行 WCFClient:输出
启用多重绑定:<HTTP 绑定><TCP 绑定> 等
在上面的示例中,我们在终结点中配置了 HTTP 绑定。现在我们将配置 TCP 绑定。目标是客户端可以一次通过多个绑定消耗服务。我们可以在宿主控制台应用程序的配置文件中包含多个绑定信息。
1. 配置 TCP 绑定的 ENDPOINT
<endpoint address ="net.tcp://:8090/CustomerService"
binding="netTcpBinding"
contract="WcfCustomerService.ICustomerService"/>
<host> <baseAddresses> <add baseAddress ="https://:8081/CustomerService"/> <add baseAddress ="net.tcp://:8090/CustomerService"/> </baseAddresses> </host>
<configuration>
<system.serviceModel>
<services>
<service name="WcfCustomerService.CustomerService"
behaviorConfiguration = "CustomerServiceMEXBehavior" >
<endpoint address =""
binding="basicHttpBinding"
contract="WcfCustomerService.ICustomerService"/>
<endpoint address ="net.tcp://:8090/CustomerService"
binding="netTcpBinding"
contract="WcfCustomerService.ICustomerService"/>
<host>
<baseAddresses>
<add baseAddress ="https://:8081/CustomerService"/>
<add baseAddress ="net.tcp://:8090/CustomerService"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CustomerServiceMEXBehavior" >
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration >
再次构建并运行 WCFHost.exe。CTRL+F5。保持此服务运行,以便我们可以在 WCFClient.exe 中获取此服务的引用
***运行 WCFHost.exe
2. 在 WCFClient.exe 中添加服务引用
转到 WCFClient.exe 并更新服务引用 (BasicHttpBindingService) 文件。将出现对话框,添加 TCP 地址。一旦我们更新,以下标签将默认添加到 WCFClient.exe 的 app.config 文件中
<netTcpBinding>
<binding name="NetTcpBinding_ICustomerService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10"
maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="https://:8081/CustomerService" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_ICustomerService" contract="BasicHttpBindingService.ICustomerService"
name="BasicHttpBinding_ICustomerService" />
<endpoint address="net.tcp://:8091/CustomerService"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_ICustomerService"
contract="BasicHttpBindingService.ICustomerService" name="NetTcpBinding_ICustomerService">
</endpoint>
</client >
***更新 WCFClient 中的 WCF 服务请求
3. 从 WCFClient 调用 WCF 服务
使用以下代码通过 TCP 绑定调用 WCFService。
namespace WCFClient
{
class Program
{
static void Main(string[] args)
{
try
{
using (CustomerServiceClient customerServiceClient = new CustomerServiceClient("BasicHttpBinding_ICustomerService"))
{
Console.WriteLine("***** Console Based WCF Client Started *****");
Customer customer = customerServiceClient.GetCustomerDetails(1);
Console.WriteLine("***** Consume WCF Service *****");
Console.WriteLine("HTTP Binding WCF Service Response :{0}", customer.CustomerName);
}
using (CustomerServiceClient customerServiceClient = new CustomerServiceClient("NetTcpBinding_ICustomerService"))
{
Console.WriteLine("***** Console Based WCF Client Started *****");
Customer customer = customerServiceClient.GetCustomerDetails(1);
Console.WriteLine("***** Consume WCF Service *****");
Console.WriteLine("TCP Binding WCF Service Response :{0}", customer.CustomerName);
}
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("HTTP/TCP Binding WCF Service Response ERROR:{0}", ex);
}
}
}
}
选择 WCFClient 并按 CTRL+F5
***运行 WCFClient:输出
为 WCF 服务配置 IIS 托管平台
如果我们将 IIS 用作宿主引擎,则无需创建显式控制台或窗口服务来持续运行 WCF 服务。这里没有宿主应用程序。所以您一定在想,我可以在哪里提及宿主和客户端之间的终结点。在之前的示例中,宿主应用程序包含客户端消耗服务的终结点信息。在 IIS 作为宿主引擎时,我们可以在 WCFService 配置本身中指定终结点信息。即 WCF 服务应用程序的 Web.config 文件。
1. 为 WCF 服务创建虚拟目录:WCFCustomerService
选择 WCFCustomerService 并右键单击并选择属性菜单。在 VS2010 中,我们获得了为 WCFCustomerService 创建虚拟目录的选项。
2. 在 WCFCustomerService 包中添加服务终结点。[WCF 服务-服务器]
如果使用 IIS 平台,则不需要宿主包。在这种情况下,我们需要在服务器本身中配置终结点。在 WCFCustomerService 包配置文件本身中添加以下标签。
<services>
<service name="WcfCustomerService.CustomerService">
<endpoint address =""
binding="basicHttpBinding"
contract="WcfCustomerService.ICustomerService"/>
</service>
</services>
注意:服务、宿主和客户端的配置文件几乎相同。此配置可以使用 VS2010 中提供的工具完成,但动手操作将有助于理解概念。
3. 在 WCFClient 中添加服务引用
创建虚拟目录并在 WCFCustomerService 包中提及终结点后,在 WCFClient.exe 中为 IIS 中托管的服务添加服务引用。
***服务引用中的多重绑定
以下终结点和绑定将默认添加到 WCFClient 配置文件中。这里没有手动添加标签。
注意:如果 IIS 设置为 Windows 身份验证,则在以下配置中将 Windows 设置为 <transport clientCredentialType="Windows"> <security mode="TransportCredentialOnly"> 在 basicHttpBinding 下
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ICustomerService1" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</bindings>
</basicHttpBinding>
<client>
<endpoint address="https://:8081/CustomerService" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_ICustomerService" contract="BasicHttpBindingService.ICustomerService"
name="BasicHttpBinding_ICustomerService" />
<endpoint address="net.tcp://:8091/CustomerService"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_ICustomerService"
contract="BasicHttpBindingService.ICustomerService" name="NetTcpBinding_ICustomerService" />
<endpoint address="http://10.10.10.10/WcfCustomerService1/CustomerService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ICustomerService1"
contract="IISHostCustomerService.ICustomerService" name="BasicHttpBinding_ICustomerService1" />
</client>
4. 从 WCFClient 调用 WCF 服务
在多重绑定情况下,必须包含特定的引用。
using WCFClient.BasicHttpBindingService;
using WCFClient.IISHostCustomerService;
namespace WCFClient
{
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("...HTTP BINDING...");
using (BasicHttpBindingService.CustomerServiceClient customerServiceClient1 =
new BasicHttpBindingService.CustomerServiceClient("BasicHttpBinding_ICustomerService"))
{
Console.WriteLine("***** Console Based WCF Client Started *****");
BasicHttpBindingService.Customer customer = customerServiceClient1.GetCustomerDetails(1);
Console.WriteLine("***** Consume WCF Service *****");
Console.WriteLine("HTTP Binding WCF Service Response :{0}", customer.CustomerName);
}
Console.WriteLine("...");
Console.WriteLine("...TCP BINDING...");
using (BasicHttpBindingService.CustomerServiceClient customerServiceClient2 =
new BasicHttpBindingService.CustomerServiceClient("NetTcpBinding_ICustomerService"))
{
Console.WriteLine("***** Console Based WCF Client Started *****");
BasicHttpBindingService.Customer customer = customerServiceClient2.GetCustomerDetails(1);
Console.WriteLine("***** Consume WCF Service *****");
Console.WriteLine("TCP Binding WCF Service Response :{0}", customer.CustomerName);
}
Console.WriteLine("...");
Console.WriteLine("...IIS HTTP BINDING...");
using (IISHostCustomerService.CustomerServiceClient customerServiceClient3 = new IISHostCustomerService.CustomerServiceClient("BasicHttpBinding_ICustomerService1"))
{
Console.WriteLine("***** Console Based WCF Client Started *****");
IISHostCustomerService.Customer customer = customerServiceClient3.GetCustomerDetails(1);
Console.WriteLine("***** Consume WCF Service *****");
Console.WriteLine("IIS HTTP Binding WCF Service Response :{0}", customer.CustomerName);
}
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("HTTP/TCP Binding WCF Service Response ERROR:{0}", ex);
}
}
}
}
***运行 WCFClient:输出
在 WCFClient.exe 中异步调用 WCF 服务
添加上述任何服务引用。
在 WCFClient 中添加服务引用
单击如下屏幕截图所示的高级按钮。
在客户端部分选择异步选项并单击确定,关闭对话框。终结点配置将默认添加到 WCFClient App.config 文件中
<client>
<endpoint address="net.tcp://:8091/CustomerService"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_ICustomerService1"
contract="AsynchronousCallWCFService.ICustomerService" name="NetTcpBinding_ICustomerService1">
</endpoint>
</client>
调用 WCF 服务的异步调用:WCFClient
namespace WCFClient
{
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("...");
Console.WriteLine("...Async Calling of WCF Service...");
Console.WriteLine("***** The Async Customer Client *****\n");
using (AsynchronousCallWCFService.CustomerServiceClient asynProxyService =
new AsynchronousCallWCFService.CustomerServiceClient("NetTcpBinding_ICustomerService1"))
{
asynProxyService.Open();
IAsyncResult asyncResult = asynProxyService.BeginGetServerResponse(786,
strResult =>
{
Console.WriteLine
("Get Server Response = {0}", asynProxyService.EndGetServerResponse(strResult));
},
null);
while (!asyncResult.IsCompleted)
{
Thread.Sleep(100);
Console.WriteLine("In Progress...");
}
}
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine
("Aysnhcronous WCFClient Server Response ERROR:{0}", ex);
}
}
}
}
运行 WCFClient.exe,您可以看到来自 WCFCustomerService 的响应。我的整个想法是展示最简单的案例,可以帮助开发人员在他们的应用程序中构建 WCF 结构。最初我自己从头开始做,但花了很多时间才理解概念和实现。想到将其作为演示并帮助有兴趣尝试简单 WCF 开发的人。
结论
我希望初学者能够轻松掌握 WCF 服务的使用,并减少问题。任何建议和更正都非常欢迎。