在IIS中托管WCF4,从不读取WSDL:bindingNamespace

时间:2011-01-18 23:04:33

标签: wcf iis wsdl

尝试从wsdl文件中删除“tempuri”引用。我已经遵循了我能想到的所有现有建议。添加

[ServiceBehavior(Namespace="mynamespace")] 

属性到实现类,添加一个

[ServiceContract(Namespace="mynamespace")]

到合约接口并更改web.config中结束点的“bindingNamespace”属性以匹配。然而,当加载(在IIS中)时,绑定名称空间永远不会被更改..它始终是tempuri。

有没有人对解决此问题有任何其他想法?下面是来自web配置的示例...绑定名称空间永远不会,无论我做什么,更新为mynamespace,它总是tempuri.org。如果在通过主机工厂加载端点后,我遍历主机描述中的绑定并更新它们,它们将会改变,但这似乎是一个黑客攻击。

对于以下服务:“http://mydomain.com/MyService.svc”以下代表我的终点配置,这是否会被IIS使用?

<services>
  <service name="ServiceImplementationClassReference,MyAssembly" >
    <endpoint name=""
              address="MyService.svc"
              binding="basicHttpBinding"
              bindingNamespace="mynamespace"
              bindingConfiguration=""
              contract="IMyContract" />

    <endpoint name="mexHttpBinding" 
              address="mex"
              binding="mexHttpBinding"
              contract="IMetadataExchange" />        
  </service>
</services>

重新生成仍然引用tempuri.org

的生成的WSDL文件
  <wsdl:import namespace="http://tempuri.org/" location="http://mydomain.org/MyService.svc?wsdl=wsdl0" />

........

  <wsdl:service name="Directory">
    <wsdl:port name="BasicHttpBinding_IDirectoryServices"
    binding="i0:BasicHttpBinding_IDirectoryServices">
      <soap:address location="http://mydomain.org/MyService.svc" />
    </wsdl:port>
  </wsdl:service>

在wsdl:definition节点中,xml名称空间i0(由上面列出的服务引用)也设置为tempuri.org,因此需要import语句。如果我使用BasicHttpBinding或wsHttpBinding,则temprui的使用没有变化。实际上,在web.config文件中设置绑定到wsHttpBinding仍会导致上面的输出,引用BasicHttpBinding_IdirectoryServices。

谢谢!

1 个答案:

答案 0 :(得分:9)

似乎是一个已知问题:https://connect.microsoft.com/wcf/feedback/details/583163/endpoint-bindingnamespace?wa=wsignin1.0

这是我的web.config的一大概。请注意我将我的使用限制为HTTPS,因此YMMV包含您可能需要执行的操作:

    <behaviors>
        <endpointBehaviors>
            <behavior name="Secure" />
        </endpointBehaviors>
        <serviceBehaviors>
            <behavior name="MetadataBehavior">
                <serviceMetadata httpsGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <services>
        <service name="Company.Services.Implementation.Service" behaviorConfiguration="MetadataBehavior">
            <endpoint address="" behaviorConfiguration="Secure"
                      binding="basicHttpBinding" bindingConfiguration="httpsBinding" bindingNamespace="http://services.company.com"
                      contract="Company.Services.Interfaces.IService" />
            <endpoint address="mex" behaviorConfiguration="Secure"
                      binding="mexHttpsBinding" bindingConfiguration="httpsBinding" bindingNamespace="http://services.company.com"
                      contract="IMetadataExchange" />
        </service>
    </services>
    <bindings>
        <basicHttpBinding>
            <binding name="httpsBinding">
                <security mode="Transport" />
            </binding>
        </basicHttpBinding>
        <mexHttpsBinding>
            <binding name="httpsBinding" />
        </mexHttpsBinding>
    </bindings>

以下是来自Raffaele Rialdi的代码解决方案(由我稍加修改):

/// <summary>
/// Attribute which will add a binding namespace to every endpoint it's used in.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public sealed class BindingNamespaceBehaviorAttribute : Attribute, IServiceBehavior
{
    /// <summary>
    /// The binding namespace;
    /// </summary>
    private readonly string bindingNamespace;

    /// <summary>
    /// Initializes a new instance of the <see cref="BindingNamespaceBehaviorAttribute"/> class.
    /// </summary>
    /// <param name="bindingNamespace">The binding namespace.</param>
    public BindingNamespaceBehaviorAttribute(string bindingNamespace)
    {
        this.bindingNamespace = bindingNamespace;
    }

    /// <summary>
    /// Gets the binding namespace.
    /// </summary>
    /// <value>The binding namespace.</value>
    public string BindingNamespace
    {
        get
        {
            return this.bindingNamespace;
        }
    }

    /// <summary>
    /// Provides the ability to pass custom data to binding elements to support the contract implementation.
    /// </summary>
    /// <param name="serviceDescription">The service description of the service.</param>
    /// <param name="serviceHostBase">The host of the service.</param>
    /// <param name="endpoints">The service endpoints.</param>
    /// <param name="bindingParameters">Custom objects to which binding elements have access.</param>
    public void AddBindingParameters(
        ServiceDescription serviceDescription,
        ServiceHostBase serviceHostBase,
        Collection<ServiceEndpoint> endpoints,
        BindingParameterCollection bindingParameters)
    {
    }

    /// <summary>
    /// Provides the ability to change run-time property values or insert custom extension objects such as error
    /// handlers, message or parameter interceptors, security extensions, and other custom extension objects.
    /// </summary>
    /// <param name="serviceDescription">The service description.</param>
    /// <param name="serviceHostBase">The host that is currently being built.</param>
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }

    /// <summary>
    /// Provides the ability to inspect the service host and the service description to confirm that the service
    /// can run successfully.
    /// </summary>
    /// <param name="serviceDescription">The service description.</param>
    /// <param name="serviceHostBase">The service host that is currently being constructed.</param>
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        if (serviceHostBase == null)
        {
            throw new ArgumentNullException("serviceHostBase");
        }

        foreach (var endpoint in serviceHostBase.Description.Endpoints)
        {
            endpoint.Binding.Namespace = this.bindingNamespace;
        }
    }
}

使用像:

[ServiceBehavior(Namespace = "http://schemas.vevy.com/Printing")]
[BindingNamespaceBehavior("http://schemas.vevy.com/Printing")]
public class LabelsService : ILabelsService
{
    // ...
}