WSDL-первый подход: как указать разные имена для wsdl: port и wsdl: binding? - PullRequest
12 голосов
/ 16 января 2011

Я придерживаюсь подхода WSDL-first (предоставляемого нашим клиентом) для разработки службы WCF, но WSDL, сгенерированные из моей службы wcf, немного отличаются от WSDL, предоставленного мне нашим клиентом, и из-за этого несоответствия клиент сталкивается с трудностями звонок в мою службу.

Клиент предоставил wsdl:

<wsdl:service name='CheckoutService'> <wsdl:port binding='tns:CheckoutBinding' name='CheckoutServicePort'> <soap:address location='place holder to service uri' /> </wsdl:port> </wsdl:service>


WSDL, сгенерированный из службы wcf:

<wsdl:service name="CheckoutService"> <wsdl:port binding="tns:CheckoutBinding" name="CheckoutBinging"> <soap:address location="place holder to service uri" /> </wsdl:port> </wsdl:service>

и мои настройки службы следующие:

<endpoint name="CheckoutBinding" address="" binding="basicHttpBinding" bindingName="CheckoutServicePort" bindingConfiguration="basicHttpBinding" bindingNamespace="<<namespace>>" contract="<<contractname>>" />

Я использовал WSCF.Blue для генерации кода заглушки сервера из предоставленного клиентом wsdl и внес незначительные изменения в сгенерированный код, чтобы выдавать WSDL точно так же, как тот, который предоставлен клиентом, но я не понимаю, какие изменения сделать в файле конфигурации или в сгенерированном коде, чтобы получить то же самое «wsdl: port / @ name», что и в файле wsdl, предоставленном клиентом.

Согласно этому url свойство имени точки обслуживания сопоставляется с wsdl: port / @ name и wsdl: binding / @ name. Исходя из этого, значение атрибута конечной точки / @ name в моем конфигурационном файле отображается на wsdl: port / @ name и wsdl: binding / @ name, но я хочу, чтобы разные имена отображались на wsdl: port / @ name и wsdl: binding / атрибуты @name.

Пожалуйста, помогите мне в достижении этого.

1 Ответ

18 голосов
/ 16 января 2011

Вы можете попробовать реализовать IWsdlExportExtension и в ExportEndpoint изменить wsdl: port / @ name. Затем реализуйте IEndpointBehavior, который добавит ваше расширение к конечной точке. Чтобы использовать ваше новое поведение, у вас есть два варианта:

  • Добавить поведение из кода. Когда служба размещается в IIS, вы должны создать пользовательские ServiceHost и ServiceHostFactory. При самостоятельном размещении вы можете просто перебирать конечные точки и добавлять поведение.
  • Добавить поведение из конфигурации. Вы должны реализовать пользовательский BehaviorExtensionElement, зарегистрировать этот элемент и использовать его в endpointBehaviors, относящемся к вашей конечной точке.

Вот простой пример с элементом расширения:

using System;
using System.Configuration;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;

namespace CustomWsdlExtension    
{
    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 
            { 
                object value = this["name"];
                return value != null ? value.ToString() : string.Empty; 
            }
            set { this["name"] = value; }
        }

        public override Type BehaviorType
        {
            get { return typeof(PortNameWsdlBehavior); }
        }

        protected override object CreateBehavior()
        {
            return new PortNameWsdlBehavior { Name = Name };
        }
    }
}

И конфигурация:

  <system.serviceModel>
    <extensions>
      <behaviorExtensions>
        <add name="portName" type="CustomWsdlExtension.PortNameWsdlBehaviorExtension, CustomWsdlExtension" />
      </behaviorExtensions>
    </extensions>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="customPortName">
          <portName name="myCustomName" />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service name="CustomWsdlExtension.Service">
        <endpoint address="" binding="basicHttpBinding" contract="CustomWsdlExtension.IService"
                  behaviorConfiguration="customPortName" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

Мой WSDL выглядит так:

<wsdl:service name="Service">
    <wsdl:port name="myCustomName" binding="tns:BasicHttpBinding_IService">
        <soap:address location="http://localhost:2366/Service.svc" /> 
    </wsdl:port>
</wsdl:service>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...