dotnet / dotnet/wcf

ServiceContractAttribute.ConfigurationName differs from what Visual Studio generated

Open
#5,359 5 comments 0 reactions 1 assignee Claimed by @imcarolwang View on GitHub
tooling
Dominant language
C#
Stars
1.8k
Forks
576
Avg merge
6d 9h
Merged PRs (30d)
2

Description

**Describe the bug**

When Visual Studio 2017 generates code for a Service Reference, it sets ServiceContractAttribute.ConfigurationName = the name of the Service Reference + "." + the name of the interface type. However, dotnet-svcutil 2.1.0 instead sets ServiceContractAttribute.ConfigurationName = the full name of the interface type. This difference makes the generated code incompatible with existing configuration files, hindering our migration from .NET Framework to .NET.

(We're first switching to SDK-style csproj files and dotnet-svcutil before we start multitargeting.)

**To Reproduce**

The attached [ConfigurationNameDemo.zip](https://github.com/dotnet/wcf/files/13392062/ConfigurationNameDemo.zip) demonstrates the problem. It contains three projects:

* DemoService is a WCF web service. It has an old-style C# project file and targets .NET Framework 4.8.

* DemoProjectVS is a console application that uses DemoService via a "Connected Service" (`WCFMetadata` item) in Visual Studio. It has an old-style C# project file and targets .NET Framework 4.8.

Visual Studio generates `ConfigurationName="DemoService.IService1"`:

```csharp
namespace DemoProjectVS.DemoService {


[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="DemoService.IService1")]
public interface IService1 {
```

The App.config file then has: `contract="DemoService.IService1"`:

```XML

```

* DemoProjectSvcUtil is a console application that uses DemoService via code generated by dotnet-svcutil 2.1.0, augmented with a `partial class` that lets the application use the [ClientBase\(string endpointConfigurationName)](https://learn.microsoft.com/dotnet/api/system.servicemodel.clientbase-1.-ctor?view=netframework-4.8#system-servicemodel-clientbase-1-ctor(system-string)) constructor. It has an SDK-style C# project file and targets .NET Framework 4.8.

`dotnet-svcutil` generates `ConfigurationName="DemoProjectSvcUtil.DemoService.IService1"`:

```csharp
namespace DemoProjectSvcUtil.DemoService
{


[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.1.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="DemoProjectSvcUtil.DemoService.IService1")]
internal interface IService1
{
```

The App.config file then has: `contract="DemoProjectSvcUtil.DemoService.IService1"`:

```XML

```

**Expected behavior**

Have some way to generate the same ServiceContractAttribute.ConfigurationName as in Service Reference in Visual Studio. For example, the parameters JSON file could support a "configurationNamespaceMappings" akin to "namespaceMappings":

```JSON
{
"providerId": "Microsoft.Tools.ServiceModel.Svcutil",
"version": "2.1.0",
"options": {
"configurationNamespaceMappings": [
"*, DemoService"
]
"inputs": [
"Service1.wsdl",
"Service11.xsd",
"Service12.xsd"
],
"internal": true,
"namespaceMappings": [
"*, DemoProjectSvcUtil.DemoService"
],
"outputFile": "Reference.cs",
"sync": true,
"targetFramework": "net48",
"typeReuseMode": "All"
}
}
```

Alternatively, the parameters JSON file could support a mapping from Type.FullName to the desired ServiceContractAttribute.ConfigurationName. This would be more tedious to configure if there are multiple services in the same WSDL:

```JSON
"configurationNameMappings": [
"DemoProjectSvcUtil.DemoService.IService1, DemoService.IService1"
]
```

Either way, the parameters would then cause the generated code to change:

```diff
--- a/DemoProjectSvcUtil/ServiceReferences/DemoService/Reference.cs
+++ b/DemoProjectSvcUtil/ServiceReferences/DemoService/Reference.cs
@@ -10,11 +10,11 @@
namespace DemoProjectSvcUtil.DemoService
{

[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.1.0")]
- [System.ServiceModel.ServiceContractAttribute(ConfigurationName="DemoProjectSvcUtil.DemoService.IService1")]
+ [System.ServiceModel.ServiceContractAttribute(ConfigurationName="DemoService.IService1")]
internal interface IService1
{

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService1/GetData", ReplyAction="http://tempuri.org/IService1/GetDataResponse")]
string GetData();
```

**Screenshots**

None.

**Additional context**

It seems Visual Studio uses [VSWCFServiceContractGenerator.PatchConfigurationName](https://github.com/microsoft/referencesource/blob/51cf7850defa8a17d815b4700b67116e3fa283c2/System.Web.Extensions/Compilation/WCFModel/VSWCFServiceContractGenerator.cs#L977-L1035) to change ConfigurationName after ServiceContractGenerator has generated it. The VSWCFServiceContractGenerator class does not exist in .

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.