Skip to content

Fix/csharp reserved headers and file parameter not serialising correctly#23593

Open
BottlecapDave wants to merge 7 commits intoOpenAPITools:masterfrom
BottlecapDave:fix/csharp-reserved-headers
Open

Fix/csharp reserved headers and file parameter not serialising correctly#23593
BottlecapDave wants to merge 7 commits intoOpenAPITools:masterfrom
BottlecapDave:fix/csharp-reserved-headers

Conversation

@BottlecapDave
Copy link
Copy Markdown

@BottlecapDave BottlecapDave commented Apr 21, 2026

This PR fixes a couple of issues

  • Fixes issue with certain reserved headers being added to the request object instead of the content object (fixes Misused header name 'Content-Range' when generating .NET API client #21727)
  • Fixes issue with serialising of FileParameter parameters which are incorrectly JSON serialised as the content instead of the contained stream
  • Updates samples based on template changes

I've tested this locally via template overrides. I'm not sure what else needs to be included for this PR.

@mandrean, @shibayan, @Blackclaws, @lucamazzanti, @iBicha

PR checklist

  • Read the contribution guidelines.
  • Pull Request title clearly describes the work in the pull request and Pull Request description provides details about how to validate the work. Missing information here may result in delayed response from the community.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • File the PR against the correct branch: master (upcoming 7.x.0 minor release - breaking changes with fallbacks), 8.0.x (breaking changes without fallbacks)
  • If your PR solves a reported issue, reference it using GitHub's linking syntax (e.g., having "fixes #123" present in the PR description)
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Fixes request building in the C# generichost client so reserved headers and file uploads are handled correctly. Fixes #21727.

  • Bug Fixes

    • Route reserved content headers (e.g., content-type, content-length, content-language, content-disposition) to HttpContent headers instead of the request message.
    • Serialize FileParameter as the contained stream (not JSON) for correct file upload behavior.
  • Refactors

    • Centralized content header detection in ClientUtils (IsContentHeader) with a header list compatible with older .NET versions; updated templates to use it.
    • Regenerated C# generichost samples to reflect template changes.

Written for commit dd199ab. Summary will update on new commits.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 158 files

Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed. cubic prioritises the most important files to review.

@wing328
Copy link
Copy Markdown
Member

wing328 commented Apr 21, 2026

thanks for the PR

cc @devhl-labs

private JsonSerializerOptions _jsonSerializerOptions;

private readonly string[] _contentHeaders =
[
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider making this static readonly, or move it to ClientUtils.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to ClientUtils

"content-type",
"expires",
"last-modified",
"extension-header"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot is telling me extension-header is demonstrating the format, but isn't a real entry. Consider removing it. I'd also appreciate if you remove the spaces that appear after these values.

httpRequestMessageLocalVar.Content = ({{paramName}}{{^required}}.Value{{/required}} as object) is System.IO.Stream stream
? httpRequestMessageLocalVar.Content = new StreamContent(stream)
: httpRequestMessageLocalVar.Content = new StringContent(JsonSerializer.Serialize({{paramName}}{{^required}}.Value{{/required}}, _jsonSerializerOptions));
if (({{paramName}}{{^required}}.Value{{/required}} as object) is System.IO.Stream stream)
Copy link
Copy Markdown
Contributor

@devhl-labs devhl-labs Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In generichost I don't believe it will ever be a System.IO.Stream anymore, I think its always going to be a FileParameter. Im not positive though. Worth looking into. You can leave this alone if you want though.

edit - I had copilot check and despite the type mapping being a Stream, the templates actually use FileParameter, so it should be safe to remove.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

17 issues found across 207 files (changes from recent commits).

Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed. cubic prioritises the most important files to review.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="samples/client/petstore/csharp/generichost/net10/AnyOf/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/net10/AnyOf/src/Org.OpenAPITools/Client/ClientUtils.cs:333">
P2: `ContentHeaders` is missing `content-disposition`, so `IsContentHeader()` will misclassify valid multipart/file headers and route them to request headers instead of content headers.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/latest/Tags/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/latest/Tags/src/Org.OpenAPITools/Client/ClientUtils.cs:344">
P2: `Content-Disposition` is missing from the content-header allowlist, so `IsContentHeader()` will misclassify a valid content header as a request header.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/net10/SourceGeneration/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/net10/SourceGeneration/src/Org.OpenAPITools/Client/ClientUtils.cs:434">
P2: `ContentHeaders` allowlist is incomplete (missing `content-disposition`), so valid content headers can be misrouted to request headers.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/latest/ComposedEnum/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/latest/ComposedEnum/src/Org.OpenAPITools/Client/ClientUtils.cs:324">
P1: `ContentHeaders` is missing the standard `content-disposition` content header, so `IsContentHeader()` will misclassify valid content headers and can route them to the wrong header collection.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/net10/AnyOfNoCompare/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/net10/AnyOfNoCompare/src/Org.OpenAPITools/Client/ClientUtils.cs:318">
P2: `Content-Disposition` is a standard content header but is missing from the allowlist, so `IsContentHeader()` misclassifies it as a non-content header.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/latest/UseDateTimeOffset/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/latest/UseDateTimeOffset/src/Org.OpenAPITools/Client/ClientUtils.cs:419">
P2: `IsContentHeader` uses an incomplete content-header allowlist and omits `content-disposition`, which can misroute that header to request headers instead of content headers.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/net10/NullReferenceTypes/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/net10/NullReferenceTypes/src/Org.OpenAPITools/Client/ClientUtils.cs:434">
P1: `content-disposition` is missing from the reserved content-header allowlist, so it can still be routed to request headers instead of `HttpContent.Headers`.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/net4.7/Petstore/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/net4.7/Petstore/src/Org.OpenAPITools/Client/ClientUtils.cs:432">
P2: `ContentHeaders` is missing `content-disposition`, so `IsContentHeader()` will misclassify that reserved content header and route it to the wrong header collection.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/latest/InlineEnumAnyOf/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/latest/InlineEnumAnyOf/src/Org.OpenAPITools/Client/ClientUtils.cs:320">
P2: `ContentHeaders` is incomplete for `HttpContentHeaders` because it omits `content-disposition`, causing potential misclassification of a valid content header.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/net4.7/AnyOfNoCompare/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/net4.7/AnyOfNoCompare/src/Org.OpenAPITools/Client/ClientUtils.cs:304">
P2: `Content-Disposition` is a valid `HttpContentHeaders` member but is missing from the content-header whitelist, so `IsContentHeader()` will misclassify it.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/net10/Petstore/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/net10/Petstore/src/Org.OpenAPITools/Client/ClientUtils.cs:432">
P1: Content headers allowlist is incomplete: `content-disposition` is missing, so that header can be misclassified and routed to request headers.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/net4.7/OneOf/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/net4.7/OneOf/src/Org.OpenAPITools/Client/ClientUtils.cs:328">
P2: `content-disposition` is a standard content header but is missing from the allowlist, so `IsContentHeader` will misclassify it and route it to request headers instead of `HttpContent.Headers`.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/net4.7/AnyOf/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/net4.7/AnyOf/src/Org.OpenAPITools/Client/ClientUtils.cs:328">
P2: `ContentHeaders` is missing the `content-disposition` content header, so `IsContentHeader()` will misclassify a real `HttpContent` header and can route file-upload headers to the wrong collection.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Client/ClientUtils.cs:428">
P2: Content header allowlist is incomplete (missing `content-disposition`), causing valid content headers to be misclassified and routed incorrectly.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/net4.7/AllOf/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/net4.7/AllOf/src/Org.OpenAPITools/Client/ClientUtils.cs:328">
P2: Content header allowlist is incomplete: `content-disposition` is missing, so `IsContentHeader` can misclassify a valid content header as a request header.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/net4.7/FormModels/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/net4.7/FormModels/src/Org.OpenAPITools/Client/ClientUtils.cs:428">
P2: Missing `Content-Disposition` from the reserved content-header list can misroute a valid content header to `HttpRequestMessage.Headers` instead of `HttpContent.Headers`.</violation>
</file>

<file name="samples/client/petstore/csharp/generichost/latest/OneOfList/src/Org.OpenAPITools/Client/ClientUtils.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/latest/OneOfList/src/Org.OpenAPITools/Client/ClientUtils.cs:318">
P2: `ContentHeaders` whitelist is incomplete: it omits `content-disposition`, causing valid content headers to be misclassified.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 37 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="modules/openapi-generator/src/main/resources/csharp/libraries/generichost/api.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/csharp/libraries/generichost/api.mustache:593">
P1: Routing content headers to `HttpRequestMessage.Content.Headers` can dereference null when the request has no body/content initialized.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

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.

Misused header name 'Content-Range' when generating .NET API client

3 participants