WCF配置文件与文件下载之坎坷路

题外话:本以为我会WCF了,精通WCF了,毕竟刚做过一个WCF的项目,不就是写写契约接口,然后实现接口,改下配置。最后用控制台或者服务发布一下,不就能用了。不就是简单ABC吗?不是So Easy吗?做第二个项目的时候我悲剧了,被碰的头破血流!忽然发现什么什么都不会(第一个项目比照网上教程一步一步弄的),连写一个简单hello world都写不出来。我之前还以为自己很懂了……

一、WCF文件配置

      为了不重蹈覆辙,这次争取把他整懂整透(当然这才是入门而已)。WCF很强大,它的强大跟它的配置有很大的关系,所以我首先要先把它的配置搞懂。

     WCF的配置文件共分为两部分:服务端配置与客户端配置。两者由于功能的不同,在配置文件的使用上也略有不同。

WCF的服务端配置

服务端的配置文件主要包括endpoint、binding、behavior的配置。一个标准的服务端配置文件所包含的主要xml配置节如下所示:

 

<system.ServiceModel>

   <services>
      <service>
         <endpoint/>
      </service>
   </services>

   <bindings>
   <!—定义一个或多个系统提供的binding元素,例如<basicHttpBinding> -->
   <!—也可以是自定义的binding元素,如<customBinding>. -->
      <binding>
      <!—例如<BasicHttpBinding>元素. -->
      </binding>
   </bindings>

   <behaviors>
   <!—一个或多个系统提供的behavior元素. -->
      <behavior>
      <!—例如<throttling>元素. -->
      </behavior>
   </behaviors>

</system.ServiceModel>

1.1 <services>配置节
在<services>配置节中可以定义多个服务,每一个服务都被放到<service>配置节中,WCF的宿主程序可以通过配置文件找到这些定义的服务并发布这些服务。

<service>配置节包含name和behaviorConfiguration属性。其中,name配置了实现Service Contract的类型名。类型名必须是完整地包含了命名空间和类型名。而behaviorConfiguration的配置值则与其后的<behaviors>配置节的内容有关。<endpoint>是<service>配置节的主体,其中,<endpoint>配置节包含了endpoint的三个组成部分:Address、Binding和Contract。由于具体的binding配置是在<bindings>配置节中完成,因而,在<endpoint>中配置了bindingConfiguration属性,指向具体的binding配置。如下所示:

<services>
  <service name="MyService.Service1" behaviorConfiguration="MyBehavior">
    <endpoint address=""
             binding="netTcpBinding"
             bindingConfiguration="DuplexBinding"
             contract="MyService.IHello" />
  </service>
</services> 

我们也可以定义多个endpoint,例如:

<services>
  <service
      name="Microsoft.ServiceModel.Samples.CalculatorService"
      behaviorConfiguration="CalculatorServiceBehavior">
    <endpoint address=""
             binding="wsHttpBinding"
             contract="Microsoft.ServiceModel.Samples.ICalculator" />
    <endpoint address="mex"
             binding="mexHttpBinding"
             contract=" Microsoft.ServiceModel.Samples.IMetadataExchange" />
  </service>
</services> 

      如果address值为空,那么endpoint的地址就是默认的基地址(Base Address)。例如ICalculator服务的地址就是http://localhost/servicemodelsamples/service.svc,而IMetadataExchange服务的地址则为http://localhost/servicemodelsamples/service.svc/mex。这里所谓的基地址可以在

<service>中通过配置<host>来定义:

<service
      name="Microsoft.ServiceModel.Samples.CalculatorService"
      behaviorConfiguration="CalculatorServiceBehavior">
<host>
    <baseAddresses>
        <add baseAddress="http://127.0.0.1/ServiceModelSamples”/>
    </baseAddresses>
</host>
<endpoint … />
</service> 

1.2 <behaviors>配置节
    当我们在定义一个实现了Service Contract的类时, binding和address信息是客户端必须知道的,否则无法调用该服务。然而,如果需要指定服务在执行方面的相关特性时,就必须定义服务的behavior。在WCF中,定义behavior就可以设置服务的运行时属性,甚至于通过自定义behavior插入一些自定义类型。例如通过指定ServiceMetadataBehavior,可以使WCF服务对外公布Metadata。配置如下:

<behaviors>
    <serviceBehaviors>
    <behavior name="metadataSupport">
      <serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
    </behavior>
    <serviceBehaviors>
<behaviors> 

