新开传奇网站一,c 购物网站开发流程图,手机app网站模板,专业制作网站报价WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现]#xff08;提供模拟程序#xff09; 原文:WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现]#xff08;提供模拟程序#xff09;基于HTTP-GET的元数据发布方式与基于WS-MEX原理类似… WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现]提供模拟程序 原文:WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现]提供模拟程序基于HTTP-GET的元数据发布方式与基于WS-MEX原理类似,但是ServiceMetadataBehavior需要做的更多额外的工作。原因很简单由于在WS-MEX模式下我们为寄宿的服务添加了相应的MEX终结点那么当服务被成功寄宿后WCF已经为元数据的消息交换建立了如图1所示的分发体系我们需要做的仅仅是对MEX终结点的DispatchRuntime进行相应的定制而已。 图1 WCF服务端分发体系 但是如果采用HTTP-GET模式实际上我们需要从ChannelDispatcher开始重新构建整个分发体系。接下来我们在《WS-MEX原理》提供实例的基础上对我们自定义ServiceMetadataBehaviorAttribute进行进一步的完善使之同时对两种模式的元数据发布提供支持。 Source Code从这里下载 首先我们需要定义一个新的服务契约接口IHttpGetMetadataGet操作处理任何形式的消息请求因为它的输入参数和返回类型均为Message并且Action和ReplyAction为*。 1: using System.ServiceModel; 2: using System.ServiceModel.Channels; 3: namespace ServiceMetadataBehaviorSimulator 4: { 5: [ServiceContract(Name IHttpGetMetadata, Namespace http://www.artech.com/)] 6: public interface IHttpGetMetadata 7: { 8: [OperationContract(Action *, ReplyAction *)] 9: Message Get(Message msg); 10: } 11: } 然后我们让前面定义的MetadataProvisionService实现IHttpGetMetadata接口在这里无需再写任何多余的代码因为MetadataProvisionService已经具有了一个Get方法。 1: public class MetadataProvisionService : IMetadataProvisionService, IHttpGetMetadata 2: { 3: //省略成员 4: } 接下来的工作就是构建一个全新的ChannelDispatcher以及关联EndpointDispatcher最后对EndpointDispatcher的DispatchRuntime进行定制。为此我单独写了一个方法CreateHttpGetChannelDispatcher。 1: [AttributeUsage(AttributeTargets.Class)] 2: public class ServiceMetadataBehaviorAttribute : Attribute, IServiceBehavior 3: { 4: //其他成员 5: private const string SingletonInstanceContextProviderType System.ServiceModel.Dispatcher.SingletonInstanceContextProvider,System.ServiceModel, Version3.0.0.0, Cultureneutral, PublicKeyTokenb77a5c561934e089; 6: private const string SyncMethodInvokerType System.ServiceModel.Dispatcher.SyncMethodInvoker,System.ServiceModel, Version3.0.0.0, Cultureneutral, PublicKeyTokenb77a5c561934e089; 7: private const string MessageOperationFormatterType System.ServiceModel.Dispatcher.MessageOperationFormatter, System.ServiceModel, Version3.0.0.0, Cultureneutral, PublicKeyTokenb77a5c561934e089; 8: 9: private static void CreateHttpGetChannelDispatcher(ServiceHostBase host, Uri listenUri, MetadataSet metadata) 10: { 11: //创建Binding 12: TextMessageEncodingBindingElement messageEncodingElement new TextMessageEncodingBindingElement() { MessageVersion MessageVersion.None }; 13: HttpTransportBindingElement transportElement new HttpTransportBindingElement(); 14: Utility.SetPropertyValue(transportElement, Method, GET); 15: Binding binding new CustomBinding(messageEncodingElement, transportElement); 16: 17: //创建ChannelListener 18: IChannelListener listener binding.BuildChannelListenerIReplyChannel(listenUri, string.Empty, ListenUriMode.Explicit, new BindingParameterCollection()); 19: ChannelDispatcher dispatcher new ChannelDispatcher(listener, ServiceMetadataBehaviorHttpGetBinding, binding) { MessageVersion binding.MessageVersion }; 20: 21: //创建EndpointDispatcher 22: EndpointDispatcher endpoint new EndpointDispatcher(new EndpointAddress(listenUri), IHttpGetMetadata, http://www.artech.com/); 23: 24: //创建DispatchOperation并设置DispatchMessageFormatter和OperationInvoker 25: DispatchOperation operation new DispatchOperation(endpoint.DispatchRuntime, Get, *, *); 26: operation.Formatter Utility.CreateInstanceIDispatchMessageFormatter(MessageOperationFormatterType, Type.EmptyTypes, new object[0]); 27: MethodInfo method typeof(IHttpGetMetadata).GetMethod(Get); 28: operation.Invoker Utility.CreateInstanceIOperationInvoker(SyncMethodInvokerType, new Type[] { typeof(MethodInfo) }, new object[] { method }); 29: endpoint.DispatchRuntime.Operations.Add(operation); 30: 31: //设置SingletonInstanceContext和InstanceContextProvider 32: MetadataProvisionService serviceInstance new MetadataProvisionService(metadata); 33: endpoint.DispatchRuntime.SingletonInstanceContext new InstanceContext(host, serviceInstance); 34: endpoint.DispatchRuntime.InstanceContextProvider Utility.CreateInstanceIInstanceContextProvider(SingletonInstanceContextProviderType, new Type[] { typeof(DispatchRuntime) }, new object[] { endpoint.DispatchRuntime }); 35: dispatcher.Endpoints.Add(endpoint); 36: 37: //设置ContractFilter和AddressFilter 38: endpoint.ContractFilter new MatchAllMessageFilter(); 39: endpoint.AddressFilter new MatchAllMessageFilter(); 40: 41: host.ChannelDispatchers.Add(dispatcher); 42: } 43: } 大体上介绍一下创建ChannelDispatcher的逻辑。首先创建绑定对象该绑定由两个绑定元素构成TextMessageEncodingBindingElement和HttpTransportBindingElement这些因为元数据请求消息就是单纯的HTTP-GET请求消息并不是一个SOAP所以需要将HttpTransportBindingElement的消息版本设为None并将Method属性这是一个internal属性设为GET。 然后利用创建的绑定对象创建ChannelListener并基于该ChannelListener创建ChannelDispatcher对象。当ChannelDispatcher成功创建开始创建EndpointDispatcher对象并定制该EndpointDispatcher的DispatchRuntime。这其中包括创建DispatchOperation对象以及相关的消息格式化器以及操作执行器。然后是我们熟悉的对InstanceContextProvider和SingletonInstanceContext的设定。最后需要设置EndpointDispatcher的两个消息筛选器契约筛选器和地址筛选器在这将它们设置成MatchAllMessageFilter类型使之能够匹配所有的请求消息。关于WCF的消息筛选机制在《WCF技术剖析卷1》第2章有详细介绍。 待DispatchRuntime被成功定制将创建的EndpointDispatcher添加到ChannelDispatcher的EndpointDispatcher列表最终再将ChannelDispatcher添加到ServiceHost的ChannelDispatcher列表中。 然后我们在ServiceMetadataBehaviorAttribute添加两个属性HttpGetEnabled和HttpGetUrl前者表示是否采用基于HTTP-GET的元数据发布模式后者指定元数据发布的地址。并将上面定义的CreateHttpGetChannelDispatcher添加到ApplyDispatchBehavior方法中。 1: [AttributeUsage(AttributeTargets.Class)] 2: public class ServiceMetadataBehaviorAttribute : Attribute, IServiceBehavior 3: { 4: //其他成员 5: public bool HttpGetEnabled 6: { get; set; } 7: public string HttpGetUrl 8: { get; set; } 9: public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 10: { 11: MetadataSet metadata GetExportedMetadata(serviceDescription); 12: CustomizeMexEndpoints(serviceDescription, serviceHostBase, metadata); 13: if (this.HttpGetEnabled) 14: { 15: CreateHttpGetChannelDispatcher(serviceHostBase, new Uri(this.HttpGetUrl), metadata); 16: } 17: } 18: } 那么现在我们就可以通过下面的方式将ServiceMetadataBehaviorAttribute应用到我们的CalculatorService并通过HttpGetUrl属性指定原数据发布的目标地址 1: [ServiceMetadataBehavior(HttpGetEnabled true, HttpGetUrl http://127.0.0.1:9999/calculatorservice/mex)] 2: public class CalculatorService : ICalculator, IMetadataProvisionService 3: { 4: //省略成员 5: } 如果CalculatorService被成功寄宿直接通过浏览器访问元数据发布的地址http://127.0.0.1:9999/calculatorservice/mex你可以看到与图2一样的结果。 图2 通过IE获取发布的元数据 作者Artech 出处http://artech.cnblogs.com 本文版权归作者和博客园共有欢迎转载但未经作者同意必须保留此段声明且在文章页面明显位置给出原文连接否则保留追究法律责任的权利。 posted on 2015-07-10 15:25 NET未来之路 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/lonelyxmas/p/4635861.html