wcf icon indicating copy to clipboard operation
wcf copied to clipboard

`dotnet-svcutil` generates incomplete client classes when providing multiple WSDL services

Open jacobjmarks opened this issue 1 year ago • 0 comments

Describe the bug When attempting to generate a single C# service client reference for more than one WSDL spec - for the purposes of type reuse - all but the last service client class contains missing elements. See details below.

To Reproduce Please find below a sample project which demonstrates this issue. https://github.com/jacobjmarks/dotnet-svcutil-issue-demo

Contained within the repository are 3 WSDL services which closely represent the format of services I am looking to generate.

In general, all services each contain a single operation with unique request/response models, and all services reference a common reference type called ServiceFault, in this case. I am trying to generate the service clients in a way such that these common reference types between services are in fact shared in the resultant C# code.

There are two scripts as described below:

  • generate-service-clients.ps1 Uses the dotnet-svcutil command once for each service; i.e.

    dotnet-svcutil service-a.wsdl
    dotnet-svcutil service-b.wsdl
    dotnet-svcutil service-c.wsdl
    

    Generates separate service clients within the MyProject/ServiceReference folder; i.e. ServiceA.cs, ServiceB.cs, ServiceC.cs. The results here are as expected: All service client classes contain the following constructors, as well as the partial ConfigureEndpoint method, as below;

    static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);
    public ServiceAServiceClient() : base(ServiceAServiceClient.GetDefaultBinding(), ServiceAServiceClient.GetDefaultEndpointAddress()) { ... }
    public ServiceAServiceClient(EndpointConfiguration endpointConfiguration) : base(ServiceAServiceClient.GetBindingForEndpoint(endpointConfiguration), ServiceAServiceClient.GetEndpointAddress(endpointConfiguration)) { ... }
    public ServiceAServiceClient(EndpointConfiguration endpointConfiguration, string remoteAddress) : base(ServiceAServiceClient.GetBindingForEndpoint(endpointConfiguration), new System.ServiceModel.EndpointAddress(remoteAddress)) { ... }
    public ServiceAServiceClient(EndpointConfiguration endpointConfiguration, System.ServiceModel.EndpointAddress remoteAddress) : base(ServiceAServiceClient.GetBindingForEndpoint(endpointConfiguration), remoteAddress) { ... }
    public ServiceAServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : base(binding, remoteAddress) { ... }
    
  • generate-shared-service-clients.ps1 Uses the dotnet-svcutil once for all services; i.e.

    dotnet-svcutil service-a.wsdl service-b.wsdl service-c.wsdl
    

    Generates a shared service client within the MyProject/SharedServiceReference folder; i.e. Services.cs. The results here are not as expected: All but the last service client class contains only the following constructor (the partial ConfigureEndpoint method is also missing):

    public ServiceAServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : base(binding, remoteAddress) { ... }
    

    In addition, the last (fully-featured) service client class seems to erroneously contain the GetBindingForEndpoint and GetEndpointAddress methods as well as the EndpointConfiguration enum which contain endpoint information for all three services.

Expected behavior When passing multiple WSDL services to the dotnet-svcutil command, fully-featured service client classes are generated as if they were individually generated, and share reference types where applicable.

The GetBindingForEndpoint(), GetEndpointAddress(), and enum EndpointConfiguration elements are abstracted in a way such that etiher

  • All services reference a shared implementation which contains information for all services
  • OR All services reference a local implementation which contains information only for that single service

Additional context Project is targeting net6.0 Generated with dotnet-svcutil/2.0.3

Notes Please do let me know if this is not in fact an intended use case for this tool, or I am approaching this the wrong way.

jacobjmarks avatar Sep 01 '22 01:09 jacobjmarks