在WCF中,behavior被定义为Attribute,其中,System.ServiceModel.ServiceBehaviorAttribute和System.ServiceModel.OperationBehaviorAttribute是最常用的behavior。虽然,behavior作为Attribute可以通过编程的方式直接施加到服务上,但出于灵活性的考虑,将behavior定义到配置文件中才是最好的设计方式。
利用ServiceBehavior与OperationBehavior可以控制服务的如下属性:

1、 对象实例的生命周期;

2、 并发与异步处理;

3、 配置行为;

4、 事务行为;

5、 序列化行为;

6、 元数据转换;

7、 会话的生命周期;

8、 地址过滤以及消息头的处理;

9、 模拟(Impersonation);

例如,通过ServiceBehavior设置对象实例的生命周期:

<behaviors>
    <serviceBehaviors>
    <behavior name="metadataSupport">
      <instanceContextMode httpGetEnabled="true" httpGetUrl=""/>
    </behavior>
    <serviceBehaviors>
<behaviors>

这是通过使用配置文件指定的地址

另外我们还可以通过代码的方式指定地址:代码如下

   private static void Main(string[] args)
        {
            using (ServiceHost serviceHost = new ServiceHost(typeof (Service1)))
            {
                serviceHost.AddServiceEndpoint(typeof (IService1), new WSHttpBinding(),
                    "http://127.0.0.1:9999/Service1");
                serviceHost.AddServiceEndpoint(typeof (IService1), new NetTcpBinding()
                    , "net.tcp://127.0.0.1:8888/Service1");
                serviceHost.Opened += (s, e) => Console.WriteLine("服务已打开!");
                serviceHost.Open();
                Console.Read();
            }
        }

这里调用了ServiceHost 类的AddServiceEndpoint方法:它的抽象方法为

public ServiceEndPoint AddServiceEndpoint(Type implementedContract,Binding binding,string  address);

当然你还可以使用ServiceHost 继承自ServiceHostBase的方法AddServiceEndpoint:它的方法签名为:

public ServiceEndPoint AddServiceEndpoint(string implementedContract,Binding binding,string  address);

这里只是将implementedContract以字符串的形式表示服务契约类型的有效名称。

上面添加终结地就变成了

