Skip to content

Commit 7b13e23

Browse files
lauranetoclaude
andauthored
Templating: Creating a doctype with template now yields a strongly typed template (closes #20443) (#20688)
* Adjust the document type creation flow so that a template can be created for a content type Add id, name and alias to the request payload to allow creating multiple templates for the same document type Small adjustments Remove unused import and unnecessary async Switched content type template creation to content type controller Missing constant export # Conflicts: # src/Umbraco.Web.UI.Client/src/packages/core/backend-api/sdk.gen.ts * Add default implementation for CreateForContentTypeAsync * Small adjustments from code review * Introduce InvalidTemplateAlias content type operation status * Add tests for CreateTemplateAsync and fix alias validation - Add integration tests for ContentTypeService.CreateTemplateAsync: - Success case with template association - NotFound status for non-existent content type - InvalidTemplateAlias for empty and too-long aliases - Default template assignment verification - Fix bug in TemplateService.CreateAsync where alias validation occurred after GetViewContent call, causing ArgumentNullException for invalid aliases instead of returning InvalidAlias status 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]> --------- Co-authored-by: Claude Opus 4.5 <[email protected]>
1 parent 8c187a6 commit 7b13e23

File tree

22 files changed

+750
-49
lines changed

22 files changed

+750
-49
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using Asp.Versioning;
2+
using Microsoft.AspNetCore.Http;
3+
using Microsoft.AspNetCore.Mvc;
4+
using Umbraco.Cms.Api.Management.Controllers.Template;
5+
using Umbraco.Cms.Api.Management.ViewModels.DocumentType;
6+
using Umbraco.Cms.Core;
7+
using Umbraco.Cms.Core.Security;
8+
using Umbraco.Cms.Core.Services;
9+
using Umbraco.Cms.Core.Services.OperationStatus;
10+
11+
namespace Umbraco.Cms.Api.Management.Controllers.DocumentType;
12+
13+
[ApiVersion("1.0")]
14+
public class CreateDocumentTypeTemplateController : DocumentTypeControllerBase
15+
{
16+
private readonly IContentTypeService _contentTypeService;
17+
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
18+
19+
public CreateDocumentTypeTemplateController(
20+
IContentTypeService contentTypeService,
21+
IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
22+
{
23+
_contentTypeService = contentTypeService;
24+
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
25+
}
26+
27+
[HttpPost("{id:guid}/template")]
28+
[MapToApiVersion("1.0")]
29+
[ProducesResponseType(StatusCodes.Status201Created)]
30+
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
31+
public async Task<IActionResult> CreateTemplate(
32+
CancellationToken cancellationToken,
33+
Guid id,
34+
CreateDocumentTypeTemplateRequestModel requestModel)
35+
{
36+
Attempt<Guid?, ContentTypeOperationStatus> result = await _contentTypeService.CreateTemplateAsync(
37+
id,
38+
requestModel.Name,
39+
requestModel.Alias,
40+
requestModel.IsDefault,
41+
CurrentUserKey(_backOfficeSecurityAccessor));
42+
43+
return result.Success
44+
? CreatedAtId<ByKeyTemplateController>(controller => nameof(controller.ByKey), result.Result!.Value)
45+
: OperationStatusResult(result.Status);
46+
}
47+
}

src/Umbraco.Cms.Api.Management/Controllers/DocumentType/DocumentTypeControllerBase.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ status is ContentTypeOperationStatus.Success
4141
.WithTitle("Invalid property type alias")
4242
.WithDetail("One or more property type aliases are invalid")
4343
.Build()),
44+
ContentTypeOperationStatus.InvalidTemplateAlias => new BadRequestObjectResult(problemDetailsBuilder
45+
.WithTitle("Invalid template alias")
46+
.WithDetail("The specified template alias is invalid")
47+
.Build()),
4448
ContentTypeOperationStatus.PropertyTypeAliasCannotEqualContentTypeAlias => new BadRequestObjectResult(problemDetailsBuilder
4549
.WithTitle("Invalid property type alias")
4650
.WithDetail("The property type alias cannot be the same as the content type alias")

src/Umbraco.Cms.Api.Management/OpenApi.json

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5597,6 +5597,137 @@
55975597
]
55985598
}
55995599
},
5600+
"/umbraco/management/api/v1/document-type/{id}/template": {
5601+
"post": {
5602+
"tags": [
5603+
"Document Type"
5604+
],
5605+
"operationId": "PostDocumentTypeByIdTemplate",
5606+
"parameters": [
5607+
{
5608+
"name": "id",
5609+
"in": "path",
5610+
"required": true,
5611+
"schema": {
5612+
"type": "string",
5613+
"format": "uuid"
5614+
}
5615+
}
5616+
],
5617+
"requestBody": {
5618+
"content": {
5619+
"application/json": {
5620+
"schema": {
5621+
"oneOf": [
5622+
{
5623+
"$ref": "#/components/schemas/CreateDocumentTypeTemplateRequestModel"
5624+
}
5625+
]
5626+
}
5627+
},
5628+
"text/json": {
5629+
"schema": {
5630+
"oneOf": [
5631+
{
5632+
"$ref": "#/components/schemas/CreateDocumentTypeTemplateRequestModel"
5633+
}
5634+
]
5635+
}
5636+
},
5637+
"application/*+json": {
5638+
"schema": {
5639+
"oneOf": [
5640+
{
5641+
"$ref": "#/components/schemas/CreateDocumentTypeTemplateRequestModel"
5642+
}
5643+
]
5644+
}
5645+
}
5646+
}
5647+
},
5648+
"responses": {
5649+
"201": {
5650+
"description": "Created",
5651+
"headers": {
5652+
"Umb-Generated-Resource": {
5653+
"description": "Identifier of the newly created resource",
5654+
"schema": {
5655+
"type": "string",
5656+
"description": "Identifier of the newly created resource"
5657+
}
5658+
},
5659+
"Location": {
5660+
"description": "Location of the newly created resource",
5661+
"schema": {
5662+
"type": "string",
5663+
"description": "Location of the newly created resource",
5664+
"format": "uri"
5665+
}
5666+
},
5667+
"Umb-Notifications": {
5668+
"description": "The list of notifications produced during the request.",
5669+
"schema": {
5670+
"type": "array",
5671+
"items": {
5672+
"$ref": "#/components/schemas/NotificationHeaderModel"
5673+
},
5674+
"nullable": true
5675+
}
5676+
}
5677+
}
5678+
},
5679+
"400": {
5680+
"description": "Bad Request",
5681+
"headers": {
5682+
"Umb-Notifications": {
5683+
"description": "The list of notifications produced during the request.",
5684+
"schema": {
5685+
"type": "array",
5686+
"items": {
5687+
"$ref": "#/components/schemas/NotificationHeaderModel"
5688+
},
5689+
"nullable": true
5690+
}
5691+
}
5692+
},
5693+
"content": {
5694+
"application/json": {
5695+
"schema": {
5696+
"oneOf": [
5697+
{
5698+
"$ref": "#/components/schemas/ProblemDetails"
5699+
}
5700+
]
5701+
}
5702+
}
5703+
}
5704+
},
5705+
"401": {
5706+
"description": "The resource is protected and requires an authentication token"
5707+
},
5708+
"403": {
5709+
"description": "The authenticated user does not have access to this resource",
5710+
"headers": {
5711+
"Umb-Notifications": {
5712+
"description": "The list of notifications produced during the request.",
5713+
"schema": {
5714+
"type": "array",
5715+
"items": {
5716+
"$ref": "#/components/schemas/NotificationHeaderModel"
5717+
},
5718+
"nullable": true
5719+
}
5720+
}
5721+
}
5722+
}
5723+
},
5724+
"security": [
5725+
{
5726+
"Backoffice-User": [ ]
5727+
}
5728+
]
5729+
}
5730+
},
56005731
"/umbraco/management/api/v1/document-type/allowed-at-root": {
56015732
"get": {
56025733
"tags": [
@@ -37580,6 +37711,28 @@
3758037711
},
3758137712
"additionalProperties": false
3758237713
},
37714+
"CreateDocumentTypeTemplateRequestModel": {
37715+
"required": [
37716+
"alias",
37717+
"isDefault",
37718+
"name"
37719+
],
37720+
"type": "object",
37721+
"properties": {
37722+
"alias": {
37723+
"minLength": 1,
37724+
"type": "string"
37725+
},
37726+
"name": {
37727+
"minLength": 1,
37728+
"type": "string"
37729+
},
37730+
"isDefault": {
37731+
"type": "boolean"
37732+
}
37733+
},
37734+
"additionalProperties": false
37735+
},
3758337736
"CreateFolderRequestModel": {
3758437737
"required": [
3758537738
"name"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System.ComponentModel.DataAnnotations;
2+
3+
namespace Umbraco.Cms.Api.Management.ViewModels.DocumentType;
4+
5+
public class CreateDocumentTypeTemplateRequestModel
6+
{
7+
[Required]
8+
public required string Alias { get; set; }
9+
10+
[Required]
11+
public required string Name { get; set; }
12+
13+
public bool IsDefault { get; set; }
14+
}

0 commit comments

Comments
 (0)