好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

寄宿于CS程序的WCF服务

寄宿于CS程序的WCF服务

寄宿于CS程序的WCF服务

最近项目中,需要对外部程序提供服务接口,用来进行数据交互和部分设备控制。由于都是使用的.NET平台开发的,因此想到使用WCF服务。之前也用过WCF服务,但是当初使用的时候是通过IIS寄宿的,有些地方不太让人满意,一则是同一个软件要部署两个地方,CS的桌面程序和寄宿于IIS的WCF服务部分,二则是由于系统本身问题,使用的是SQLite数据库,无法实现多线程访问,造成了数据重复,容易造成数据不一致。所以现在准备把WCF服务寄宿于CS程序中,这样就解决了以上两个问题。

由于对WCF一知半解,只知道按部就班的使用,从明白过其中的道理,所以在网上找了些 教程 [1] ,实现了自己的想法,但其中碰到不少问题,想来还是记下,或许以后还有用处。

本文使用一个最简单的控制台应用程序,同时通过使用WcfTestClient.exe测试,来完成这个示例。

一、在代码中实现并配置WCF服务。

在VS2012中创建一个控制台应用程序项目CsWcf,并添加接口ICalculator作为契约接口、类CalculatorService作为服务实现此接口中的操作方法,代码如下:

1 . ICalculator.cs--服务契约

    1:   using  System;
    2:   using  System.Collections.Generic;
    3:   using  System.Linq;
    4:   using  System.Text;
    5:   using  System.ServiceModel;
    6:   
    7:   namespace  CsWcf
    8:  {
    9:      [ServiceContract]
   10:       public   interface  ICalculator
   11:      {
   12:          [OperationContract]
   13:           double  Add( double  x,  double  y);
   14:      }
   15:  }

2 . CalculatorService.cs--服务实现

    1:   using  System;
    2:   using  System.Collections.Generic;
    3:   using  System.Linq;
    4:   using  System.Text;
    5:   using  System.ServiceModel;
    6:   
    7:   namespace  CsWcf
    8:  {
    9:       public   class  CalculatorService:ICalculator
   10:      {
   11:           public   double  Add( double  x,  double  y)
   12:          {
   13:               return  x + y;
   14:          }
   15:      }
   16:  }

3 . 在Program.cs中的 Main 函数中,添加如下代码,实现WCF服务的寄宿,并开启服务。

    1:   using  (ServiceHost host =  new  ServiceHost( typeof (CalculatorService)))
    2:  {
    3:      host.AddServiceEndpoint( typeof (ICalculator),  new  WSHttpBinding(),  "http://192.168.1.102:10002/CalculatorService" );
    4:   
    5:       if  (host.Description.Behaviors.Find<ServiceMetadataBehavior>() ==  null )
    6:      {
    7:          ServiceMetadataBehavior behavior =  new  ServiceMetadataBehavior();
    8:          behavior.HttpGetEnabled =  true ;
    9:          behavior.HttpGetUrl =  new  Uri( "http://192.168.1.102:10002/CalculatorService" );
   10:          host.Description.Behaviors.Add(behavior);
   11:      }
   12:   
   13:      host.Opened +=  delegate 
   14:      {
   15:          Console.WriteLine( "CalculaorService已经启动,按任意键终止服务!" );
   16:      };
   17:   
   18:      host.Open();
   19:      Console.Read();
   20:  }

4 . F5调试执行,服务开启后,打开WcfTestClient,添加服务地址,可以正确调用Add服务函数。

但是,以上将服务相关配置写到代码中了,这不利于后面的安装和部署。所以需要将配置信息放置在config配置文件中。

二,使用配置文件动态配置WCF服务 。

配置app.config文件,实现WCF服务的可配置性。在项目中添加应用程序配置文件,并添加以下内容:

    1:  <system.serviceModel>
    2:    <behaviors>
    3:      <serviceBehaviors>
    4:        <behavior name= "metadataBehavior" >
    5:          <serviceMetadata httpGetEnabled= "true"  httpGetUrl= "http://192.168.1.102:10002/CalculatorService/metadata"  />
    6:        </behavior>
    7:      </serviceBehaviors>
    8:    </behaviors>
    9:    <services>
   10:      <service behaviorConfiguration= "metadataBehavior"  name= "CsWcf.CalculatorService" >
   11:        <endpoint address= "http://192.168.1.102:10002/calculatorservice"  binding= "wsHttpBinding"  
   12:                  contract= "CsWcf.ICalculator"   />
   13:        <endpoint address= "http://192.168.1.102:10002/calculatorservice/MEX/"  binding= "mexHttpBinding"  
   14:                    contract= "IMetadataExchange"   />
   15:      </service>
   16:    </services>
   17:  </system.serviceModel>

