Skip to content

C# generator erases referenced additionalProperties value schemas #262

Description

@daviburg

Description

The C# DirectClient generator erases a concrete model referenced as the value schema of additionalProperties.

Seismic Planner's reachable Swagger model has this shape:

{
  "CustomPropertyValues": {
    "type": "object",
    "properties": {
      "localizations": {
        "type": "object",
        "additionalProperties": {
          "$ref": "#/definitions/CustomPropertyDataDisplay"
        }
      }
    }
  },
  "CustomPropertyDataDisplay": {
    "type": "object",
    "properties": {
      "name": {
        "type": "string"
      }
    }
  }
}

At immutable .NET main commit 70a1f5ed, the generated client instead exposes JsonElement? Localizations, and CustomPropertyDataDisplay is not emitted anywhere in the file.

This was reproduced during Python SDK PR 77 validation by generating C# and Python from the same fresh ARM Swagger cache with AzureUX-BPM generator PR 16929357 source commit b57efae. The cross-language model-coverage check identified CustomPropertyDataDisplay as reachable from an operation contract but unmatched in generated C#.

The controlling fix belongs in the BPM CodefulSdkGenerator; this .NET SDK issue tracks the public generated-contract defect and required regeneration.

Steps to reproduce

  1. Export the Seismic Planner managed connector Swagger.
  2. Generate its C# DirectClient with the CodefulSdkGenerator.
  3. Inspect CustomPropertyValues.Localizations and the generated model declarations.
  4. Observe that Localizations is JsonElement? and that no CustomPropertyDataDisplay class is generated, despite the reachable additionalProperties.$ref.

Expected behavior

The generated contract should retain the map value schema, for example:

[JsonPropertyName("localizations")]
public Dictionary<string, CustomPropertyDataDisplay> Localizations { get; set; }

public class CustomPropertyDataDisplay
{
    [JsonPropertyName("name")]
    public string Name { get; set; }
}

The generator's reachable-model traversal should follow $ref values beneath additionalProperties, and its C# type mapper should preserve typed dictionary value shapes rather than degrading them to free-form JSON.

SDK version

main at 70a1f5ed.

.NET version

Generation defect; reproduced with .NET SDK 10.0.101 while building the generator's net8.0 target.

Additional context

This is distinct from:

  • Issue 157, which intentionally types genuinely free-form JSON properties as JsonElement?. Here the source contract supplies a concrete value schema.
  • Issue 231, which covers CLR member-name collisions, including reserving the synthetic AdditionalProperties member name.
  • Issue 232, which was closed after separating unreachable definitions, typeless schemas, and Python wire-name collisions. This model is reachable through CustomPropertyValues.properties.localizations.additionalProperties.

Suggested acceptance criteria:

  • Add a generator regression where a reachable property is an object whose additionalProperties value is a $ref to a concrete model.
  • Emit Dictionary<string, T> and retain T in the generated model graph.
  • Cover nested/cyclic references without duplicate model emission or infinite traversal.
  • Preserve existing free-form and primitive-map behavior.
  • Regenerate Seismic Planner and add a JSON round-trip test with arbitrary locale keys and typed CustomPropertyDataDisplay values.
  • Validate C# and Python model coverage from one immutable Swagger cache.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions