Первый подход WSDL: как указать разные имена для wsdl: port и wsdl: binding?

Я следую WSDL-первому (предоставлен нашим клиентом) подходу для разработки службы 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 свойство name службы имен сопоставляется с wsdl: port/@name и wsdl: binding/@name. Исходя из этого, значение атрибута endpoint/@name в моем файле конфигурации отображается на wsdl: port/@name и wsdl: binding/@name, но я хочу, чтобы разные имена были сопоставлены с wsdl: port/@name и wsdl: binding/@name.

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

Ответ 1

Вы можете попробовать реализовать 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>