Skip to content

feat: enable C# emitter in playground with backend server#10346

Open
JoshLove-msft wants to merge 20 commits intomicrosoft:mainfrom
JoshLove-msft:feat/csharp-playground-server
Open

feat: enable C# emitter in playground with backend server#10346
JoshLove-msft wants to merge 20 commits intomicrosoft:mainfrom
JoshLove-msft:feat/csharp-playground-server

Conversation

@JoshLove-msft
Copy link
Copy Markdown
Contributor

@JoshLove-msft JoshLove-msft commented Apr 12, 2026

Fixes #10228

  • Split emitter into emit-generate.ts (Node.js) and emit-generate.browser.ts (browser stub)
  • Browser stub POSTs code model to playground server for generation
  • Created .NET playground server (ASP.NET Core) that runs the generator
  • Added Dockerfile for containerized deployment
  • Pipeline: ACR build + App Service deployment with managed identity
  • Bundle upload to blob storage for browser-side emitter loading
  • Website: added C# to playground with server URL configuration
  • Fix: explicit ValueExpression conversion in spread expressions to prevent SIGSEGV when ParameterProvider is spread into ValueExpression collections

JoshLove-msft and others added 2 commits April 12, 2026 11:36
- Split emitter into emit-generate.ts (Node.js) and emit-generate.browser.ts (browser stub)
- Browser stub POSTs code model to playground server for generation
- Created .NET playground server (ASP.NET Core) that runs the generator
- Added Dockerfile for containerized deployment
- Pipeline: ACR build + App Service deployment with managed identity
- Bundle upload to blob storage for browser-side emitter loading
- Website: added C# to playground with server URL configuration
- Fix: explicit ValueExpression conversion in spread expressions to prevent
  SIGSEGV when ParameterProvider is spread into ValueExpression collections

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ployment

Only add new parameters (PlaygroundBundleBuildScript, PlaygroundServerDockerfile,
PlaygroundServerAppName) and server deployment section. No changes to existing
publish/ESRP pipeline logic.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 12, 2026

Open in StackBlitz

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

commit: cf88a0a

@github-actions
Copy link
Copy Markdown
Contributor

No changes needing a change description found.

@JoshLove-msft
Copy link
Copy Markdown
Contributor Author

Will have a follow up PR for some UX enhancements to show a compiling spinner and change highlighting.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-sdk
Copy link
Copy Markdown
Collaborator

azure-sdk commented Apr 12, 2026

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread packages/http-client-csharp/playground-server/Program.cs
Comment thread eng/emitters/pipelines/templates/stages/emitter-stages.yml
Comment thread eng/emitters/pipelines/templates/stages/emitter-stages.yml Outdated
Comment thread website/src/components/playground-component/playground.tsx Outdated
Comment thread packages/http-client-csharp/playground-server/Dockerfile Outdated
Comment thread packages/http-client-csharp/.dockerignore
- Simplify pipeline: remove Azure resource creation (ACR, plan, webapp,
  identity) since resources already exist manually; keep only ACR build
  and App Service container update
- Move server URL default into browser stub so website doesn't need to
  set globalThis.__TYPESPEC_PLAYGROUND_SERVER_URL__
- Add --no-restore to Dockerfile publish step (restore already done)
- Add **/artifacts/ to .dockerignore
- Add azure.github.io to CORS allowed origins

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread eng/emitters/pipelines/templates/stages/emitter-stages.yml
JoshLove-msft and others added 3 commits April 13, 2026 10:00
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Test default and custom server URL
- Test request body contains codeModel, configuration, generatorName
- Test response files are written to host
- Test error handling on non-OK response
- Test empty files array

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@markcowl markcowl left a comment

Choose a reason for hiding this comment

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

I think we should be able to test changes using the typespec - PR Tools ci checks, so should update that workflow to ensure proper setup

Comment thread packages/http-client-csharp/emitter/src/emit-generate.browser.ts Outdated
JoshLove-msft and others added 3 commits April 13, 2026 15:39
Remove default server URL from browser stub to prevent it from
leaking to third-party sites. The URL must be explicitly set via
globalThis.__TYPESPEC_PLAYGROUND_SERVER_URL__ by the host site.
Moved the URL configuration back to the website playground.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The server URL is hardcoded in the browser stub with no globalThis
fallback. No configuration needed from the website.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@JoshLove-msft
Copy link
Copy Markdown
Contributor Author

I think we should be able to test changes using the typespec - PR Tools ci checks, so should update that workflow to ensure proper setup

Yes, that would capture the website changes, but the emitter changes would need to be published via the emitter pipeline.

JoshLove-msft and others added 5 commits April 13, 2026 15:52
The publish stage didn't set a Node version, defaulting to Node 20
on the agent. The bundle-uploader depends on asset-emitter which
requires Node >=22. Added NodeTool@0 step before the bundle upload.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The publish stage checks out fresh source with the original package.json
version (e.g. 0.1.0). The bundle uploader reads this version for
latest.json. Added a step to apply the build number (e.g.
0.1.0-beta.12345) before bundling, matching Build-Packages.ps1 behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ADO template parser was failing on the inline script. Use the
auto-set BUILD_BUILDNUMBER environment variable instead of the
macro syntax.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
C# emitter sets BuildPrereleaseVersion=true so gets -alpha tag,
matching Build-Packages.ps1 behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

is there any emitter option that allow users to run a post emitting script that would allow a playground user to basically run code on the server?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No, the closest thing is there an option to configure a plugin but the plugin would need to exist on the server.

Server-side (Program.cs):
- Request size limit: 10 MB max body via Kestrel
- Content-Type validation: must be application/json
- JSON parse error handling: returns 400 on invalid JSON
- Subprocess timeout: 5 minutes, kills process tree on timeout (504)
- Security headers: X-Content-Type-Options, X-Frame-Options,
  Referrer-Policy

Client-side (emit-generate.browser.ts):
- Validate response content-type is application/json
- Validate response shape: { files: Array<{ path, content }> }
- Validate each file entry has string path and content

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@JoshLove-msft JoshLove-msft force-pushed the feat/csharp-playground-server branch from c36f99a to 5cb4659 Compare April 15, 2026 02:37
Mock responses now include Headers with content-type to match
the response validation added in the browser stub.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
}

const result: { files: Array<{ path: string; content: string }> } = await response.json();
const contentType = response.headers.get("content-type");
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.

I'm wondering about a limit on response size? content-length is not a great way to police this, but not sure what size quotas are available to use

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added a Content-Length check against a 10 MB limit before parsing the response JSON. As you noted, Content-Length isn't always reliable, but it provides a reasonable guard against obviously oversized responses without buffering the entire body.

-- Generated by Copilot

Checks Content-Length header against a 10 MB limit before parsing
the response JSON to protect against unexpectedly large responses.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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 eng meta:website TypeSpec.io updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(http-client-csharp): Enable C# emitter in the TypeSpec playground

6 participants