寄宿于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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did46729