在基于WCF开发的Web Service导出WSDL定义问题及自定义wsdl:port 名称

         在契约优先的Web服务开发过程当中,每每是先拿到WSDL服务定义,各家开发各自的服务实现或客户端,而后互相调用。框架

         尽管Web Service的标准已经发布不少年,但各个语言,框架对其实现仍然有差别,实际使用中仍有许多坑须要填。ide

        .NET平台下,ASP.NET Web Service的兼容性最好,对比较复杂一点的wsdl文件更较好的生成Proxy Stub代码,而WCF兼容性较差,遇到复杂一点的生产就会存在问题,并且从Java等平台的客户端调用也存在问题。但毕竟WCF很灵活,能够嵌入到任何应用中,没必要必须是Web应用,这一点很诱人。this

         在Web Service服务实现好之后,通常不会直接使用原来的wsdl定义文件,平台会根据导出契约自动生成wsdl,而后客户端会据今生成相应的Proxy访问代码。spa

WCF导出WSDL的坑接口

      悲催的是,在我根据WSDL生成的类,并实现相应接口后,在导出的WSDL中找不到任何方法,基本就是空的,我还觉得哪里的配置出来问题,百思不得其解。改来改去,最后,用攒机时的最小系统法来排除,原来问题出在OperationContract里的Action属性,这个属性是由WSDL文件生成代码时自动产生的,所以不敢去改,但正是所以,致使没法正确生成WSDL,删掉之后,一切正常。ci

OperationContract的Action属性本是用于控制消息的派发,基本对应WSDL里定义的operation的名字,在一个服务里能够有一个方法Action=”*”来接收全部未处理的消息。开发

  [ServiceContract(Namespace="http://Microsoft.WCF.Documentation")]
  public interface ISampleService{

    [OperationContract(
      Action="http://Microsoft.WCF.Documentation/OperationContractMethod",
      Name="OCAMethod",
      ReplyAction="http://Microsoft.WCF.Documentation/ResponseToOCAMethod"
    )]
    string SampleMethod(string msg);

    [OperationContractAttribute(Action = "*")]
    void UnrecognizedMessageHandler(Message msg);
  }

至于为什么有他会影响我WSDL的导出,还但愿高手指点。get

wsdl:port的名称的自定义string

       本人先使用的使用Java平台的JAX-WS实现Linux下Web Service,而后在Windows上用客户端调用,客户端同时本身也实现Web Service,用于回调消息。这里问题就来了,同一个WSDL定义,在Java下面名称是XXXServerSoap,而在WCF里就是BasicHttpBinding_XXXServerSoap,这样在Java里回调的时候就失败了,本人Java不熟,不知道Java里为啥不能自动取可用的port,非得指定命名。这里最好能把BasicHttpBinding_这个前缀去掉,查了很久好像这是写死的,BasicHttpBinding这个名字能够改,但必须是BindingName_ServiceName这种形式。it

    惟一有的办法就是写一个扩展,自定义WSDL导出过程,呵呵还真有人这么干

    public class PortNameWsdlBehavior : IWsdlExportExtension, IEndpointBehavior
    {
        public string Name { get; set; }

        public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)
        {
        }

        public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)
        {
            if (!string.IsNullOrEmpty(Name))
            {
                context.WsdlPort.Name = Name;
            }
        }

        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
        {
        }

        public void Validate(ServiceEndpoint endpoint)
        {
        }
    }

    public class PortNameWsdlBehaviorExtension : BehaviorExtensionElement
    {
        [ConfigurationProperty("name")]
        public string Name
        {
            get
            {
                Console.WriteLine("PortNameWsdlBehaviorExtension");
                object value = this["name"];
                return value != null ? value.ToString() : string.Empty;
            }
            set { this["name"] = value; }
        }

        public override Type BehaviorType
        {
            get { return typeof(PortNameWsdlBehavior); }
Technorati 标签: Web Service, WCF, WSDL, Java, JAX-WS
        }

        protected override object CreateBehavior()
        {
            return new PortNameWsdlBehavior { Name = Name };
        }
    }
拷贝,粘贴。在服务配置节<system.serviceModel>中加入扩展的配置:
  <extensions>
        <behaviorExtensions>
            <add name="portName" type="<NameSpace>.PortNameWsdlBehaviorExtension, <NameSpace>, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
        </behaviorExtensions>
 </extensions>
搞定,这时候再看wsdl:port的name属性已经变成你的binding name了,你在配置文件里爱怎么配置怎么配置
相关文章
相关标签/搜索