<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>WCF on 冯威的博客</title><link>https://fwhyy.com/tags/wcf/</link><description>Recent content in WCF on 冯威的博客</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Sun, 29 Aug 2010 00:00:00 +0800</lastBuildDate><atom:link href="https://fwhyy.com/tags/wcf/atom.xml" rel="self" type="application/rss+xml"/><item><title>WCF中绑定的简单介绍</title><link>https://fwhyy.com/2010/08/the-simple-introduction-of-the-wcf-binding/</link><pubDate>Sun, 29 Aug 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/08/the-simple-introduction-of-the-wcf-binding/</guid><description>&lt;h2 id="绑定基本概念"&gt;绑定基本概念&lt;/h2&gt;
&lt;p&gt;绑定就是一个从通用基础类型派生出来的运行时类型。绑定中描述了传输协议，消息编码格式和其他的一些用于通信的通信协议。&lt;/p&gt;
&lt;h2 id="绑定的种类介绍"&gt;绑定的种类介绍&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302117082.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="两种方式来配置端点以及相关联的绑定"&gt;两种方式来配置端点以及相关联的绑定&lt;/h2&gt;
&lt;p&gt;绑定的配置可以使用配置文件的形式或是代码的形式，如下面的代码：&lt;/p&gt;
&lt;p&gt;配置文件形式(服务端)&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;endpoint address=&amp;#34;HelloWorld&amp;#34; binding=&amp;#34;basicHttpBinding&amp;#34;
 contract=&amp;#34;Service.IHelloWorldService&amp;#34;&amp;gt;&amp;lt;/endpoint&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;配置文件形式(客户端)&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;endpoint address=&amp;#34;http://localhost:10000/HelloWorld&amp;#34; binding=&amp;#34;basicHttpBinding&amp;#34;
 bindingConfiguration=&amp;#34;BasicHttpBinding_oec2003&amp;#34; contract=&amp;#34;HelloWorld.oec2003&amp;#34;
 name=&amp;#34;BasicHttpBinding_oec2003&amp;#34; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;代码形式&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;WSHttpBinding wsHttpBinding = new WSHttpBinding();
