一,新建WCF服务引用程序
1,删除.svc文件,全部删除。
2,新建 IService 类
namespace TestWcf { [ServiceContract] public interface IService { [OperationContract] string DoWork(); } }
3,实现接口类 Service类
namespace TestWcf { public class Service : IService { public string DoWork() { return "你妹!"; } } }
4,编写配置文件
<system.serviceModel> <!--添加此节点,否则出现405错误--> <bindings> <wsHttpBinding> <binding name="NoneSecurity" maxBufferPoolSize="12000000" maxReceivedMessageSize="12000000" useDefaultWebProxy="false"> <readerQuotas maxStringContentLength="12000000" maxArrayLength="12000000"/> <security mode="None"/> </binding> </wsHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="metadataBehavior"> <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false --> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/> <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 --> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> <protocolMapping> <add binding="wsHttpBinding" scheme="http" /> </protocolMapping> <services> <service name="TestWcf.Service" behaviorConfiguration="metadataBehavior"> <endpoint address="" binding="wsHttpBinding" contract="TestWcf.IService" bindingConfiguration="NoneSecurity"> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> <!--无svc文件wcf服务激活--> <serviceHostingEnvironment> <serviceActivations> <add relativeAddress="Service.svc" service="TestWcf.Service"/> </serviceActivations> </serviceHostingEnvironment> </system.serviceModel>
5,注意事项
以下代码是无.svc,激活WCF服务的关键,WCF4.0的新特性
从消息交换的角度来说,客户端对IIS/WAS寄宿下服务的调用本质上体现在对.svc这个真实存在的物理文件的访问。如果服务尚未激活,WCF最终根据读取请求的物理文件来激活相应的服务。具体来说,就是获 取用于创建ServiceHost的ServiceHostFactory的类型(如果没有通过<%@ServiceHost%>指令的 Factory进行显式设置,默认使用的ServiceHostFactory的类型为 System.ServiceModel.Activation.ServiceHostFactory)。在正确解析出 ServiceHostFactory类型之后,通过反射创建用于寄宿服务的ServiceHost对象。
如果WCF的服务端能够根据请求正确地创建出基于目标服务的ServiceHost,就能解决服务的激活问题。进一步来说,如果服务端能够维护一个 Service/ServiceHostFactory与请求地址之间的映射关系,我们就可以不再需要.svc文件,因为.svc对于服务激活来说就是起 到了这么一个映射的作用。在最新的WCF中,这么一个映射关系可以在配置文件中进行设置。换言之,如果在配置对这个映射关系进行了相应设置之后,我们将不 再需要为服务定义了.svc文件了。
在<system.serviceModel>/<serviceHostingEnvironment>配置节下,具有 一个<serviceActivations>子节点。上述的关于Service/ServiceHostFactory与请求地址之间的映 射关系就定义在这个配置节点下。具体来说,<serviceActivations>配置节下的配置元素具有三个基本的属性,其中 service和factory对用着原来定义在.svc文件中<%@ServiceHost>指令的Service和Factory属性, 而relativeAddress则表示服务相对服务寄宿的IIS站点的地址,该地址必须以.svc为后缀。下面一段配置与上面给出的.svc文件具有相 同的作用,有了这段配置,.svc就不再需要了。
<!--无svc文件wcf服务激活--> <serviceHostingEnvironment> <serviceActivations> <add relativeAddress="Service.svc" service="TestWcf.Service"/> </serviceActivations> </serviceHostingEnvironment>
二,不直接引用WCF服务,使用代理类实现对WCF的调用
1,新建控制台程序,新建客户端代理类,MyClient
namespace WCFClient { /// <summary> /// 用于调用服务的类 /// </summary> public class MyClient : ClientBase<IService>, IService { public MyClient(Binding binding, EndpointAddress edpAddress) : base(binding, edpAddress) { } /// <summary> /// 调用服务端函数 /// </summary> /// <returns></returns> public string DoWork() { return base.Channel.DoWork(); } } }
2,调用测试
namespace WCFClient { class Program { static EndpointAddress edpHttp = new EndpointAddress("http://10.11.109.7:8001/Service.svc"); static void Main(string[] args) { MyClient client = new MyClient(new WSHttpBinding(SecurityMode.None), edpHttp); Console.WriteLine(client.DoWork()); Console.ReadKey(); } } }
3,运行结果
这样就可以不需要添加服务引用,而直接纯代码手工实现对WCF的调用。