Skip to content

Templates: Update Umbraco extension template for OpenAPI route changes#22670

Merged
lauraneto merged 3 commits into
v18/devfrom
v18/task/update-extension-template-openapi
May 4, 2026
Merged

Templates: Update Umbraco extension template for OpenAPI route changes#22670
lauraneto merged 3 commits into
v18/devfrom
v18/task/update-extension-template-openapi

Conversation

@lauraneto

@lauraneto lauraneto commented May 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #21058 (the Microsoft.AspNetCore.OpenApi migration). The UmbracoExtension dotnet template was not updated as part of that PR, so a freshly scaffolded extension hits several issues against a v18 site.

This PR fixes:

  • The generate-client URL in Client/package.json and the example URL in Client/scripts/generate-openapi.js to use the new /umbraco/openapi/{name}.json route. Also renames swaggerUrl to openApiUrl, updates the related log strings for consistency, and replaces outdated "Swagger" terminology in UmbracoExtensionApiComposer.cs comments.
  • An explicit ShouldInclude predicate on OpenApiOptions in UmbracoExtensionApiComposer.cs, filtering by the MapToApi attribute that's already on the extension's controller base. Without it, Microsoft.AspNetCore.OpenApi's default predicate filters by ApiExplorer.GroupName matching the document name, which doesn't match for the template's setup, so the custom document was created but stayed empty (paths: []), making npm run generate-client produce an empty TypeScript SDK.
  • A direct dependency on Microsoft.AspNetCore.OpenApi in the Central package management mode of the extension template (Umbraco.Extension.csproj and Directory.Packages.props). The PerProject mode already had this, but Central mode did not, so default Central scaffolds failed to build with the source-generator interceptors error.

Testing

End-to-end test requires a running Umbraco 18 site with the extension loaded. Quickest path is to pack everything locally and scaffold a fresh site and extension from the updated templates:

  1. From the repo root, pack the solution: dotnet pack umbraco.sln -c Release -o ./packages.
  2. Install the templates from the local pack: dotnet new install ./packages/Umbraco.Templates.18.0.0--*.nupkg.
  3. Create a scratch directory for the test project, then drop a NuGet.config in it that points at <repo>/packages alongside nuget.org.
  4. From the scratch directory, scaffold the site: dotnet new umbraco -n MyTestSite --development-database-type SQLite --friendly-name "Test Admin" --email admin@test.local --password "Test1234!@#".
  5. Scaffold the extension: dotnet new umbraco-extension -n MyTestExtension.
  6. In MyTestExtension/Client/package.json, set @umbraco-cms/backoffice to ^17.3.5 (no v18 release on npm yet) and update the URL in the generate-client script to match the port you'll run the site on (e.g. https://localhost:44339).
  7. From MyTestSite: dotnet add reference ../MyTestExtension/MyTestExtension.csproj, then dotnet build, then dotnet run --urls https://localhost:44339 (matching the port from step 6).
  8. Confirm https://localhost:44339/umbraco/openapi/mytestextension.json returns 200 with the ping endpoint under paths, and https://localhost:44339/umbraco/swagger/mytestextension/swagger.json returns 404.
  9. In MyTestExtension/Client, run npm install, npm run generate-client, npm run build. All three should succeed.

lauraneto added 2 commits May 1, 2026 11:50
Following the migration from Swashbuckle to Microsoft.AspNetCore.OpenApi
in #21058, the extension template still pointed at the old Swagger URL
pattern and used outdated terminology in code comments.

- generate-client npm script now points at /umbraco/openapi/{name}.json
  instead of /umbraco/swagger/{name}/swagger.json
- generate-openapi.js renames swaggerUrl to openApiUrl and updates the
  example URL in the missing-argument error message
- UmbracoExtensionApiComposer.cs comments updated from "Swagger" to
  "OpenAPI"
Without an explicit ShouldInclude predicate, Microsoft.AspNetCore.OpenApi
only includes endpoints whose ApiExplorer GroupName equals the document
name. The template's controller declared a different group name, so the
custom document was created but stayed empty (paths: []), which in turn
made npm run generate-client produce an empty TypeScript SDK.

