对于WCF一直都是只知其然,公司框架的架构者也只是对我们授之以鱼,而不授之以渔。
带着初学者的态度进入了大神Artech的博客,逐步慢慢上手。
起步的项目很简单,就是照抄大神的功能,整个项目结构:
1,契约(Contracts)里面的WCF服务接口
public interface ICalculator { [OperationContract] double Add(double x, double y); [OperationContract] double Subtract(double x, double y); [OperationContract] double Multiply(double x, double y); [OperationContract] double Divide(double x, double y); }
2,WCF服务实现库Services,对契约的具体实现
public class CalculatorService : ICalculator { public double Add(double x, double y) { return x + y; } public double Subtract(double x, double y) { return x - y; } public double Multiply(double x, double y) { return x * y; } public double Divide(double x, double y) { return x / y; } }
3,宿主项目中对于服务的配置(在控制台程序中新建app.config配置文件进行配置)
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="metadataBehavior"> <serviceMetadata httpGetEnabled="true" /> </behavior> </serviceBehaviors> </behaviors> <services> <service behaviorConfiguration="metadataBehavior" name="CalculatorService"> <endpoint binding="wsHttpBinding" contract="Contracts.ICalculator" /> <endpoint binding="netTcpBinding" contract="Contracts.ICalculator" /> <host> <baseAddresses> <add baseAddress="http://localhost:9527/calculatorservice/ser" /> <add baseAddress="net.tcp://localhost:9528/calculatorservice/ser" /> </baseAddresses> </host> </service> </services> </system.serviceModel>
4,控制台进行寄宿
using (ServiceHost host = new ServiceHost(typeof(CalculatorService))) { host.Opened += delegate { Console.WriteLine("CalculaorService已经启动,按任意键终止服务!"); }; host.Open(); Console.Read(); }
然后开始了旅程…
Error:【服务“Services.CalculatorService”有零个应用程序(非基础结构)终结点。这可能是因为未找到应用程序的配置文件,或者在配置文件中未找到与服务名称匹配的服务元素,或者服务元素中未定义终结点。】
上述错误困扰了我近一个小时,到处找资料Google与百度都瞅遍了,什么样答案都能找到!对我就是木有用。
折腾了许久后,去泡了杯茶,回来后竟然就… 原来折腾我老久的问题是我自己给弄出来的。
在将服务给提供服务的主机 ServiceHost 时CalculatorService是引入了命名空间的,然而在配置文件中进行服务名称配置时确实这样的:
<service behaviorConfiguration="metadataBehavior" name="CalculatorService">
当给服务名称 加上命名空间后 就一切正常了
<service behaviorConfiguration="metadataBehavior" name="Services.CalculatorService">
顿时 ………
Error:【响应消息的内容类型 text/html; charset=utf-8 与绑定(text/xml; charset=utf-8)的内容类型不匹配。】
这个错误也折腾了我许久。错误是说内容类型不匹配,网上说要新建一个绑定
<bindings> <basicHttpBinding> <binding name="defaultHttpBinding" /> </basicHttpBinding> </bindings>
让后在终结点绑定bindingConfiguration
<endpoint address="http://localhost:9527/calculatorservice/ser" binding="basicHttpBinding" bindingConfiguration="defaultHttpBinding" contract="Contracts.ICalculator" name="hostEndpoint_http" />
照着试了下,完全没有效果,进入反思再反思,想着肯定是不是配置的问题,然后一遍遍检查,破绽便出现了(也怪自己不够细心)
在寄宿控制台的配置文件中绑定的是wsHttpBinding:
<endpoint binding="wsHttpBinding" contract="Contracts.ICalculator" />
而在客服端(Clients)配置文件中绑定的却是basicHttpBinding---->
<basicHttpBinding> <binding name="defaultHttpBinding" /> </basicHttpBinding>
解决方案是将客服端(Clients)配置文件改成wsHttpBinding:
<wsHttpBinding> <binding name="defaultHttpBinding" /> </wsHttpBinding>
最后客服端配置文件中的客服端配置为:
<system.serviceModel> <bindings> <netTcpBinding> <binding name="defaultTcpBinding" /> </netTcpBinding> <wsHttpBinding> <binding name="defaultHttpBinding" /> </wsHttpBinding> </bindings> <client> <endpoint address="http://localhost:9527/calculatorservice/ser" binding="wsHttpBinding" bindingConfiguration="defaultHttpBinding" contract="Contracts.ICalculator" name="hostEndpoint_http" /> <endpoint address="net.tcp://localhost:9528/calculatorservice/ser" binding="netTcpBinding" bindingConfiguration="defaultTcpBinding" contract="Contracts.ICalculator" name="hostEndpoint_tcp" /> </client> </system.serviceModel>
一切准备就绪,接下来开始建立WCF 通信将这些通道将消息发送到不同配置的服务终结点。
var channel = new ChannelFactory<ICalculator>("hostEndpoint_http").CreateChannel(); var d = channel.Add(1.2, 2.5);
OK ,完事。