serviceHost.AddServiceEndpoint(“命名空间.IService1”,new WSHttpBinding(),http://127.0.0.1:9999/Service1);

基地址与相对地址

     除了向上面那样以绝对路径的方式指定服务的终结点地址外,还可以通过“基地址+相对地址”的方式进行设置。对于一个服务来说,可以指定一个或多个基地址,但是对于一种传输方式协议类型,只能具有一个唯一的基地址。服务的基地址与终结点相对地址可以通过编码的方式,在创建ServiceHost对象时在构造函数中指定。具体实现代码如下:

    internal class Program
    {
        private static void Main(string[] args)
        {
            Uri[] baseAddress =
            {
              new Uri("http://127.0.0.1:8888/myservices"),
              new Uri("net.tcp://127.0.0.1/:8888")
            };

            using (ServiceHost serviceHost = new ServiceHost(typeof (Service1),baseAddress))
            {
                serviceHost.AddServiceEndpoint(
                    typeof (IService1),
                    new BasicHttpBinding(),
                    "Service1");
                serviceHost.AddServiceEndpoint(
                    typeof (IService1),
                    new NetTcpBinding(),
                     "Service1");
                serviceHost.Opened += (s, e) => Console.WriteLine("服务已打开!");
                serviceHost.Open();
                Console.Read();
            }
        }
    }

          上面的代码中,在寄宿Service1服务的时候,添加了两个基地址,一个是基于HTTP的,另外一个是基于net.tcp的。然后为Service1添加了两个终结地,基于HTTP的BasicHttpBinding和基于TCP的NetTcpBinding。添加的两个终结点均采用相对地址Service1。

          由于AddServiceEndpoint指定的是相对地址,所以WCF会根据绑定采用的传输协议在ServiceHost的基地址列表中寻找与之匹配的基地址,相对地址与基地址组合确定终结点的绝对地址。(完整地址为:http://127.0.0.1:9999/myservices/Service1).

         由于基地址与相对地址的匹配关系是根据绑定对象采用的传输协议确定的,所以对于一个确定的传输协议,最多只能有一个基地址。如果在上面的基地址中再加一个HTTP的基地址,那程序就会抛出异常。

如果采用上面配置文件的方式:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <compilation debug="true" />
  </system.web>
  <!-- 部署服务库项目时,必须将配置文件的内容添加到
  主机的 app.config 文件中。System.Configuration 不支持库的配置文件。-->
  <system.serviceModel>
    <services>
      <service name="ConsoleApplication1.Service1">
        <host>
          <baseAddresses>
            <add baseAddress = "http://127.0.0.1:9999/myservice" />
              <add baseAddress="net.tcp://127.0.0.1:9999/myservice"/>
          </baseAddresses>
        </host>
        <!-- Service Endpoints -->
        <!-- 除非完全限定,否则地址将与上面提供的基址相关 -->
        <endpoint address ="Service1"
                  binding="basicHttpBinding"
                  contract="ConsoleApplication1.IService1"
                  bindingConfiguration="HttpStreaming">
        </endpoint>
          <endpoint address="Service1"
                    binding="netTcpBinding"
                    contract="ConsoleApplication1.IService1"
                    bindingConfiguration="netTcpBindingConfiguration"/>
        <!-- Metadata Endpoints -->
        <!-- 元数据交换终结点供相应的服务用于向客户端做自我介绍。 -->
        <!-- 此终结点不使用安全绑定,应在部署前确保其安全或将其删除-->
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- 为避免泄漏元数据信息,
          请在部署前将以下值设置为 false 并删除上面的元数据终结点  -->
          <serviceMetadata httpGetEnabled="false"/>
          <!-- 要接收故障异常详细信息以进行调试,
          请将以下值设置为 true。在部署前设置为 false
            以避免泄漏异常信息-->
          <serviceDebug includeExceptionDetailInFaults="False" />
            <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
      <bindings>
          <basicHttpBinding>
              <binding name="HttpStreaming" maxReceivedMessageSize="67108864" transferMode="Streamed"/>
          </basicHttpBinding>
          <netTcpBinding>
              <binding name="netTcpBindingConfiguration"
                       closeTimeout="00:01:00"
                       openTimeout="00:01:00"
                       receiveTimeout="00:10:00"
                       sendTimeout="00:10:00"
                       transactionFlow="false"
                       transferMode="Buffered"
                       transactionProtocol="OleTransactions"
                       hostNameComparisonMode="StrongWildcard"
                       listenBacklog="10"
                       maxBufferPoolSize="2147483647 "
                       maxBufferSize="2147483647 "
                       maxConnections="10"
                       maxReceivedMessageSize="2147483647 ">
                  <readerQuotas maxDepth="64" maxStringContentLength="2147483647 " maxArrayLength="2147483647 " maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                  <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
                  <security mode="Transport">
                      <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
                  </security>
              </binding>
          </netTcpBinding>
      </bindings>
  </system.serviceModel>

</configuration>

 

注:如果采用代码和配置的方式,两者都会生效,所以必须确保两者的设置的内容不会相互冲突。

这是服务端的配置,真的搞明白了,确实还挺有意思的。不过在调试过程中出现了错误

在服务“Service1”实现的协定列表中找不到协定名称,这个问题费我半天时间,

出错的原因有两个:

1. 看契约是否写对, 这个一般不会写错

2.看配置文件:service name="命名空间名+服务名称"    endpoint contract="命名空间名+契约名称"

(这里有个小细节要注意, ""中不能出现空格,否则依然报错)

     我出的问题原因是第二种,命名空间名前多了空格。费了半天劲原来是自己的粗心大意,唉,真想把自己杀了……

    在编写配置中当然还出现了各种各样无法八门的问题,都是因为配置没有写对的原因,这也给我一个教训,编写代码一定不能粗心大意,不然都是血的代价……

    下面是本文的重点了,文件的下载。

二、WCF文件的下载

  其实WCF下载也没有什么可说的,就是写个返回Steam的接口就行了,关键就是写好配置文件就行了

(待续……)

 

时间: 2024-09-20 06:07:21

WCF配置文件与文件下载之坎坷路的相关文章

[WCF]配置文件中Certificate 的encodeValue怎么设置?

在WCF配置文件中经常会出现这样的属性:   <identity> <certificate encodedValue="large string!!!!!!!" /> </identity>     那么这其中的encodedValue如何设置?   1.把cer文件(证书)导出为base64格式 a,使用mmc找到需要的证书  -- (Add Snap-In) b,右击证书  导出    c,base64 encoded x509(.cer) 2

光伏产业融资坎坷路 仍待政策推动

光伏融资坎坷路 要解决光伏产业融资难的问题,一方面要整合国内外金融机构,搭建投融资对接和信息交流平台:另一方面需要推动光伏产业行业模式和融资模式的创新,提升投融资行业服务水平和对接效率,推广适合我国光伏发电应用的投融资产品. 11月7日,国家发改委.国家能源局召开新闻发布会,对外正式发布<电力发展"十三五"规划>(以下简称<规划>),其中对分布式光伏提出明确目标.<规划>要求,到2020年,太阳能发电装机达到110GW(GW为十亿瓦特发电装机容量)以

CNNIC十年磨一剑:“.中国”域名的坎坷路

中介交易 SEO诊断 淘宝客 云主机 技术大厅 2009年10月30日,韩国首尔,当地时间11点40分(北京时间10点40分),第36届ICANN(互联网名称与数字地址分配机构)年会正在紧张进行-- 作为近年来最大规模的一次ICANN会议,1000多名国际互联网界知名人士参与其中.尽管他们有着不同的肤色.操持不同语言,但大多数人都为了见证被誉为"互联网40年里程碑事件"--".中国"等非英文国家顶级域名后缀快速通道实施计划的命运.一旦通过,则意味着全球超过20个国家

WCF配置文件全攻略

当今的软件系统开发,如果没有配置文件几乎是不可想象的事.没有配置文件,软件如何按照用户的要求对功能进行定制?没有配置文件,在对软件进行配置安装的时候如何根据具体的硬软件环境进行修改?最重要的是没有配置文件,该如何应对软件系统的可扩展要求?不知不觉地,配置文件的编写与管理竟然成了软件开发的重中之重. WCF作为分布式开发的基础框架,在定义服务以及定义消费服务的客户端时,都使用了配置文件的方法.虽然WCF也提供硬编程的方式,通过在代码中直接设置相关对象的属性来完成服务端与客户端的配置,然而这种方式并

WCF系列(三) WCF配置文件注释

<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.ServiceModel> <!-- services 元素包含应用中驻留的所有service的配置要求 --> <services> <!-- 每个服务的配置 属性说明: name - 指定这个service配置是针对的那个服务,为一个实现了某些Contract的服务类的完

WCF配置文件详解

原文地址:http://www.cnblogs.com/weichuo/archive/2008/07/09/1238979.html <?xml version="1.0" encoding="utf-8" ?> <configuration> <!-- <system.ServiceModel> section --> <system.ServiceModel> <!-- services 元素包

.xxx顶级域名获批坎坷路

&http://www.aliyun.com/zixun/aggregation/37954.html">nbsp;    早在2005年,.XXX域名就获得了内部认可,但因为呼吁色情控制的团体抗议而暂时搁浅.ICANN 表示担心该域名可能会被命令来遭到内容管制--这并不是它本应承担的角色.2010年2月,有美国的法官团体指出ICANN不应该无故拖延域名审批过程.ICANN于是启动了关于此域名是否可以通过的公众咨询.在2011年早些时候上线,大约有11万个.XXX域名被预先保留.

靠150元起家,网上卖起情侣装,80后的坎坷路

刘迅说,在网上卖服装除了要把握好服装的款式.面料.色彩.流行因素外,图片也很重要 150元起家,在网上卖情侣装和亲子装,年产值能达到上千万元,你相信吗?綦江区青年镇的刘迅做到了.目前,他已经拥有近9000平方米的专业厂房.4000家代销商和上百号工人,创业6年来累计销售的情感服饰达到了上百万件.下一步,他准备把自己的线上销售渠道向线下拓展,发展"网络+实体"的销售模式,把自己一手创造的"柏鹭"打造成为全国知名的情感服饰品牌. 靠150元起家 网上卖起情侣装 刘迅生长

万达电商坎坷路,不想重复以前经验

万达已经做了两年电商,现在,又说要做个新的了. 公众目光总是紧跟B.A.T.很难说这是出于好奇,还是出于习惯. 8月29日,百度董事长兼首席执行官李彦宏,和腾讯董事会主席兼首席执行官马化腾,同时出现在新闻发布会上,这还是第一次. 特别之处还在于,这并不是一场互联网公司的活动,万达集团董事长王健林站在他们中间,不时地左右交谈. 万达.百度.腾讯三方合作的消息已盛传两天,一家名为万达电子商务的合资公司就此宣布成立.在50亿元的首期投资中,万达持股70%,百度.腾讯各持有15%的股权,未来5年将追加投