使用无文件激活时如何设置bindingNamespace?

时间:2011-05-31 15:03:06

标签: wcf

我正在尝试从使用fileless activation在IIS中托管的WCF服务中删除tempuri.org。我已按照here的说明操作了,当bindingNamespace中的Web.config属性出现时,我陷入困境,因为我正在使用无文件激活。

我的Web.config仅包含:

<serviceActivations>
    <add relativeAddress="Foo.svc"
         service="BigCorp.Services.Foo, BigCorp.Services"
         />
</serviceActivations>

因此,我没有<endpoint>节点可以设置bindingNamespace

怎么办?

6 个答案:

答案 0 :(得分:4)

您仍然可以将<services><endpoint>节点用于WCF无文件激活。看一下下面的例子,我甚至修改默认的wsHttpBinding以添加传输安全性并启用默认行为;全部用于“Module1.DES.ExternalDataService”服务的无文件激活。

  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding messageEncoding="Mtom">
          <security mode="Transport"/>
        </binding>
      </wsHttpBinding>
    </bindings>

    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <services>
      <service name="Module1.DES.ExternalDataService">
        <endpoint binding="wsHttpBinding" bindingNamespace="" contract="Module1.DES.IExternalDataService"/>
      </service>
    </services>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
      <serviceActivations>
        <add relativeAddress="ExternalDataService.svc" service="Module1.DES.ExternalDataService"/>
      </serviceActivations>

    </serviceHostingEnvironment>
  </system.serviceModel>

希望这有帮助。

答案 1 :(得分:3)

要更改绑定命名空间,您可以使用自定义工厂(而不是提供的默认工厂),您可以在其中更改绑定的所有属性:

  <serviceActivations>
    <add relativeAddress="Foo.svc"
         service="BigCorp.Services.Foo, BigCorp.Services"
         factory="BigCorp.Services.FooHostFactory, BigCorp.Services"/>
  </serviceActivations>

工厂:

public class FooHostFactory : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        return new FooServiceHost(serviceType, baseAddresses);
    }
}
public class FooServiceHost : ServiceHost
{
    public FooServiceHost(Type serviceType, params Uri[] baseAddresses)
        : base(serviceType, baseAddresses) { }

    protected override void OnOpening()
    {
        base.OnOpening();
        foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
        {
            if (!endpoint.IsSystemEndpoint)
            {
                endpoint.Binding.Namespace = "http://services.bigcorp.com/foo";
            }
        }
    }
}

答案 2 :(得分:0)

在您的服务代码中,您指定:

[ServiceContract(Namespace="http://your-url")]
public interface IMyInterface { ... }

您还可以为数据合同指定它:

[DataContract(Namespace="http://your-url/data")]
public class MyData { ... }

答案 3 :(得分:0)

除了service/data contract namespaces的明显变化外,您还可以在Binding对象本身设置a namespace,并在服务描述上设置命名空间:

Binding binding = new BasicHttpBinding();
binding.Namespace = "urn:binding_ns";
ServiceHost host = new ServiceHost(typeof(MyService), address);
var endpoint = host.AddServiceEndpoint(typeof(IMyService), binding, "");
host.Description.Namespace = "urn:desc_ns";

后者是控制WSDL文档本身的targetNamespace的东西。

答案 4 :(得分:0)

最后,我使用了源自this example的自定义BindingNamespaceAttribute

答案 5 :(得分:0)

如果您通过serviceActivations配置元素使用WCF 4.0的无文件服务激活功能,则可以在ServiceHost实现中覆盖AddDefaultEndpoints基本方法。

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

namespace MyApp.WS.WCFServiceHost
{

    public class MyHostFactory : ServiceHostFactory
    {
        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            return new EDOServiceHost(serviceType, baseAddresses);
        }
    }

    public class MyServiceHost : ServiceHost
    {
        public EDOServiceHost(Type serviceType, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses) { }


        public override System.Collections.ObjectModel.ReadOnlyCollection<ServiceEndpoint> AddDefaultEndpoints()
        {
            var endpoints = base.AddDefaultEndpoints();

            foreach (ServiceEndpoint endpoint in endpoints)
            {
                if (!endpoint.IsSystemEndpoint)
                {
                    endpoint.Binding.Namespace = NamespaceConstants.MyNamespace;
                }
            }

            return endpoints;
        }


    }
}

或者你可以只使用配置,唯一的缺点就是你略微违反DRY原则,因为你现在有两个点来维护命名空间字符串,一个在常量中,一个在配置文件中。

在下面的示例中,我使用WCFExtrasPlus行为来“展平”WSDL。如果你部署到.net 4.5 IIS7服务器,你不需要这个,因为你无论如何都可以访问一个扁平的WSDL,这是4.5框架内置的新功能,我离题了。

该示例还假设这些合同有两个服务合同和两个服务行为实现。

<system.serviceModel>

    <services>
      <service name ="MyApp.WS.ServiceBehaviour.Enquiries">
        <endpoint bindingNamespace="MyApp.WS" binding="basicHttpBinding" contract="MyApp.WS.ServiceContract.IEnquiries" />
      </service>

      <service name ="MyApp.WS.ServiceBehaviour.CallLogging">
        <endpoint bindingNamespace="MyApp.WS" binding="basicHttpBinding" contract="MyApp.WS.ServiceContract.ICallLogging" />
      </service>
    </services>

    <serviceHostingEnvironment>
      <serviceActivations>
        <add relativeAddress="Enquiries.svc" 
             service="MyApp.WS.ServiceBehaviour.Enquiries" 
             />
        <add relativeAddress="CallLogging.svc" 
             service="MyApp.WS.ServiceBehaviour.CallLogging" 
              />
      </serviceActivations>
    </serviceHostingEnvironment>

    <extensions>
      <behaviorExtensions> <!-- The namespace on the service behaviour, the service contract, the data contract and the binding must all be set to the same.-->
        <add name="wsdlExtensions" type="WCFExtrasPlus.Wsdl.WsdlExtensionsConfig, WCFExtrasPlus, Version=2.3.1.8201, Culture=neutral, PublicKeyToken=f8633fc5451b43fc" />
      </behaviorExtensions>
    </extensions>

    <behaviors>
      <endpointBehaviors>
        <behavior>
          <wsdlExtensions singleFile="true" />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, 
          set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="True"/>
          <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="True"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

供参考服务合约;

[ServiceBehavior(Namespace = NamespaceConstants.MyNamespace)]
public class CallLogging : ICallLogging 
{
}

[ServiceBehavior(Namespace = NamespaceConstants.MyNamespace)]
public class Enquiries : IEnquiries
{
}

注意:命名空间的名称中不需要http://。如果您喜欢MyApp.MyProject.Somthing,它可以是项目的命名空间。见URN