Skip to content

[http-client-csharp] Route nested model reads and writes through ModelReaderWriter proxies #12485

Open

Description

@m-nash

Summary

Generated serialization code reads and writes a nested model by calling that model's own implementation directly. So a ModelReaderWriter proxy registered for the nested type is never consulted, even when it is registered on the options passed in. For proxies to help libraries that substitute types nested inside another library's models, generated code has to route nested reads and writes through them. (System.ClientModel's proxy API is still a prototype: Azure/azure-sdk-for-net#59083.)

Current behavior

Generated code on main, from the Sample-TypeSpec test project:

OpenAI's generated models follow the same pattern, for example StreamingResponseOutputItemAddedUpdate (read, write).

Scenario

Azure.AI.Extensions.OpenAI's ProjectResponsesClient derives from OpenAI's ResponsesClient. It converts Azure-specific response items and tools, which OpenAI's generated discriminator switch can't produce, into Azure types. Today that means overriding the response methods and post-processing their results (streaming override). For streaming, that requires either a hook in OpenAI (openai/openai-dotnet#1473) or Azure re-implementing event parsing.

If generated code honored nested proxies, Azure could register ResponseItem and ResponseTool proxies on its client options. OpenAI's own deserializer would then produce the Azure types in streaming updates and non-streaming results alike.

Request

When proxies are registered on the ModelReaderWriterOptions in use, generated code should resolve them for nested model properties and collection elements, on both the read and the write path. Today's static fast path should stay when no proxies are registered.

Related


🤖 m-nash-copilot

Activity

  1. added
    featureNew feature or request
    emitter:client:csharpIssue for the C# client emitter: @typespec/http-client-csharp
    on Nov 3, 2026
  2. github-actions commented on Nov 3, 2026

    @github-actions
    Contributor

    🎯 Issue Triage

    Generated C# serialization currently bypasses registered ModelReaderWriter proxies for nested model properties and collection elements. This requests proxy-aware nested reads and writes while preserving the existing fast path when no proxies are registered.

    Category: Feature Request

    Area: emitter:client:csharp

    🔍 Analysis

    The affected component is MrwSerializationTypeDefinition in the HTTP client C# generator, including nested scalar and collection serialization paths. Generated reads call the nested model's static deserializer directly, while writes call its IJsonModel.Write implementation, so proxy resolution is skipped even though the enclosing ModelReaderWriterOptions carries registrations.

    #11390 is an open draft PR with substantial overlap: it threads options through generated clients and routes nested reads through proxies. #11913 fixed forwarding reader options for external models, but is related rather than the same request because it does not add nested proxy resolution or the write path.

    The implementation depends on the provisional System.ClientModel proxy API, so its final API shape may affect generator design.

    📝 Suggested next steps
    • Align the generator implementation with the finalized System.ClientModel proxy API.
    • Cover nested scalar, list, and dictionary models on both read and write paths.
    • Verify the static fast path remains unchanged when no proxies are registered.
    • Coordinate with the overlapping work in Thread ModelReaderWriterOptions through generated clients #11390.

    Generated by Agentic Triage

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

emitter:client:csharpIssue for the C# client emitter: @typespec/http-client-csharpfeatureNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions