昨天项目组开会需要分配一下具体的任务,热后组长分给我一个WCF服务的接口开发,说是内部调用。会上讨论了具体的业务逻辑,我忽然发现这个WCF服务需要在实现的代码中再调用另一个WCF服务。我的妈呀!没遇见过这样的啊!
好吧,想想不是不能够实现,但是还需要具体实贱一下,下面是实践的过程。
如果哪位大佬看见了,有好的解决方案可以指教一下。先谢过。
首先得有俩个WCF服务和寄宿分别是基于http协议的和netTcp协议的。当然协议无关紧要。
1、第一个服务程序正常写就可以。第一个宿主的配置文件(也是正常的)
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings >
<netTcpBinding >
<binding name="nettcp">
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="beh">
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:2305/"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="ConsoleApplication6.Program" behaviorConfiguration="beh">
<endpoint address="net.tcp://localhost:2303/ConsoleApplication6/Program" binding="netTcpBinding" bindingConfiguration="nettcp" contract="ConsoleApplication6.Interface1" />
<endpoint address="net.tcp://localhost:2303/ConsoleApplication6/Program/mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
</service>
</services>
<client />
</system.serviceModel>
</configuration>
2、接下来我们的第二个WCF服务的实现代码中要调用第一个WCF服务。
过程添加服务引用,在代码中实例化一个客户端类然后正常的调用方法如下代码
public class Service1 : IService1//实现契约接口
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
/// <summary>
/// 在此实现方法中调用第一个WCF服务
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
public bool get(int i)
{
WcfService1.ServiceReference1.Interface1Client client = new Interface1Client();//WCF服务的客户端实例
if (i == 1)
return client.get(3);//调用方法
else
return false;
}
}
配置文件也正常如下
<!-- 以下内容是在system.serviceModel节点中 -->
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_Interface1" />
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://localhost:2303/ConsoleApplication6/Program"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_Interface1"
contract="ServiceReference1.Interface1" name="NetTcpBinding_Interface1">
<identity>
<userPrincipalName value="DESKTOP-UO3BIJF\asus" />
</identity>
</endpoint>
</client>
3、然后写第二个wcf服务的寄宿程序,控制台程序,正常编写代码配置文件如下:
<system.serviceModel>
<bindings>
<!--<netTcpBinding>
<binding name="NetTcpBinding_Interface1" />
</netTcpBinding>-->
<wsHttpBinding>
<binding name="userNameCredentialBinding">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<!-- 注意: 服务名称必须与服务实现的配置名称相匹配。 --><!--行为配置属性是后面的行为中的配置-->
<service name="WcfService1.Service1" behaviorConfiguration="behaviorConfiguration" >
<endpoint address="http://localhost:5443/Service1" binding="wsHttpBinding" bindingConfiguration="userNameCredentialBinding"
contract="WcfService1.IService1"></endpoint>
</service>
</services>
<!--<client>
<endpoint address="net.tcp://localhost:2303/ConsoleApplication6/Program"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_Interface1"
contract="ServiceReference1.Interface1" name="NetTcpBinding_Interface1">
<identity>
<userPrincipalName value="DESKTOP-UO3BIJF\asus" />
</identity>
</endpoint>
</client>-->
<behaviors>
<!--服务的行为配置 -->
<serviceBehaviors>
<behavior name="behaviorConfiguration" >
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:5443/"/>
<!--以下可以忽略不是关键 -->
<serviceCredentials>
<serviceCertificate storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName" findValue="DESKTOP-UO3BIJF"/>
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="myProvider"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
4、按照我的逻辑这个应该是可以的,宿主成功启动。
5、编写调用第二个WCF服务的客户端,依然是正常的编写代码,添加服务引用,实例化服务客户端实例。调用服务完成,编译正常。
6、满心欢喜进行测试,结果
我返回去第二个WCF服务实现的配置文件中确认了好几遍,明明存在的?
好吧百度,没有(暂时没找到),仔细想了想,一个大胆的尝试。
不是第二个服务也寄宿了吗。那我在宿主中再添加一下第一个WCF服务引用,虽然宿主程序不使用代码。如下的配置文件,就是第3步文件中的注释解开。
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_Interface1" />
</netTcpBinding>
<wsHttpBinding>
<binding name="userNameCredentialBinding">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<!-- 注意: 服务名称必须与服务实现的配置名称相匹配。 --><!--行为配置属性是后面的行为中的配置-->
<service name="WcfService1.Service1" behaviorConfiguration="behaviorConfiguration" >
<endpoint address="http://localhost:5443/Service1" binding="wsHttpBinding" bindingConfiguration="userNameCredentialBinding"
contract="WcfService1.IService1"></endpoint>
</service>
</services>
<client>
<endpoint address="net.tcp://localhost:2303/ConsoleApplication6/Program"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_Interface1"
contract="ServiceReference1.Interface1" name="NetTcpBinding_Interface1">
<identity>
<userPrincipalName value="DESKTOP-UO3BIJF\asus" />
</identity>
</endpoint>
</client>
<behaviors>
<!--服务的行为配置 -->
<serviceBehaviors>
<behavior name="behaviorConfiguration" >
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:5443/"/>
<!--以下可以忽略不是关键 -->
<serviceCredentials>
<serviceCertificate storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName" findValue="DESKTOP-UO3BIJF"/>
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="myProvider"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
好了见证奇迹的时刻:居然居然成功了。
后记:想了想既然你在宿主程序中可以找到协定。那么在WCF服务实现类中的协定就不重要了吧,试一下,注释掉第2步的配置文件,确保程序编译不报错。
战战兢兢的运行,TMD居然也成功了。
结论:在第二个宿主中需要添加对第一个服务的引用。至于其中缘由我目前搞不懂,希望看到的大佬可以解释一下。谢过。