在使用WCF服务时,通常都是用svcutil生成代理类和配置,用生成的默认配置就可以调用服务。先来看看生成的默认的配置内容:
View Code
<
client
>
< endpoint address ="http://localhost:8732/ConfigNameService/Service1/"
binding ="wsHttpBinding" bindingConfiguration ="WSHttpBinding_IService1"
contract ="IService1" name ="WSHttpBinding_IService1" >
< identity >
< dns value ="localhost" />
</ identity >
</ endpoint >
</ client >
< endpoint address ="http://localhost:8732/ConfigNameService/Service1/"
binding ="wsHttpBinding" bindingConfiguration ="WSHttpBinding_IService1"
contract ="IService1" name ="WSHttpBinding_IService1" >
< identity >
< dns value ="localhost" />
</ identity >
</ endpoint >
</ client >
其中contract就是代理类中指向接口或契约类,假如contract的定义如下,那么默认情况下是contract接口的名字
View Code
1 [System.ServiceModel.ServiceContract]
2 public interface IService1
3 {
4 }
2 public interface IService1
3 {
4 }
但实际上存在多个服务或者需要用命名空间去标记contract时,需要修改客户端配置中endpoint的中contract的名字,需要其包含命名空间,比如改成如下:
contract="ConfigNameService.IService1"。
按通常的理解,以为系统会按照类型名称去找代理类中的接口,但实际上并非这样,仅仅在执行以下代码时就会提示找不到默认终结点的错误。
View Code
1
using (
var client =
new Service1Client())
2 {
3 Console.WriteLine(client.GetData( 1));
4 }
2 {
3 Console.WriteLine(client.GetData( 1));
4 }
而将contract的值改回"IService1"即可正常调用。
原因是代理类中的contract定义时设置的ConfigurationName决定了配置时需要配置的值,这个属性很容易被忽视,尤其是通过svcutil生成的代理类,比如以下代码:
View Code
1 [System.ServiceModel.ServiceContractAttribute(ConfigurationName=
"
IService1
")]
2 public interface IService1
3 {
4
5 [System.ServiceModel.OperationContractAttribute(Action= " http://tempuri.org/IService1/GetData ", ReplyAction= " http://tempuri.org/IService1/GetDataResponse ")]
6 string GetData( int value);
7
8 [System.ServiceModel.OperationContractAttribute(Action= " http://tempuri.org/IService1/GetDataUsingDataContract ", ReplyAction= " http://tempuri.org/IService1/GetDataUsingDataContractResponse ")]
9 ConfigNameService.CompositeType GetDataUsingDataContract(ConfigNameService.CompositeType composite);
10 }
2 public interface IService1
3 {
4
5 [System.ServiceModel.OperationContractAttribute(Action= " http://tempuri.org/IService1/GetData ", ReplyAction= " http://tempuri.org/IService1/GetDataResponse ")]
6 string GetData( int value);
7
8 [System.ServiceModel.OperationContractAttribute(Action= " http://tempuri.org/IService1/GetDataUsingDataContract ", ReplyAction= " http://tempuri.org/IService1/GetDataUsingDataContractResponse ")]
9 ConfigNameService.CompositeType GetDataUsingDataContract(ConfigNameService.CompositeType composite);
10 }
ConfigurationName就是原服务接口的名字,因此需要手动修改ConfigurationName为需要的值,这里只能改客户代理类中的接口定义的ConfigurationName。然后在配置endpoint时的contract的值跟ConfigurationName的值保持一致即可。