wsHttpBinding.Security.Mode = SecurityMode.Transport;
wsHttpBinding.ReliableSession.Enabled = true;
wsHttpBinding.TransactionFlow = true;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="绑定的功能"&gt;绑定的功能&lt;/h2&gt;
&lt;p&gt;每个绑定都必要要提供至少一个传输协议，一个消息编码格式和一个相关的消息版本，除此之外还有一些其他的功能，如安全性、双向通信、事务等。&lt;/p&gt;
&lt;p&gt;传输协议：有Http、Https、Tcp、命名管线和MSMQ，这些都有专门的绑定类型与之对应。&lt;/p&gt;
&lt;p&gt;消息编码：描述了消息是如何格式化的，可以使用Binary、Text或Mtom。&lt;/p&gt;
&lt;p&gt;消息版本：不管消息的编码格式如何，消息总是表示为SOAP1.1或是SOAP1.2.&lt;/p&gt;
&lt;p&gt;传输安全性：指在线传输证书、签名和加密的能力。一般使用SSL。&lt;/p&gt;
&lt;p&gt;消息安全性：指独立于传输层的传输证书、签名和加密的能力。&lt;/p&gt;
&lt;p&gt;双向通信：TCP和命名管线可以直接支持，但Http不支持。&lt;/p&gt;
&lt;p&gt;这些绑定的功能都是通过配置绑定元素来进行激活看，下面就简单介绍下绑定元素。&lt;/p&gt;
&lt;p&gt;每一种绑定都会有一个绑定元素的集合，像前面提到的传输协议、编码格式等都是绑定元素的一种。绑定元素在Net对应的类型都是继承自BindingElement类。在WCF中的每一种绑定必须有一个传输协议和一个消息编码格式。传输协议的通用绑定元素为TransportBindingElement，有下面一些子类继承TransportBindingElement，分别代表不同类型的传输协议。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HttpTransportBindingElement&lt;/li&gt;
&lt;li&gt;HttpsTransportBindingElement&lt;/li&gt;
&lt;li&gt;MsmqTransportBindingElement&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;编码格式通用绑定元素为MessageEncodingBindingElement，一些子类如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;BinaryMessageEncodingBindingElement&lt;/li&gt;
&lt;li&gt;TextMessageEncodingBindingElement&lt;/li&gt;
&lt;li&gt;MtomMessageEncodingBindingElement&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;还有一些其他的不是必须但是在一些特定场合特别有用的绑定元素：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;安全相关：SecurityBindingElement&lt;/li&gt;
&lt;li&gt;混合双向通信：CompositeDuplexBindingElement OneWayBindingElement&lt;/li&gt;
&lt;li&gt;可靠通信：ReliableSessionBindingElement&lt;/li&gt;
&lt;li&gt;事务：TransactionFlowBindingElement&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;使用上面的绑定元素必须引用命名空间System.ServiceModel.Channels&lt;/p&gt;
&lt;p&gt;在WCF中使用绑定通常会在配置文件中来进行，尽管也可以用代码的方式实现，但在配置文件中更加灵活。可以在端点的bindingConfiguration来进行扩展。看下面代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;system.serviceModel&amp;gt;
 &amp;lt;services&amp;gt;
 &amp;lt;service name=&amp;#34;Service.HelloWorldService&amp;#34; behaviorConfiguration=&amp;#34;HelloWorldBebavior&amp;#34;&amp;gt;
 &amp;lt;endpoint address=&amp;#34;HelloWorld&amp;#34; binding=&amp;#34;basicHttpBinding&amp;#34;
 bindingConfiguration=&amp;#34;baseBinding_oec2003&amp;#34;
 contract=&amp;#34;Service.IHelloWorldService&amp;#34;&amp;gt;&amp;lt;/endpoint&amp;gt;
 &amp;lt;endpoint address=&amp;#34;mex&amp;#34; binding=&amp;#34;mexHttpBinding&amp;#34; contract=&amp;#34;IMetadataExchange&amp;#34; /&amp;gt;
 &amp;lt;host&amp;gt;
 &amp;lt;baseAddresses&amp;gt;
 &amp;lt;add baseAddress=&amp;#34;http://localhost:10000/&amp;#34;/&amp;gt;
 &amp;lt;/baseAddresses&amp;gt;
 &amp;lt;/host&amp;gt;
 &amp;lt;/service&amp;gt;
 &amp;lt;/services&amp;gt;
 &amp;lt;bindings&amp;gt;
 &amp;lt;basicHttpBinding&amp;gt;
 &amp;lt;binding name=&amp;#34;baseBinding_oec2003&amp;#34; maxReceivedMessageSize=&amp;#34;10000&amp;#34;
 transferMode=&amp;#34;Buffered&amp;#34;&amp;gt;
 &amp;lt;security mode=&amp;#34;Transport&amp;#34;&amp;gt;&amp;lt;/security&amp;gt;
 &amp;lt;/binding&amp;gt;
 &amp;lt;/basicHttpBinding&amp;gt;
 &amp;lt;/bindings&amp;gt;
 &amp;lt;behaviors&amp;gt;
 &amp;lt;serviceBehaviors&amp;gt;
 &amp;lt;behavior name=&amp;#34;HelloWorldBebavior&amp;#34;&amp;gt;
 &amp;lt;serviceMetadata httpGetEnabled=&amp;#34;true&amp;#34; /&amp;gt;
 &amp;lt;/behavior&amp;gt;
 &amp;lt;/serviceBehaviors&amp;gt;
 &amp;lt;/behaviors&amp;gt;
