microsoft/scaffolding-yarp-proxy-project
> Scaffolds a new ASP.NET Core project with YARP reverse proxy alongside an existing .NET Framework MVC or WebAPI project for incremental side-by-side migration. Use when a migration task requires creating a new Core project that proxies to the old Framework app, when the side-by-side migration approach is selected, or when scaffold/YARP/proxy setup is needed. Also triggers for "create new Core project", "set up YARP proxy", "side-by-side project setup".
npx skills add https://github.com/microsoft/upgrade-agent-plugins --skill scaffolding-yarp-proxy-project
Creates a new ASP.NET Core web project alongside an existing .NET Framework
MVC or WebAPI project. The new project is configured with a YARP reverse proxy
that routes unhandled requests to the old project, enabling incremental
controller-by-controller migration.
This file contains 2 steps and 10 sub-steps for manual scaffolding. You MUST read all sections before starting:
| Step | Section | What It Covers |
|------|---------|----------------|
| 1 | Check for Existing Tool | Try scaffold_yarp_proxy_web_project tool first |
| 2 | Scaffold Using Script + Templates | Primary path — script + template files |
| 2.1 | Gather Parameters | Paths, TFM, URLs, package versions |
| 2.2 | Run the Script | Script copies templates, adds to solution, links projects |
| 2.3 | If Script Fails | Manual fallback — copy templates, replace placeholders |
| - | Template Files Reference | What each template contains |
| - | Success Criteria | Final checklist |
Do not stop reading after Step 1. If the tool is unavailable, you need Steps 2.1–2.10.
Before using this skill, you need:
net10.0){OldProjectName}.Core)First, check if scaffold_yarp_proxy_web_project tool is available in your
environment. If it is, use it — it handles everything automatically:
scaffold_yarp_proxy_web_project(
solutionPath="{solution_path}",
projectPath="{old_project_path}",
targetFramework="{tfm}",
targetProjectName="{new_name}",
projectType="{MVC|WebAPI}"
)
If the tool is not available or fails, proceed with Step 2.
This skill includes template files and a PowerShell script that handles the mechanical work.
The LLM handles the parts that need judgment (finding the old app URL, resolving package versions).
All parameters are mandatory. The new project will not work correctly with the
old project unless every value is accurate. Do not use defaults without verifying them.
Before running the script, determine these values:
| Parameter | How to find it |
|-----------|---------------|
| OldProjectPath | Full path to the .NET Framework .csproj |
| SolutionPath | Full path to the .sln/.slnx file |
| TargetFramework | Upgrade TFM (e.g., net10.0) |
| NewProjectName | Name for new project (default: {OldName}.Core). Must be unique in the solution — check existing project names and folder names |
| ProjectType | MVC or WebAPI — match the old project's type |
| OldAppUrl | Must be the actual URL the old app runs on. Find it in the old project's Properties/launchSettings.json (look for applicationUrl in the active profile), or in IIS/IIS Express bindings. Do NOT guess — if the proxy points to the wrong URL, all forwarded requests will fail silently. |
| SystemWebAdaptersVersion | Use get_supported_package_version for Microsoft.AspNetCore.SystemWebAdapters.CoreServices |
| YarpVersion | Use get_supported_package_version for Yarp.ReverseProxy |
NewProjectName validation:
{parent_of_old_project}/{NewProjectName} must not already existThe script copies template files from tmpl/mvc/ or tmpl/webapi/, applies
variable substitutions ($TargetFramework$, $ProjectName$, $OldAppUrl$, etc.),
adds the project to the solution, links the old project via _MigrateToProjectGuid,
and verifies the build.
{skill_path}/scaffold-project.ps1 `
-OldProjectPath "{OLD_PROJECT_PATH}" `
-SolutionPath "{SOLUTION_PATH}" `
-TargetFramework "{TFM}" `
-NewProjectName "{NEW_PROJECT_NAME}" `
-ProjectType "{MVC|WebAPI}" `
-OldAppUrl "{OLD_APP_URL}" `
-SystemWebAdaptersVersion "{VERSION}" `
-YarpVersion "{VERSION}"
If the script cannot be executed (e.g., PowerShell not available, permissions issue),
do the steps manually. The template files in tmpl/mvc/ and tmpl/webapi/
contain the exact file contents — copy them to the new project folder and replace
the $placeholder$ variables:
| Placeholder | Replace with |
|-------------|-------------|
| $TargetFramework$ | Target framework (e.g., net10.0) |
| $SystemWebAdaptersVersion$ | Package version from get_supported_package_version |
| $YarpVersion$ | Package version from get_supported_package_version |
| $ProjectName$ | New project name |
| $HttpsPort$ | HTTPS port (pick 7100-7999, avoid old project's ports) |
| $HttpPort$ | HTTP port (pick 5100-5999, avoid old project's ports) |
| $NewPort$ | IIS Express HTTP port (pick 60000-65000) |
| $NewSslPort$ | IIS Express SSL port (pick 44300-44399) — in launchSettings.json this placeholder is quoted ("sslPort": "$NewSslPort$") so the template stays valid JSON; after substituting, remove the surrounding quotes so sslPort stays a JSON number, e.g. "sslPort": 44355 |
| $OldAppUrl$ | Old app's URL (e.g., https://localhost:44319) |
Then manually:
ProjectName.csproj to {NewProjectName}.csprojdotnet sln "{SOLUTION_PATH}" add "{NEW_PROJECT_PATH}"<_MigrateToProjectGuid>{GUID}</_MigrateToProjectGuid> to the old project's .csprojdotnet build to verifytmpl/
mvc/ ← For MVC projects
ProjectName.csproj ← SDK-style web project with YARP + SystemWebAdapters packages
Program.cs ← AddControllersWithViews + YARP forwarder + UseStaticFiles
appsettings.json ← Includes ProxyTo key
appsettings.Development.json
Properties/
launchSettings.json ← ProxyTo in environmentVariables
webapi/ ← For WebAPI projects
ProjectName.csproj ← Same packages, no Swashbuckle
Program.cs ← AddControllers + YARP forwarder (no UseStaticFiles)
appsettings.json
appsettings.Development.json
Properties/
launchSettings.json
Key things the templates set up:
builder.Services.AddSystemWebAdapters() — System.Web compatibility shimsbuilder.Services.AddHttpForwarder() — YARP forwarder registrationapp.UseSystemWebAdapters() — middleware for adapter supportapp.MapForwarder("/{**catch-all}", ...) — catch-all route at lowest priority, forwards unmatched requests to old appProxyTo keyProxyTo pointing to the verified old app URL_MigrateToProjectGuid property pointing to new projectIf the scaffolded project doesn't work, tell the user to check:
| Symptom | Likely cause | Fix |
|---------|-------------|-----|
| Proxy returns 502/connection refused | ProxyTo URL is wrong or old app isn't running | Verify URL in launchSettings.json matches old app's actual URL; start old app first |
| New project won't build | Wrong TFM or package versions | Check TargetFramework matches installed SDK; verify package versions are compatible |
| Requests not forwarded | YARP middleware not registered | Check Program.cs has AddHttpForwarder() and MapForwarder() |
| Controllers return 404 | Routes not configured | Ensure MapDefaultControllerRoute() (MVC) or MapControllers() (WebAPI) is in Program.cs |
| _MigrateToProjectGuid missing | Script couldn't find GUID in solution | Manually find the project GUID in .sln/.slnx and add the property to old .csproj |
Take microsoft/scaffolding-yarp-proxy-project from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.