WCF - 使用命名空间进行版本控制服务时生成平面WSDL时出错

时间:2018-06-18 21:42:23

标签: c# .net wcf wsdl versioning

我有一个WCF Web服务,我想要版本。在这种情况下,我有一个特定的操作MyOperation,它可以更改类型签名并在语义上进行更改,以便获得新的主要版本。我希望客户端尽可能只将命名空间从 v1 更改为 v2 ,并能够使用新操作。

我使用严格的版本控制并定义服务合同(我使用占位符名称):

[DataContract(Namespace = "http://mycompany.com/myService/v1", Name = "MyOpResponse")]
public class MyOpResponse
{
    [DataMember]
    public string Value { get; set; }
}

[ServiceContract(Namespace = "http://mycompany.com/myService/v1")]
public interface IMyService
{
    [OperationContract(Name = "MyOperation")]
    MyOpResponse MyOperation(string parameter);

    [OperationContract(Name = "MyOtherOperation")]
    int MyOtherOperation(int parameter);
}

[DataContract(Namespace = "http://mycompany.com/myService/v2", Name = "MyOpResponse")]
public class MyOpResponse_v2
{
    [DataMember]
    public int Value { get; set; }
}

[ServiceContract(Namespace = "http://mycompany.com/myService/v2")]
public interface IMyService_v2
{
    [OperationContract(Name = "MyOperation")]
    MyOpResponse_v2 MyOperation_v2(string parameter);

    [OperationContract(Name = "MyOtherOperation")]
    int MyOtherOperation(int parameter);
}

我想将MyOperation更改为具有新返回类型的新版本,但其他操作保持不变(例如MyOtherOperation

服务定义如下(使用默认实现):

public class MyService : IMyService, IMyService_v2
{
    public MyOpResponse_v2 MyOperation_v2(string parameter)
    {
        return new MyOpResponse_v2 { Value = parameter.Length };
    }

    public int MyOtherOperation(int parameter)
    {
        return parameter + 100;
    }

    public MyOpResponse MyOperation(string parameter)
    {
        return new MyOpResponse { Value = parameter };
    }
}

在我的 Web.config 中,我有以下定义:

<behaviors>
    <endpointBehaviors>
        <behavior name="MyEndpointBehavior" />
    </endpointBehaviors>
</behaviors>

<serviceBehaviors>
    <behavior name="MyServiceBehavior">
        <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
        <serviceDebug includeExceptionDetailInFaults="true" />
        <serviceSecurityAudit auditLogLocation="Application" suppressAuditFailure="true" serviceAuthorizationAuditLevel="Failure" messageAuthenticationAuditLevel="Failure" />
        <aspNetCompatibilityRequirementsBehavior requirementsMode="Allowed" />
    </behavior>
</serviceBehaviors>

<bindings>
    <basicHttpBinding>
        <binding name="MyBinding">
            <security mode="None" />
        </binding>
    </basicHttpBinding>
</bindings>

<service behaviorConfiguration="MyServiceBehavior" name="MyCompany.MyService">
    <endpoint address="" behaviorConfiguration="MyEndpointBehavior" binding="basicHttpBinding" bindingConfiguration="MyBinding" name="MyService" contract="MyCompany.IMyService" />

    <endpoint address="" behaviorConfiguration="MyEndpointBehavior" binding="basicHttpBinding" bindingConfiguration="MyBinding" name="MyService_v2" contract="MyCompany.IMyService_v2" />
</service>

当我发布服务时,http://localhost/MyService.svc?wsdl中生成的WSDL似乎是正确的(我删除了不相关的名称空间和定义):

<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:i1="http://mycompany.com/myService/v2" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://tempuri.org/" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:i0="http://mycompany.com/myService/v1" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" name="MyService" targetNamespace="http://mycompany.com/myService/v2">
    <wsdl:binding name="MyService" type="i0:IMyService">
    ...
    </wsdl:binding>

    <wsdl:binding name="MyService_v2" type="i1:IMyService_v2">
    ...
    </wsdl:binding>

    <wsdl:service name="MyService">
        <wsdl:port name="MyService" binding="tns:MyService">
            <soap:address location="http://localhost/MyService.svc"/>
        </wsdl:port>
        <wsdl:port name="MyService_v2" binding="tns:MyService_v2">
            <soap:address location="http://localhost/MyService.svc"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

但是,如果我尝试用http://localhost/MyService.svc?singleWsdl生成平面WSDL文件,我会收到此错误:

System.NotSupportedException: A single WSDL document could not be generated for this service. Multiple service contract namespaces were found (http://mycompany.com/myService/v1, http://mycompany.com/myService/v2). Ensure that all your service contracts have the same namespace.

通过上述解决方案,我在http://localhost/MyService.svc托管了我的两个服务版本。如果客户端想要调用v1,他只需要使用命名空间 http://mycompany.com/myService/v1 ;如果他想要更改为v2版本,他只需要将命名空间更改为http://mycompany.com/myService/v2。正确生成带导入的WSDL文件,但只生成错误的平面WSDL文件。我需要生成平面WSDL以提供给第三方。

是否可以使用上述版本控制系统并仍使用?singleWSDL正确生成平面WSDL?

如果没有,有什么更好的选择?

0 个答案:

没有答案