&amp;lt;/system.serviceModel&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;本文只是简单介绍了下绑定的概念以及绑定的种类，以及使用了一些代码来说明绑定的运用，关于每种绑定的详细介绍及用法在后面的博文中介绍。&lt;/p&gt;</description></item><item><title>WCF契约的简单介绍（服务契约 数据契约 消息契约）</title><link>https://fwhyy.com/2010/07/the-simple-introduction-of-wcf-contract/</link><pubDate>Wed, 21 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/the-simple-introduction-of-wcf-contract/</guid><description>&lt;p&gt;本篇博文只是简单说下WCF中的契约的种类、作用以及一些简单的代码示例。在WCF中契约分为服务契约、数据契约和消息契约。下面对这几种契约进行简单的介绍。&lt;/p&gt;
&lt;h2 id="服务契约"&gt;服务契约&lt;/h2&gt;
&lt;p&gt;服务契约描述了暴露给外部的类型（接口或类）、服务所支持的操作、使用的消息交换模式和消息的格式。每个WCF服务必须实现至少一个服务契约。使用服务契约必须要引用命名空间System.ServiceModel 。服务契约中常用到的三个特性：&lt;/p&gt;
&lt;h3 id="servicecontractattribute"&gt;ServiceContractAttribute&lt;/h3&gt;
&lt;p&gt;该特性定义在类或接口上，用来描述一个相关操作的集合。ServiceContractAttribute特性还有如下的一些属性值可以设置：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Name：给服务契约定义一个名称，而不是使用接口或是类的类型名，在客户端添加服务引用时会用到。&lt;/li&gt;
&lt;li&gt;Namespace：命名空间，默认值为http://tempuri.org。&lt;/li&gt;
&lt;li&gt;CallbackContract：将另一个服务契约定义为回调契约，使得客户端可以接收服务端的异步消息。&lt;/li&gt;
&lt;li&gt;ProtectionLevel：控制契约中发送给消息的保护方式是否需要被签名和加密。该属性为System.Net.Security.ProtectionLevel枚举类型。&lt;/li&gt;
&lt;li&gt;SessionMode：确定会话是否为公开服务契约的端点所支持。&lt;/li&gt;
&lt;li&gt;ConfigurationName：服务的配置名称。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[ServiceContract(Name=&amp;#34;HelloWorld&amp;#34;,Namespace=&amp;#34;http://oec2003.cnblogs.com&amp;#34;]
public interface IHelloWorldService
{ 

}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="operationcontractattribute"&gt;OperationContractAttribute&lt;/h3&gt;
&lt;p&gt;用OperationContractAttribute标记的方法即为一个服务操作，简单的使用该特性就可以让一个方法加入到服务契约的操作队列中，可以被客户端所调用。该特性也有一些设置消息交换方式的属性。如下&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Name：定义一个操作名称，而不是使用方法名称。&lt;/li&gt;
&lt;li&gt;Action：该操作消息的动作标题。&lt;/li&gt;
&lt;li&gt;ReplyAction：响应该操作消息的动作标题。&lt;/li&gt;
&lt;li&gt;IsOneWay：设置该操作是否单向和没有回复，如果操作是单向的，将不支持ReplyAction。&lt;/li&gt;
&lt;li&gt;ProtectionLevel：允许你控制特定的操作消息是否被保护，操作中的ProtectionLevel属性将覆盖服务契约中的ProtectionLevel。该属性为System.Net.Security.ProtectionLevel枚举类型。&lt;/li&gt;
&lt;li&gt;IsInitiating：操作是否可以用来初始化会话。&lt;/li&gt;
&lt;li&gt;IsTerminating：操作是否中止一个会话。&lt;/li&gt;
&lt;li&gt;AsyncPattern：将服务操作定义为异步实现模式。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[ServiceContract(Namespace=&amp;#34;http://oec2003.cnblogs.com&amp;#34;,Name=&amp;#34;oec2003&amp;#34;,
 ConfigurationName=&amp;#34;IHelloWorldService&amp;#34;)]
public interface IHelloWorldService
{
 [OperationContract(Name=&amp;#34;oec2003SayHello&amp;#34;,
 Action = &amp;#34;http://oec2003.cnblogs.com/IHelloWorldService/Hello&amp;#34;,
 ReplyAction = &amp;#34;http://oec2003.cnblogs.com/IHelloWorldService/HelloReply&amp;#34;)]
 string SayHello();
}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="messageparameterattribute"&gt;MessageParameterAttribute&lt;/h3&gt;
&lt;p&gt;使用 MessageParameterAttribute 可以控制参数或返回值的名称。此属性对于已用 MessageContractAttribute 特性标记的参数无效。该特性只有一个Name属性，看如下代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[ServiceContract(Namespace=&amp;#34;http://oec2003.cnblogs.com&amp;#34;,Name=&amp;#34;oec2003&amp;#34;,
 ConfigurationName=&amp;#34;IHelloWorldService&amp;#34;)]
public interface IHelloWorldService
{
 [OperationContract]
 [return: MessageParameter(Name = &amp;#34;responseString&amp;#34;)]
 string SayHello([MessageParameter(Name = &amp;#34;string&amp;#34;)]string meg);
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="数据契约"&gt;数据契约&lt;/h2&gt;
&lt;p&gt;使用数据契约必须引用System.Runtime.Serialization命名空间，在类型上使用DataContractAttribute可以创建数据契约，类型中的成员使用DataMember标记。代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[DataContract]
public class User
{
 [DataMember]
 public int Age { get; set; }
 [DataMember]
 public string Name { get; set; }
 [DataMember]
 public string Email { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="datacontractattribute"&gt;DataContractAttribute&lt;/h3&gt;
&lt;p&gt;DataContractAttribute特性定义在类型之上，类型包括类、结构、枚举但不包括接口。DataContractAttribute特性不能被继承，即继承自有DataContractAttribute特性标记的类并不是数据契约，必须显示使用DataContractAttribute标记才能成为数据契约。DataContractAttribute特性有IsReference、Name和Namespace三个属性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IsReference：bool类型，表示在进行序列化的时候是否保持对象现有的引用结构。&lt;/li&gt;
&lt;li&gt;Name：名称。&lt;/li&gt;
&lt;li&gt;Namespace：命名空间。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[DataContract(IsReference=true,Name=&amp;#34;MyUser&amp;#34;,Namespace=&amp;#34;http://oec2003.cnblogs.com&amp;#34;)]
public class User
{
 [DataMember]
 public int Age { get; set; }
 [DataMember]
 public string Name { get; set; }
 [DataMember]
 public string Email { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="datamemberattribute"&gt;DataMemberAttribute&lt;/h3&gt;
&lt;p&gt;使用DataMemberAttribute标记的类型成员才能成为数据契约的数据成员。这个和服务契约中的OperationContractAttribute类似。DataMemberAttribute特性有如下四个属性:&lt;/p&gt;</description></item><item><title>WCF问题:“HTTP 错误 404.17 – Not Found 请求的内容似乎是脚本，因而将无法由静态文件处理程序来处理”解决方法</title><link>https://fwhyy.com/2010/07/wcf-problem-http-error-404-17-solution/</link><pubDate>Mon, 19 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/wcf-problem-http-error-404-17-solution/</guid><description>&lt;p&gt;在写&lt;a href="http://blog.fwhyy.com/?p=23"&gt;在IIS中寄存已有WCF服务&lt;/a&gt;文章的时候，创建了WCF Service模板站点，按F5运行的时候会出现“HTTP 错误 404.17 – Not Found 请求的内容似乎是脚本，因而将无法由静态文件处理程序来处理 ”的错误，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290630316.webp" alt="2010-07-19_173102" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在网上查出的解决方为重新注册WCF，在命令提示符中输入如下图的命令运行即可:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290630346.webp" alt="2010-07-19_173337" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;安装成功后再次运行站点就会出现正确的页面，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290638830.webp" alt="image-20220129063819672" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>在IIS中寄存已有WCF服务</title><link>https://fwhyy.com/2010/07/register-existing-wcf-service-in-iis/</link><pubDate>Mon, 19 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/register-existing-wcf-service-in-iis/</guid><description>&lt;p&gt;IIS是WCF服务的宿主之一，在新建Web Site的时候有WCF Service模板可以供选择，不过依据WCF Service模板创建的站点是将服务和宿主整合在一起了，下面就来看看如何将一个已有的WCF服务寄存在IIS中。&lt;/p&gt;
&lt;p&gt;1 在&lt;a href="http://www.cnblogs.com/oec2003/archive/2010/07/15/1778013.html"&gt;一个简单的WCF示例&lt;/a&gt;一文的解决方案中添加新的站点，选择WCF Service模板，地址设置为http://localhost/IISHostedService，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301618792.webp" alt="2010-07-19_154628" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2 确定后，WCF Service模板就生成了一个带有服务的站点，因为我们要将已有服务寄存在该站点中，所以要删除站点中自带的服务，服务的文件在App_Code目录中，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301619850.webp" alt="2010-07-19_155053" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3 添加对Service项目的引用，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301619979.webp" alt="2010-07-19_161549" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;4 双击项目中Service.svc文件，修改@ServiceHost指令，关联上服务类型，修改后的代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;%@ ServiceHost Language=&amp;#34;C#&amp;#34; Debug=&amp;#34;true&amp;#34; Service=&amp;#34;Service.HelloWorldService&amp;#34; %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;5 修改站点的Web.Config文件，找到Service节点，修改Service节点的Name属性、endpoint节点的绑定属性和契约属性，修改后的代码如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301619029.webp" alt="2010-07-19_162314" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;6 将该站点设置为启动项目，按F5运行，如果Web.Config文件中没有配置元数据交换端点，运行后会看到如下页面：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301619804.webp" alt="2010-07-19_164149" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;可以根据上面页面中的步骤一步一步来配置元数据交换端点，配置好后，如果serviceMetadata节点的httpGetEnabled属性设置为false，运行后如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301619610.webp" alt="2010-07-19_164721" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在设置httpGetEnabled属性为true，再次运行可以看到svcutil指令后是一个带有?wsdl的链接地址，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301619381.webp" alt="2010-07-19_1649411" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击这个链接，可以看到服务的WSDL文档，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301620414.webp" alt="2010-07-19_165128" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;7 IIS宿主部分已经写好，现在要做的就是使用SvcUtil工具来生成客户端的代理，打开VS2008 的命令提示窗口，输入先前站点运行后的命令提示，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301620416.webp" alt="2010-07-19_170851" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;8 执行后生成了一个代理文件和一个配置文件，在目录C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC 中，将这两个文件拷贝到客户程序中，配置文件改名为app.config，然后再客户程序中添加如下代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;class Program
{
 static void Main(string[] args)
 {
 oec2003Client proxy = new oec2003Client();
 Console.WriteLine(proxy.SayHello());
 proxy.Close();
 Console.ReadLine();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;9 运行客户程序可以看到如下结果&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301620809.webp" alt="2010-07-19_171432" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>WCF中客户端生成代理的两种方式</title><link>https://fwhyy.com/2010/07/wcf-client-generation-agent-in-two-ways/</link><pubDate>Fri, 16 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/wcf-client-generation-agent-in-two-ways/</guid><description>&lt;p&gt;WCF程序中客户端要生成代理才能调用服务，在客户端生成代理有多种方式，如用ChannelFactory和添加服务引用等。下面就分别来介绍下这两种生成代理的方式。&lt;/p&gt;
&lt;h2 id="使用channelfactory"&gt;使用ChannelFactory&lt;/h2&gt;
&lt;p&gt;使用ChannelFactory创建代理需要的条件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;服务端点的地址，即在宿主中用程序设置的或是配置文件中设置的。&lt;/li&gt;
&lt;li&gt;服务端点的绑定协议。&lt;/li&gt;
&lt;li&gt;服务契约的元数据，可以将服务契约复制一份到客户端或是在客户端添加对服务的引用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下面的代码示例为通过ChannelFactory手动创建代理&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;EndpointAddress ea =
 new EndpointAddress(&amp;#34;http://localhost:10000/Service/HelloWorldService&amp;#34;);
IHelloWorldService proxy =
 ChannelFactory&amp;lt;IHelloWorldService&amp;gt;.CreateChannel(new BasicHttpBinding(),ea);
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;EndpointAddress：端点地址，该类的实例作为CreateChannel方法的一个参数，实例化EndpointAddress时给的地址要和宿主中设置的地址一致。&lt;/li&gt;
&lt;li&gt;IHelloWorldService：这个是服务契约在客户端的一个副本，不包含具体的实现。&lt;/li&gt;
&lt;li&gt;ChannelFactory&lt;T&gt;：一个服务模型类型，可以产生客户代理和基础信道栈，使用该类的CreateChannel可以生成代理，有两个参数，绑定类型和端点地址，绑定类型和端点地址要和宿主中设置的一致。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="添加服务引用的方式"&gt;添加服务引用的方式&lt;/h2&gt;
&lt;p&gt;1 在宿主的配置文件中配置元数据呢交换节点，并在行为中设置serviceMetadata，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290626408.webp" alt="2010-07-16_163822" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2 在客户端添加服务引用时必须启动宿主。&lt;/p&gt;
&lt;p&gt;3 配置文件设置好后，启动宿主，然后再客户项目上右击选择“Add Service Reference ”，在地址框中输入正确地址，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290627453.webp" alt="2010-07-16_164810" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Http://localhost:10000/mex：是配置文件中的基地址http://localhost:10000加上端点地址mex组合而成。&lt;/p&gt;
&lt;p&gt;oec2003：为服务契约中设置的属性Name的值，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290627963.webp" alt="2010-07-16_165418" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;HelloWorld：为自己定义的引用到客户端的名称。&lt;/p&gt;
&lt;p&gt;4 添加服务引用后客户端的项目列表显示如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290627665.webp" alt="2010-07-16_165914" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;5 在客户端添加如下代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;class Program
{
 static void Main(string[] args)
 {
 HelloWorld.oec2003Client proxy = new Client.HelloWorld.oec2003Client();
 Console.WriteLine(proxy.SayHello());
 Console.ReadLine();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;6 先运行宿主，然后运行客户程序就可以看到调用服务返回的结果。&lt;/p&gt;</description></item><item><title>一个简单的WCF示例</title><link>https://fwhyy.com/2010/07/a-simple-wcf-example/</link><pubDate>Thu, 15 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/a-simple-wcf-example/</guid><description>&lt;p&gt;WCF程序分为三个部分：服务、宿主和客户端。下面就一步一步按这三个部分来构建一个简单的WCF程序。可以选择这三个部分都创建独立的解决方案，也可以在一个解决方案中创建三个项目。在下面的例子中将采用将三个项目放在一个解决方案中。服务使用类库项目，宿主和客户端使用控制台程序。&lt;/p&gt;</description></item><item><title>WCF的一些基本知识点</title><link>https://fwhyy.com/2010/07/some-basic-knowledge-of-wcf/</link><pubDate>Wed, 14 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/some-basic-knowledge-of-wcf/</guid><description>&lt;p&gt;Windows Communication Foundation (WCF)是Microsoft为构建面向服务的应用提供的分布式通信编程框架，是.NET Framework 3.5的重要组成部分。使用该框架，开发人员可以构建跨平台、安全、可靠和支持事务处理的企业级互联应用解决方案。&lt;/p&gt;
&lt;p&gt;构建一个WCF程序通常分为三个部分：服务类（Server）、宿主（Host）、客户程序（Client）。有一个很重要的程序集（System.ServeiceModel）要引用，它包含WCF的核心功能。&lt;/p&gt;
&lt;p&gt;贯穿整个WCF的程序会涉及到服务、契约、寄存、端点、地址、绑定、与数据、代理、通道、行为等概念，下面一一介绍下&lt;/p&gt;
&lt;h2 id="服务"&gt;服务&lt;/h2&gt;
&lt;p&gt;通常为一个类库项目，在实际开发中建议将服务类独立出来。服务类中封装业务功能并提供可以让外部访问的方法集接口。一些具体的操作通常抽像为接口然后由类来实现，并且接口上要用ServiceContractAtrribute来定义，接口中的方法要用OperationContractAttribute来定义，这样任何实现了该接口的类都是服务类型。当然也可以直接在类上来定义契约。&lt;/p&gt;
&lt;h2 id="契约"&gt;契约&lt;/h2&gt;
&lt;p&gt;契约定义了服务向外界发布的操作，以及WCF 服务与客户相互通讯时的消息格式。WCF 中有四种类型的契约。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;服务契约: 定义一个接口，给接口附加[ServiceContract] ，给接口方法附加[OperationContract]&lt;/li&gt;
&lt;li&gt;数据契约: 数据契约定义将在客户端与服务器端传送的各种数据类型。定义数据契约时需要使用[DataContract] 和[DataMember] 。&lt;/li&gt;
&lt;li&gt;消息契约: 可以使用消息契约来定制WCF 服务与WCF 客户间相互通讯的SOAP 消息格式。&lt;/li&gt;
&lt;li&gt;错误契约: 定义在服务中如何处理异常，以及这些异常又如何传送到客户端。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="寄存"&gt;寄存&lt;/h2&gt;
&lt;p&gt;服务做好了后需要能够运行，因为客户在调用服务的时候服务必须是处在运行状态的，这就需要将服务寄存在一个地方，在一些Demo中会使用控制台程序来做宿主寄存服务，除此之外还可以是WinForm程序、WPF应用、Windows 服务、IIS、WAS等。&lt;/p&gt;
&lt;h2 id="端点"&gt;端点&lt;/h2&gt;
&lt;p&gt;端点的用处是方便客户程序调用服务的操作。端点定义了在什么地方可以访问服务、用什么方式访问以及有哪些操作可用，这就是端点的三要素（地址 绑定 契约）。端点可以在程序中设置也可以用配置文件的形式设置。&lt;/p&gt;
&lt;h2 id="地址"&gt;地址:&lt;/h2&gt;
&lt;p&gt;地址由模式、域、端口和路径组成。模式指所用的传输协议如TCP、命名管线、HTTP、MSMQ等，WCF中针对这些协议的模式为net.tcp 、net.pipe、 http 、net.msmq。看下面例子：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;net.tcp://localhost:10000&lt;/li&gt;
&lt;li&gt;net.pipe://oec2003 [oec2003为机器名]&lt;/li&gt;
&lt;li&gt;http://localhost:10000&lt;/li&gt;
&lt;li&gt;net.msmq://localhost:10000&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;在ServerHost中加入多个端点时，需要为每个端点设置唯一的地址。&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="绑定"&gt;绑定&lt;/h2&gt;
&lt;p&gt;绑定描述了某一端点的协议支持。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP协议：BasicHttpBinding 、 WSHttpBinding 和WSFederationHttpBinding 。&lt;/li&gt;
&lt;li&gt;两个HTTP 通道实现双向通讯：WSDualHttpBinding。&lt;/li&gt;
&lt;li&gt;TCP协议：NetTcpBinding。&lt;/li&gt;
&lt;li&gt;P2P：NetPeerTcpBinding。&lt;/li&gt;
&lt;li&gt;命名管道：NamedPipeBinding。&lt;/li&gt;
&lt;li&gt;消息队列：NetMsmqBinding 和MsmqIntegrationBinding。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="元数据"&gt;元数据&lt;/h2&gt;
&lt;p&gt;这里元数据指的是服务中暴露的接口和服务端点的信息，客户依据这些元数据来生成代理调用服务。元数据可以通过两种方式被调用：1 ServiceHost可以公开一个元数据交换端点（IMetadataExchange）以便客户访问元数据；2 将元数据生成一个WSDL文档来描述端点和服务支持的协议。&lt;/p&gt;
&lt;h2 id="代理"&gt;代理&lt;/h2&gt;
&lt;p&gt;客户端是使用代理和服务通信。一个代理就是一个类型高开服务契约中的操作，客户调用时，对客户隐藏实现细节。客户端可以使用ChannelFactory或通过引用Web服务的方式来创建代理。&lt;/p&gt;
&lt;h2 id="通道"&gt;通道&lt;/h2&gt;
&lt;p&gt;通道是为了方便WCF中客户端和服务的通信而建立的。熟悉Remoting的朋友一定不会感到陌生。ServiceHost会为每一个端点创建一个通道侦听器，用来侦听客户端发送的消息。客户段和服务的两种信道必须相互兼容才能保持通信。&lt;/p&gt;
&lt;h2 id="行为"&gt;行为&lt;/h2&gt;
&lt;p&gt;行为会影响服务对消息的处理方式，当服务和端点确定了核心的通信需求以及和客户端之间共享了元数据后，当行为穿过信道栈时会改变消息的处理方式。行为可以在配置文件中进行配置。&lt;/p&gt;
&lt;p&gt;这些概念有的可能不太好理解，但在WCF的学习过程中会始终伴随着他们，也会随着我们不断的学习进而有较深入的理解。下面我就目前的理解对WCF的开发流程做个简单的总结：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;创建服务，这个通常是个类库项目，可以选择创建一个空的类库项目或是WCF Service Library。如果是创建的空的类库项目，则需要引用程序集System.ServeiceModel。&lt;/li&gt;
&lt;li&gt;在服务中创建服务契约和服务的操作，一般抽象为接口，ServiceContract和OperationContract标记定义在接口和接口中的方法上，然后创建类继承接口给出具体实现即可。&lt;/li&gt;
&lt;li&gt;服务需要寄存，必要要有宿主环境，可以根据需要自己选择任意一种，比如控制台程序。需要引用服务的程序集和System.ServeiceModel。然后就是配置端点和绑定。可以用程序的方式或是配置文件的方式。&lt;/li&gt;
&lt;li&gt;客户端可以是控制台程序、WinForm程序等。拿控制台程序来说吧，创建一个控制台程序，引用程序集System.ServeiceModel。在客户端可以使用ChannelFactory的方式或是通过添加服务引用的方式来创建代理。如果是使用ChannelFactory的方式创建代理，在客户端必须有服务契约的副本，可以将服务中的接口复制到客户端或是添加对服务的引用。创建代理时端点信息可以在程序中写也可以在配置文件中配置。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>WCF中的ServiceHost初始化两种方式</title><link>https://fwhyy.com/2010/07/wcf-servicehost-initialization-in-two-ways/</link><pubDate>Tue, 13 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/wcf-servicehost-initialization-in-two-ways/</guid><description>&lt;p&gt;在宿主程序中初始化ServiceHost有直接写代码和使用配置文件两种方式。使用ServiceHost首先要引用System.ServiceModel 命名空间。&lt;/p&gt;
&lt;h2 id="代码方式"&gt;代码方式&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;using(ServiceHost host=new ServiceHost(typeof(HelloWordService)))
{
 host.AddServiceEndpoint(typeof(IHelloWordService),
 new BasicHttpBinding(), new Uri(&amp;#34;http://localhost:10000/HelloWorldService&amp;#34;));
 host.AddServiceEndpoint(typeof(IHelloWordService),
 new NetTcpBinding(), new Uri(&amp;#34;net.tcp://localhost:10001/HelloWorldService&amp;#34;));

 if (host.State != CommunicationState.Opening)
 host.Open();
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="配置文件方式"&gt;配置文件方式&lt;/h2&gt;
&lt;p&gt;配置文件代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;services&amp;gt;
 &amp;lt;service behaviorConfiguration=&amp;#34;serverBehavior&amp;#34; name=&amp;#34;HelloWordService&amp;#34;&amp;gt;
 &amp;lt;endpoint address=&amp;#34;http://localhost:10000/HelloWorldService&amp;#34;
 binding=&amp;#34;basicHttpBinding&amp;#34; contract=&amp;#34;IHelloWordService&amp;#34;&amp;gt;&amp;lt;/endpoint&amp;gt;
 &amp;lt;endpoint address=&amp;#34;net.tcp://localhost:10001/HelloWorldService&amp;#34;
 binding=&amp;#34;netTcpBinding&amp;#34; contract=&amp;#34;IHelloWorldService&amp;#34;&amp;gt;&amp;lt;/endpoint&amp;gt;
 &amp;lt;/service&amp;gt;
&amp;lt;/services&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;当然也可以使用基地址的方式来配置&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;services&amp;gt;
 &amp;lt;service behaviorConfiguration=&amp;#34;serverBehavior&amp;#34; name=&amp;#34;HelloWordService&amp;#34;&amp;gt;
 &amp;lt;endpoint address=&amp;#34;HelloWorldService&amp;#34;
 binding=&amp;#34;basicHttpBinding&amp;#34; contract=&amp;#34;IHelloWordService&amp;#34;&amp;gt;&amp;lt;/endpoint&amp;gt;
 &amp;lt;endpoint address=&amp;#34;HelloWorldService&amp;#34;
 binding=&amp;#34;netTcpBinding&amp;#34; contract=&amp;#34;IHelloWorldService&amp;#34;&amp;gt;&amp;lt;/endpoint&amp;gt;
 &amp;lt;host&amp;gt;
 &amp;lt;baseAddresses&amp;gt;
 &amp;lt;add baseAddress=&amp;#34;http://localhost:10000/&amp;#34;/&amp;gt;
 &amp;lt;add baseAddress=&amp;#34;net.tcp://localhost:10001/&amp;#34;/&amp;gt;
 &amp;lt;/baseAddresses&amp;gt;
 &amp;lt;/host&amp;gt;
 &amp;lt;/service&amp;gt;
&amp;lt;/services&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;配置好配置文件后就宿主程序中就很简单了，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;using(ServiceHost host=new ServiceHost(typeof(HelloWordService)))
{
 if (host.State != CommunicationState.Opening)
 host.Open();
}
&lt;/code&gt;&lt;/pre&gt;</description></item></channel></rss>