同时需要删除Program.cs中的配置代码:

    1:   using  (ServiceHost host =  new  ServiceHost( typeof (CalculatorService)))
    2:  {
    3:      host.Opened +=  delegate 
    4:      {
    5:          Console.WriteLine( "CalculaorService已经启动,按任意键终止服务!" );
    6:      };
    7:   
    8:      host.Open();
    9:      Console.Read();
   10:  }

F5调试执行,与刚刚的执行结果一样!此处要特别注意:配置节中的第二个endpoint,即MEX配置,一定要加上,否则会出现如下错误:

错误: 无法从  http://192.168.1.102:10002/CalculatorService  获取元数据如果是您有权访问的 Windows (R) Communication Foundation 服务,请检查是否已启用在指定地址发布元数据。有关启用元数据发布的帮助,请参阅  http://go.microsoft.com/fwlink/?LinkId=65455  上的 MSDN 文档。WS-Metadata Exchange 错误 URI:  http://192.168.1.102:10002/CalculatorService  元数据包含无法解析的引用:“ http://192.168.1.102:10002/CalculatorService”。  Sendera:BadContextToken无法处理消息。这很可能是因为操作“ http://schemas.xmlsoap.org/ws/2004/09/transfer/Get”不正确,或因为消息包含无效或过期的安全上下文令牌,或因为绑定之间出现不匹配。如果由于未处于活动状态导致服务中止了该通道,则安全上下文令牌无效。若要防止服务永久中止闲置会话,请增加服务终结点绑定上的接收超时。HTTP  GET Error URI:  http://192.168.1.102:10002/CalculatorService  下载“ http://192.168.1.102:10002/CalculatorService”时出错。  请求因 HTTP 状态 400 失败: Bad Request。

我在Artech的文章 [1] 中学习中并没有看到第二个终结点的配置,所以运行的时候一直出错,找了好久才找到这个解决办法,可以参考“WCF Part 4 : Make your service visible through metadata”这篇文章 [2] 。

三、其它机器访问权限限制的解决办法

以上两步骤,我们完成了WCF服务的寄宿、发布和访问,但是如果在其它计算机上访问此WCF服务时,会发现权限提示:

无法满足对安全令牌的请求,因为身份验证失败!

这个时候,默认的安全是计算机名和用户名做为权限要求。如果想让其他用户也可以随时访问到些WCF服务,就需要修改配置文件中的安全级别,设置<security>的mode为None就可以了。同时更改一个endpoint的bindingConfiguration="wsHttpBindingConfiguration"。

    1:  <bindings>
    2:    <wsHttpBinding>
    3:      <binding name= "wsHttpBindingConfiguration"  maxReceivedMessageSize= "20971510" >
    4:        <readerQuotas maxStringContentLength= "20971520"  maxArrayLength= "20971520" />
    5:        <security mode= "None" />
    6:      </binding>
    7:    </wsHttpBinding>
    8:  </bindings>

再次运行此服务,其它计算机上也可以访问此服务了。

总结 :WCF用起来简单,“制作”起来貌似也很简单,和写其它的代码基本无异,但是真正使用起来的时候,却又经常碰到这样那样的问题,个人感觉WCF是一个极其精密的仪器,操作简单,但是仪器的操作步骤和顺序却比较麻烦,而且零部件不牢固,经常脱落损坏,所以要想更好的使用它,需要对它有个很好的了解才是。由于现在网络的存在,好多东西都是用的时候搜索一下,基本没有系统、深入的学习过,这对以后的学习和工作经验的积累都用处不太大。

[1]  Artech, 我的WCF之旅(1):创建一个简单的WCF程序

[2]  Dennis van der Stelt, WCF Part 4 : Make your service visible through metadata

---------------------------------------------

作者:Ritchie( 乞戈 ) 
出处: http://RitchieChen.cnblogs.com/  
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

 

分类:  WCF学习

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于寄宿于CS程序的WCF服务的详细内容...

  阅读:45次