Filter by the [MapToApi] attribute already present on the extension's
controller base, mirroring the pattern used by the Management and
Delivery API options.
@lauraneto lauraneto force-pushed the v18/task/update-extension-template-openapi branch from 7193594 to 9117b27 Compare May 1, 2026 12:42
The PerProject mode of the umbraco-extension template took a direct
dependency on Microsoft.AspNetCore.OpenApi (with a long comment
explaining why) but the Central mode did not, so default Central
scaffolds failed to build with the source-generator interceptors
error. Mirror the dependency in the Central csproj block and
Directory.Packages.props.
@lauraneto lauraneto marked this pull request as ready for review May 1, 2026 13:44
Copilot AI review requested due to automatic review settings May 1, 2026 13:44
@claude

claude Bot commented May 1, 2026

Copy link
Copy Markdown

Claude finished @lauraneto's task in 3m 41s —— View job


PR Review

Target: origin/v18/dev · Based on commit: 6ca37128

Updates the UmbracoExtension scaffolding template to align with the OpenAPI route and library changes from #21058, fixing three distinct runtime/build failures that affected freshly scaffolded extensions against a v18 site.

  • Other changes: Scaffolded extensions now generate TypeScript clients against /umbraco/openapi/{name}.json (previously /umbraco/swagger/{name}/swagger.json), and npm run generate-client now correctly populates the generated client (the custom OpenAPI document was previously empty due to the missing ShouldInclude predicate). Central package management scaffolds now compile without the source-generator interceptors error.

Suggestions

  • Composers/UmbracoExtensionApiComposer.cs:45–48: The ShouldInclude lambda is correct, but the EndpointMetadata.OfType<MapToApiAttribute>().Any(...) pattern is an inline re-implementation of what actionDescriptor.HasMapToApiAttribute(Constants.ApiName) already does (from Umbraco.Cms.Api.Common.Extensions). Using the extension method would shorten the predicate to one line and stay consistent with how the rest of the Umbraco infrastructure filters endpoints. Worth considering if you'd like template consumers to see the established helper:
    // requires: using Umbraco.Cms.Api.Common.Extensions;
    options.ShouldInclude = apiDescription =>
        apiDescription.ActionDescriptor.HasMapToApiAttribute(Constants.ApiName);
    (The existing implementation is also correct and is slightly more robust if multiple MapToApi attributes were ever stacked, so this is purely stylistic.)

Approved

This looks good to be merged as-is, but please do a manual sanity check and testing before merging.


Copilot AI left a comment

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.

Pull request overview

Updates the UmbracoExtension template to match Umbraco v18’s Microsoft OpenAPI document generation and routing, ensuring newly scaffolded extensions can generate a usable OpenAPI document and TypeScript client.

Changes:

  • Update template OpenAPI spec URLs from /umbraco/swagger/.../swagger.json to /umbraco/openapi/{name}.json and align terminology/naming.
  • Add an explicit OpenApiOptions.ShouldInclude predicate so the template’s custom document includes the extension endpoints.
  • Add an explicit Microsoft.AspNetCore.OpenApi dependency for both CPM and non-CPM template modes.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
templates/UmbracoExtension/Umbraco.Extension.csproj Adds explicit Microsoft.AspNetCore.OpenApi reference (and reorders package refs) to avoid transitive version mismatches in generated extensions.
templates/UmbracoExtension/Directory.Packages.props Pins Microsoft.AspNetCore.OpenApi for CPM-based scaffolds.
templates/UmbracoExtension/Composers/UmbracoExtensionApiComposer.cs Switches comments to OpenAPI terminology and adds ShouldInclude filtering by MapToApi.
templates/UmbracoExtension/Client/scripts/generate-openapi.js Renames swaggerUrlopenApiUrl and updates example/spec URL to the new OpenAPI route.
templates/UmbracoExtension/Client/package.json Updates generate-client script to call the new /umbraco/openapi/{name}.json endpoint.

Comment thread templates/UmbracoExtension/Composers/UmbracoExtensionApiComposer.cs
Comment thread templates/UmbracoExtension/Client/scripts/generate-openapi.js
Comment thread templates/UmbracoExtension/Client/scripts/generate-openapi.js
Comment thread templates/UmbracoExtension/Composers/UmbracoExtensionApiComposer.cs
@claude claude Bot added the area/backend label May 1, 2026

@AndyButland AndyButland left a comment

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.

This tests out as described (thanks for the effort in providing the clear steps).

I had a suggestion for the issue you commented on, but I'm not sure it's necessary - happy for you to decide whether to update or just leave it as you have it.

@lauraneto lauraneto merged commit 4e74e33 into v18/dev May 4, 2026
48 checks passed
@lauraneto lauraneto deleted the v18/task/update-extension-template-openapi branch May 4, 2026 10:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants