Skip to content

fix(csharp): preserve constructor param name when property is renamed to avoid class-name clash - #12763

Open
joelle-a-dev wants to merge 1 commit into
swagger-api:masterfrom
joelle-a-dev:fix/csharp-12757-ctor-param-underscore
Open

fix(csharp): preserve constructor param name when property is renamed to avoid class-name clash#12763
joelle-a-dev wants to merge 1 commit into
swagger-api:masterfrom
joelle-a-dev:fix/csharp-12757-ctor-param-underscore

Conversation

@joelle-a-dev

Copy link
Copy Markdown

Summary

Fixes #12757.

When a C# model property collides with its own class name (e.g. error_message on class ErrorMessage), AbstractCSharpCodegen.postProcessModels renames the property with a leading underscore (_ErrorMessage) to avoid a compile error.

The generated constructor's parameter name, however, was derived at template-render time by camelizing that already-renamed property name via the lambda.camelcase_param mustache lambda. DefaultCodegen.camelize() strips leading underscores as part of its snake_case-to-camelCase conversion, so the parameter ended up as errorMessage — identical to what it would have been without the rename — instead of _errorMessage.

Since Newtonsoft.Json matches constructor parameters to properties by name (case-insensitively, using the C# member name) when deserializing via a non-default constructor, the mismatched parameter name (errorMessage vs. property _ErrorMessage) meant the argument was never bound, silently leaving the property null (and throwing on required-property validation).

Fix

  • AbstractCSharpCodegen.postProcessModels now computes the constructor parameter name via toParamName(var.name) before the class-name-conflict rename, and when the conflict is detected, prepends _ to both the property name and the precomputed parameter name in lockstep (rather than letting the template re-derive it from the mutated name). The result is stored as vendorExtensions["x-parameter-name"].
  • modelGeneric.mustache now reads {{vendorExtensions.x-parameter-name}} instead of re-camelizing {{name}} via lambda.camelcase_param at every constructor call site.

This only affects the csharp generator's own templates; csharp-dotnet2, aspnetcore, and nancyfx (the other AbstractCSharpCodegen subclasses) use separate template directories and are unaffected.

Test plan

  • ./mvnw -pl modules/swagger-codegen -am compile succeeds.
  • Built the CLI jar and regenerated C# code from the exact spec in [C#] Properties are escaped with _, which causes deserialization to fail #12757 — the constructor now reads public ErrorMessage(string errorId, string _errorMessage) and assigns this._ErrorMessage = _errorMessage;, so the parameter now matches the property.
  • Existing test suites (csharp, csharpdotnettwo, aspnetcore, nancyfx, CamelCaseLambdaTest) pass: 34 tests, 0 failures.

… to avoid class-name clash

When a C# model property collides with its own class name, the codegen
renames it with a leading underscore (e.g. error_message -> _ErrorMessage)
to avoid a compile error. The generated constructor parameter name was
still derived by camelizing that already-renamed value at template
render time, which strips the leading underscore and produces a name
that no longer matches the property. Newtonsoft.Json then fails to bind
the constructor argument to the property during deserialization, leaving
it null.

Compute the parameter name in lockstep with the property rename instead
of re-deriving it from the mutated name at render time.

Fixes swagger-api#12757
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[C#] Properties are escaped with _, which causes deserialization to fail

1 participant