Skip to content

[http-client-csharp] Fix spread model parameter matching to use wire name#10111

Merged
JoshLove-msft merged 4 commits into
microsoft:mainfrom
JoshLove-msft:fix/spread-model-null-params
Mar 23, 2026
Merged

[http-client-csharp] Fix spread model parameter matching to use wire name#10111
JoshLove-msft merged 4 commits into
microsoft:mainfrom
JoshLove-msft:fix/spread-model-null-params

Conversation

@JoshLove-msft
Copy link
Copy Markdown
Contributor

@JoshLove-msft JoshLove-msft commented Mar 22, 2026

Problem

When generating convenience methods with spread model construction, parameters were matched between the convenience method and the model constructor by C# name. This fails when:

  • @clientName\ renames a property (e.g., spec name \model\ → C# name \OverrideModelName)
  • @Encodedname\ wire names leak into parameter names (e.g., \ ool_resources\ vs \ oolResources)
  • PascalCase vs camelCase differences between the convenience parameter and constructor parameter

Unmatched parameters fell back to \default\ (null), causing \NullReferenceException\ during serialization when \Optional.IsCollectionDefined(null)\ returns \ rue\ for null collections.

This was discovered while migrating \Azure.AI.Agents.Persistent\ to the new @azure-typespec/http-client-csharp\ emitter — 172 out of 261 tests failed with NRE in serialization.

Fix

Match spread parameters by their wire (serialized) name (\WireInfo.SerializedName) instead of C# name. Both the convenience parameter and model constructor parameter share the same wire name since they represent the same JSON field. Uses \TryAdd\ to handle potential duplicate wire names gracefully.

Validation

  • Generator builds with 0 errors
  • Regenerated \Azure.AI.Agents.Persistent\ \ThreadRuns.cs\ — all spread parameters now properly forwarded (previously 5 parameters were \default, now only \�dditionalBinaryDataProperties\ is \default\ which is correct)

@microsoft-github-policy-service microsoft-github-policy-service Bot added the emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp label Mar 22, 2026
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Mar 22, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/http-client-csharp@10111

commit: a65a97c

@github-actions
Copy link
Copy Markdown
Contributor

No changes needing a change description found.

When constructing spread models in convenience methods, the parameter
matching between convenience method parameters and model constructor
parameters used C# names which can diverge due to:
- @clientName renames (e.g., 'model' -> 'OverrideModelName')
- @Encodedname wire names leaking (e.g., 'tool_resources' vs 'toolResources')
- PascalCase vs camelCase differences

This caused unmatched parameters to fall back to 'default' (null),
leading to NullReferenceException during serialization when
Optional.IsCollectionDefined(null) returns true for null collections.

Fix: match by the property's wire (serialized) name, which is stable
across both the convenience parameter and the model property since
they represent the same JSON field.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@JoshLove-msft JoshLove-msft force-pushed the fix/spread-model-null-params branch from 875c063 to 6eb86ca Compare March 22, 2026 19:23
@JoshLove-msft JoshLove-msft changed the title fix: use case-insensitive matching for spread model parameter lookup [http-client-csharp] Fix spread model parameter matching to use wire name Mar 22, 2026
…hing

Move the TryGetValue into the if condition directly so the compiler
can track that convenienceParam is definitely assigned when used.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
JoshLove-msft and others added 2 commits March 23, 2026 11:18
The Sample-TypeSpec test project now correctly forwards the 'name'
parameter in spread model construction instead of using 'default'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The wire-name-only matching fails for cases where the constructor
parameter's Property.WireInfo is not available (e.g., in unit tests
using mock models). Add a fallback that matches by C# name
(case-insensitive) when wire name matching doesn't find a match.

Matching order:
1. Wire name (handles @clientName, @Encodedname, casing differences)
2. C# name (handles simple cases and parameters without wire info)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@JoshLove-msft JoshLove-msft force-pushed the fix/spread-model-null-params branch from de5193d to a65a97c Compare March 23, 2026 19:20
@JoshLove-msft JoshLove-msft added this pull request to the merge queue Mar 23, 2026
Merged via the queue into microsoft:main with commit 096443e Mar 23, 2026
25 checks passed
@JoshLove-msft JoshLove-msft deleted the fix/spread-model-null-params branch March 23, 2026 20:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants