diff --git a/14/umbraco-cms/extending-cms/key-vault.md b/14/umbraco-cms/extending-cms/key-vault.md index d1e0d59116b..5c64638ac50 100644 --- a/14/umbraco-cms/extending-cms/key-vault.md +++ b/14/umbraco-cms/extending-cms/key-vault.md @@ -39,25 +39,70 @@ The next step is to add the Azure Key Vault endpoint to the `appsettings.json` f } ``` -After adding the Key Vault endpoint you have to update the `CreateHostBuilder` method which you can find in the `Program.cs` file. +After adding the endpoint in the appsettings, it's time to add configuration so that the KeyVault is used. One way to achieve this is to write an extension method for the `WebApplicationBuilder`: ```csharp -Host.CreateDefaultBuilder(args) - .ConfigureUmbracoDefaults() - .ConfigureAppConfiguration((context, config) => +using System; +using Azure.Identity; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Configuration; +using Umbraco.Cms.Core.DependencyInjection; +using Umbraco.Extensions; + +namespace My.Website; + +public static class WebApplicationBuilderExtensions +{ + public static WebApplicationBuilder ConfigureKeyVault(this WebApplicationBuilder builder) + { + var keyVaultEndpoint = builder.Configuration["AzureKeyVaultEndpoint"]; + if (!string.IsNullOrWhiteSpace(keyVaultEndpoint) && Uri.TryCreate(keyVaultEndpoint, UriKind.Absolute, out var validUri)) + { + builder.Configuration.AddAzureKeyVault(validUri, new DefaultAzureCredential()); + } + + return builder; + } +} +``` + +After creating the extension method, it's possible to call it from the `Program.cs` class, like so: + +```csharp +using Microsoft.AspNetCore.Builder; +using My.Project; +using Umbraco.Cms.Core.DependencyInjection; +using Umbraco.Extensions; + +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); + +builder.ConfigureKeyVault(); + +builder.CreateUmbracoBuilder() + .AddBackOffice() + .AddWebsite() + .AddDeliveryApi() + .AddComposers() + .Build(); + +WebApplication app = builder.Build(); + +await app.BootUmbracoAsync(); + +app.UseUmbraco() + .WithMiddleware(u => { - var settings = config.Build(); - var keyVaultEndpoint = settings["AzureKeyVaultEndpoint"]; - if (!string.IsNullOrEmpty(keyVaultEndpoint) && Uri.TryCreate(keyVaultEndpoint, UriKind.Absolute, out var validUri)) - { - config.AddAzureKeyVault(validUri, new DefaultAzureCredential()); - } + u.UseBackOffice(); + u.UseWebsite(); }) - .ConfigureWebHostDefaults(webBuilder => + .WithEndpoints(u => { - webBuilder.UseStaticWebAssets(); - webBuilder.UseStartup(); + u.UseInstallerEndpoints(); + u.UseBackOfficeEndpoints(); + u.UseWebsiteEndpoints(); }); + +await app.RunAsync(); ``` ### Authentication diff --git a/14/umbraco-cms/extending-cms/language-files.md b/14/umbraco-cms/extending-cms/language-files.md index 67ec2809d53..54c44426218 100644 --- a/14/umbraco-cms/extending-cms/language-files.md +++ b/14/umbraco-cms/extending-cms/language-files.md @@ -7,12 +7,18 @@ description: >- # Language Files & Localization Language files are XML files used to translate: -- The Umbraco backoffice user interface so that end users can use Umbraco in their native language. This is particularly important for content editors who do not speak English. -- The member identity errors in an Umbraco website enabling end users to use Umbraco in the website language. -- Read [Add translations for your packages](packages/language-files-for-packages.md) to see how to include translations for your own package. -- Override existing language files + +* The Umbraco backoffice user interface so that end users can use Umbraco in their native language. This is particularly important for content editors who do not speak English. +* The member identity errors in an Umbraco website enabling end users to use Umbraco in the website language. +* Read [Add translations for your packages](packages/language-files-for-packages.md) to see how to include translations for your own package. +* Override existing language files. + +{% hint style="info" %} +You can use localization files for Document and Media Types as well. You can find more information about this in the [Document Type Localization](../fundamentals/data/defining-content/document-type-localization.md) article. +{% endhint %} This is an example of such a language file, the most important parts are the `alias` fields of the `` and `` elements. This is what you need to retrieve the values from .NET or Angular. + ```xml @@ -91,6 +97,10 @@ If you want to override Umbraco core translations or translations shipped with p /config/lang/{language}.user.xml ``` +{% hint style="info" %} +The `/config/lang/` folders do not exist on a clean installation of the CMS. You will need to create them at the root of your `src` project. +{% endhint %} + By default, these files are empty but you can add any new keys you want or override existing ones with your own translations. The nice part about the user files is that they will not get overwritten by the installer when you upgrade your Umbraco versions. In order for these files to deploy when you do a `dotnet publish`, you need to add the following to your `.csproj` file: diff --git a/14/umbraco-cms/fundamentals/data/creating-media/default-media-types.md b/14/umbraco-cms/fundamentals/data/creating-media/default-media-types.md index c535993e553..288793a1621 100644 --- a/14/umbraco-cms/fundamentals/data/creating-media/default-media-types.md +++ b/14/umbraco-cms/fundamentals/data/creating-media/default-media-types.md @@ -73,3 +73,7 @@ The `UmbracoMediaVideo` media type has the following properties: * `umbracoBytes` - Label (bigint) ![MediaVideo](../../../../../10/umbraco-cms/fundamentals/data/creating-media/images/umbraco-media-video-media-type.png) + +{% hint style="info" %} +You can also create localization files for Media Types. You can read more about this in the [Document Type Localization](../defining-content/document-type-localization.md) article. +{% endhint %} diff --git a/14/umbraco-cms/fundamentals/data/defining-content/document-type-localization.md b/14/umbraco-cms/fundamentals/data/defining-content/document-type-localization.md new file mode 100644 index 00000000000..35d03803933 --- /dev/null +++ b/14/umbraco-cms/fundamentals/data/defining-content/document-type-localization.md @@ -0,0 +1,96 @@ +--- +description: Here you will learn how to apply localization for Document Types in Umbraco. +--- + +# Document Type Localization + +The Umbraco backoffice is fully localized to match the user's [configured language](../users.md). When defining Document Types, you can apply localization to: + +* Document Type names and descriptions. +* Property names and descriptions. +* Custom property validation messages. +* Tab and group names. + +Setting up localization for Document Types is a two-step process: + +* Create the localizations in [user defined language files](../../../extending/language-files.md). +* Apply the localizations to the Document Types. + +{% hint style="info" %} +Everything in this article also applies to defining [Media Types](../creating-media/). +{% endhint %} + +## Creating localizations + +User defined language files are created in `/config/lang` and must be named `{language}.user.xml`. For example: `en-us.user.xml`. + +There are no specific requirements as to how localizations should be structured for use in Document Types. The following localizations have been used for the samples in this article: + +{% code title="en-us.user.xml" lineNumbers="true" %} +```xml + + + + Article page + A textual, article-like page on the site. Use this as the main type of content. + Landing page + An inviting, very graphical page. Use this as an entry point for a campaign, and supplement with Articles. + + + Page content + SEO configuration + + + Page titles + + + Main title + This is the main title of the page. + The main title is required for this page. + Sub title + This is the sub title of the page. + + +``` +{% endcode %} + +{% hint style="info" %} +Umbraco must be restarted to pick up on changes to language files. +{% endhint %} + +## Applying localizations + +The localizations are applied by using the syntax `#{area alias}_{key alias}`. + +1. Create a **Document Type with template** called `#contentTypes_article` with **alias**: `articlePage`. +2. Under the newly created document type follow these steps: + +* Name the **description** to `#contentTypes_article-desc`. +* Create a new **tab** called `#tabs_content`. +* Add a new **group** called `#groups_titles`. +* Add a **property** called `#properties_title` with **alias** `title`. + * Set description to `#properties_title-desc`. + * Use a `TextString` editor. + * Enable to `Set this field as mandatory`. + * Under validation add `#properties_title-message`. + +![Applying localization to a property](../images/localization-document-type-editor-validation.png) + +* Add a **property** called `#properties_subTitle` with **alias** `subTitle`. + * Set description to `#properties_subTitle-desc`. + * Use a `TextString` editor. +* Enable to `Allow as root` in the **Permissions** tab. + +![Applying localization to a Document Type](../images/localization-document-type-editor.png) + +3. When creating and editing the content, you will see that the backoffice now uses the configured localizations. + +![Localized document creation dialog](../images/localization-document-editor-create.png) + +4. Create a new "Article" content: + +![Localized document editing](../images/localization-document-editor.png) + +4. When trying to save the content without adding the mandatory content, you will see a warning as expected: + +![Localized property validation](../images/localization-document-editor-validation.png) diff --git a/14/umbraco-cms/fundamentals/data/images/localization-document-editor-create.png b/14/umbraco-cms/fundamentals/data/images/localization-document-editor-create.png new file mode 100644 index 00000000000..58b02eb6b1c Binary files /dev/null and b/14/umbraco-cms/fundamentals/data/images/localization-document-editor-create.png differ diff --git a/14/umbraco-cms/fundamentals/data/images/localization-document-editor-validation.png b/14/umbraco-cms/fundamentals/data/images/localization-document-editor-validation.png new file mode 100644 index 00000000000..a81ce080608 Binary files /dev/null and b/14/umbraco-cms/fundamentals/data/images/localization-document-editor-validation.png differ diff --git a/14/umbraco-cms/fundamentals/data/images/localization-document-editor.png b/14/umbraco-cms/fundamentals/data/images/localization-document-editor.png new file mode 100644 index 00000000000..c47f8f8bc71 Binary files /dev/null and b/14/umbraco-cms/fundamentals/data/images/localization-document-editor.png differ diff --git a/14/umbraco-cms/fundamentals/data/images/localization-document-type-editor-validation.png b/14/umbraco-cms/fundamentals/data/images/localization-document-type-editor-validation.png new file mode 100644 index 00000000000..d8d55126d03 Binary files /dev/null and b/14/umbraco-cms/fundamentals/data/images/localization-document-type-editor-validation.png differ diff --git a/14/umbraco-cms/fundamentals/data/images/localization-document-type-editor.png b/14/umbraco-cms/fundamentals/data/images/localization-document-type-editor.png new file mode 100644 index 00000000000..c020c7fa757 Binary files /dev/null and b/14/umbraco-cms/fundamentals/data/images/localization-document-type-editor.png differ diff --git a/14/umbraco-cms/implementation/composing.md b/14/umbraco-cms/implementation/composing.md index 7d322076798..c87c633882c 100644 --- a/14/umbraco-cms/implementation/composing.md +++ b/14/umbraco-cms/implementation/composing.md @@ -192,7 +192,7 @@ Below is a list of collections with their corresponding 'collection type' and ho ### Example - Modifying Collections -This example shows how to control which Healthchecks are available to run in the Umbraco backoffice. Create a C# class which implements IUserComposer, the Compose method gives access to the HealthChecks collection of the Umbraco Composition - first we clear all HealthChecks from the collection, then add back in the ones we want to keep: +This example shows how to control which Healthchecks are available to run in the Umbraco backoffice. Create a C# class which implements IComposer, the Compose method gives access to the HealthChecks collection of the Umbraco Composition - first we clear all HealthChecks from the collection, then add back in the ones we want to keep: ```csharp using Umbraco.Cms.Core.Composing; @@ -390,7 +390,7 @@ public static class WebCompositionExtensions => builder.WithCollectionBuilder(); } -public class MyThingComposer : IUserComposer +public class MyThingComposer : IComposer { public void Compose(IUmbracoBuilder builder) { @@ -482,7 +482,7 @@ public static class WebCompositionExtensions => builder.WithCollectionBuilder(); } -public class MyThingComposer : IUserComposer +public class MyThingComposer : IComposer { public void Compose(IUmbracoBuilder builder) { diff --git a/14/umbraco-cms/implementation/custom-routing/README.md b/14/umbraco-cms/implementation/custom-routing/README.md index c2f4c785e25..49c3c0776a0 100644 --- a/14/umbraco-cms/implementation/custom-routing/README.md +++ b/14/umbraco-cms/implementation/custom-routing/README.md @@ -47,7 +47,7 @@ For more detailed information see: [IContentFinder documentation](../../referenc ## Custom MVC routes -You can specify your own custom MVC routes to work within the Umbraco pipeline. It requires your controller to inherit from `UmbracoPageController` and either implement `IVirtualPageController` or use `.ForUmbracoPage` when registering your route, for more information and a complete example of both approaches see [Custom routing documentation](./) +You can specify your own custom MVC routes to work within the Umbraco pipeline. It requires your controller to inherit from `UmbracoPageController` and either implement `IVirtualPageController` or use `.ForUmbracoPage` when registering your route, for more information and a complete example of both approaches see [Custom routing documentation](https://docs.umbraco.com/umbraco-cms/reference/routing/custom-routes#custom-routes-within-the-umbraco-pipeline) An example of registering a `UmbracoPageController` using `.ForUmbracoPage`: diff --git a/14/umbraco-cms/reference/content-delivery-api/README.md b/14/umbraco-cms/reference/content-delivery-api/README.md index 5b07bb6d550..6705b4ed296 100644 --- a/14/umbraco-cms/reference/content-delivery-api/README.md +++ b/14/umbraco-cms/reference/content-delivery-api/README.md @@ -186,7 +186,7 @@ This means that the content item resides under the `docs-portal` root node and c The start item can also be helpful through the `Start-Item` request header when obtaining content from the Delivery API. Supplying a root node `id` or `path` as the header value, allows you to specify which is the starting point for the requested content operation: ```http -GET /umbraco/delivery/api/v1/content/item/articles/2023/getting-started +GET /umbraco/delivery/api/v2/content/item/articles/2023/getting-started Start-Item: docs-portal ``` @@ -194,122 +194,24 @@ Start-Item: docs-portal
-Output expansion +Property expansion and limiting -**Output expansion** allows you to retrieve additional data about related content or media in the API output for a given content item. +Property expansion and limiting allows you to: -By default, a content property that allows picking a different content item (like a content picker property) outputs a shallow representation of the item. That means, only the basic information about the picked item, without the item properties. However, with output expansion, it is possible to include the properties of the picked item in the API output. Similar shallow representation applies to media items, as well. +- Include properties from related content or media in the API output for a given content item. +- Limit the content properties in the API output. -{% hint style="info" %} -Currently, output expansion allows you to retrieve one level of property data from the point of view of the requested content node. This means that you can expand the properties of the chosen content item, but not the properties of other related items within that item. -{% endhint %} - -This feature can be used when querying for both single and multiple content items by adding an `expand` parameter to the query. The value of this parameter can be either `"all"` to expand all properties of the requested content item or `"property:alias, alias, alias"` to expand specific ones. - -The following JSON snippet demonstrates the default output of a content item (without expanding any properties). +By default, a content property that allows picking a different content item (for example a content picker) outputs a "shallow" representation of the picked item. This means that the output only includes basic information about the picked item, without the item properties. -**Request** - -```http -GET /umbraco/delivery/api/v1/content/item/9bdac0e9-66d8-4bfd-bba1-e954ed9c780d -``` - -**Response** - -{% code title="Shallow output for " %} -```json -{ - "name": "My post", - "createDate": "2023-05-11T00:05:31.878211", - "updateDate": "2023-05-15T11:25:53.912058", - "route": {... - }, - "id": "9bdac0e9-66d8-4bfd-bba1-e954ed9c780d", - "contentType": "blogpost1", - "properties": { - "title": "My post page", - "blogPostNumber": 11, - "bodyContent": "Congue, sollicitudin? Est fames maiores, sociis suspendisse et aliquet tristique excepturi, aliquam, nihil illum pretium penatibus exercitationem lacinia! Dolorem tempus convallis, nulla! Eius scelerisque voluptatum penatibus, dignissimos molestiae, soluta eum. Voluptatibus quod? Temporibus potenti voluptates dictumst? Cillum metus, nec asperiores? Impedit sit! Eum tellus cillum facilisis ullamco tempor? Sint nostrum luctus? Neque dictumst diam, minus? Itaque, minus, etiam dignissimos debitis occaecat aptent tempus! Praesent molestiae duis nihil recusandae, eius imperdiet aspernatur natus. Tempus mattis at architecto, augue, consequuntur ultricies eligendi, litora morbi ante nesciunt pretium laoreet quidem recusandae voluptates dapibus, iure sagittis donec ipsum mollit? Blanditiis! Laborum sit assumenda beatae.", - "linkedItem": { - "name": "Demo blog", - "createDate": "2023-05-11T00:26:52.591927", - "updateDate": "2023-05-16T12:43:41.339963", - "route": { - "path": "/demo-blog/", - "startItem": { - "id": "5d5ae914-9885-4ee0-a14b-0ab57f501a55", - "path": "demo-blog" - } - }, - "id": "5d5ae914-9885-4ee0-a14b-0ab57f501a55", - "contentType": "blog", - "properties": {} - } - }, - "cultures": {} -} -``` -{% endcode %} +If we apply property expansion to the content property, the properties of the picked item are included in the output. This functionality applies to media items and block editors, as well. -Below is an example of how an expanded representation might look for the `linkedItem` property that references another content item with properties `title` and `description`: +Property expansion can be applied to expanded properties too, thus obtaining nested property expansion. As a consequence, the output grows in size, and this is where property limiting comes into the picture. -**Request** +By default, all content properties (including expanded properties) are included in the output. Property limiting allows us to specify exactly which content properties to include in the output. This means we can tailor the output specifically to concrete use cases without over-fetching. -```http -GET /umbraco/delivery/api/v1/content/item/9bdac0e9-66d8-4bfd-bba1-e954ed9c780d?expand=property:linkedItem -``` +Property expansion and limiting can be used when querying for both single and multiple content or media items. You can expand properties by adding an `expand` parameter to the query and limit them by the `fields` query parameter. -**Response** - -{% code title="Expanded output for " %} -```json -{ - "name": "My post", - "createDate": "2023-05-11T00:05:31.878211", - "updateDate": "2023-05-15T11:25:53.912058", - "route": { - "path": "/my-post/", - "startItem": { - "id": "5d5ae914-9885-4ee0-a14b-0ab57f501a55", - "path": "demo-blog" - } - }, - "id": "9bdac0e9-66d8-4bfd-bba1-e954ed9c780d", - "contentType": "blogpost1", - "properties": { - "title": "My post page", - "blogPostNumber": 11, - "bodyContent": "Congue, sollicitudin? Est fames maiores, sociis suspendisse et aliquet tristique excepturi, aliquam, nihil illum pretium penatibus exercitationem lacinia! Dolorem tempus convallis, nulla! Eius scelerisque voluptatum penatibus, dignissimos molestiae, soluta eum. Voluptatibus quod? Temporibus potenti voluptates dictumst? Cillum metus, nec asperiores? Impedit sit! Eum tellus cillum facilisis ullamco tempor? Sint nostrum luctus? Neque dictumst diam, minus? Itaque, minus, etiam dignissimos debitis occaecat aptent tempus! Praesent molestiae duis nihil recusandae, eius imperdiet aspernatur natus. Tempus mattis at architecto, augue, consequuntur ultricies eligendi, litora morbi ante nesciunt pretium laoreet quidem recusandae voluptates dapibus, iure sagittis donec ipsum mollit? Blanditiis! Laborum sit assumenda beatae.", - "linkedItem": { - "name": "Demo blog", - "createDate": "2023-05-11T00:26:52.591927", - "updateDate": "2023-05-16T12:43:41.339963", - "route": { - "path": "/demo-blog/", - "startItem": { - "id": "5d5ae914-9885-4ee0-a14b-0ab57f501a55", - "path": "demo-blog" - } - }, - "id": "5d5ae914-9885-4ee0-a14b-0ab57f501a55", - "contentType": "blog", - "properties": { - "title": "My demo blog", - "description": "Nihil incididunt dolores adipisicing placeat quisque imperdiet interdum autem, dolorem fusce rhoncus sunt leo inventore dictumst quisque, voluptatem, magni justo nostrud deserunt! Natus ipsam commodi dignissimos, sodales ab.\n" - } - } - }, - "cultures": {} -} -``` -{% endcode %} - -The built-in property editors in Umbraco that allow for output expansion are: - -* `Umbraco.ContentPicker` -* `Umbraco.MediaPicker` -* `Umbraco.MediaPicker3` -* `Umbraco.MultiNodeTreePicker` +Please refer to [this article](./property-expansion-and-limiting) for an in-depth explanation of this feature.
@@ -320,7 +222,7 @@ The built-in property editors in Umbraco that allow for output expansion are: Similar to the preview concept in Umbraco, the Delivery API allows for requesting unpublished content through its endpoints. This can be done by setting a `Preview` header to `true` in the API request. However, accessing draft versions of your content nodes requires authorization via an API key configured in `appsettings.json` file - `Umbraco:CMS:DeliveryApi:ApiKey` setting. To obtain preview data, you must add the `Api-Key` request header containing the configured API key to the appropriate endpoints, like: ```http -GET /umbraco/delivery/api/v1/content/item/11fb598b-5c51-4d1a-8f2e-0c7594361d15 +GET /umbraco/delivery/api/v2/content/item/11fb598b-5c51-4d1a-8f2e-0c7594361d15 Preview: true Api-Key: my-api-key ``` @@ -336,7 +238,7 @@ Draft content is not going to be included in the JSON response otherwise. If your content is available in multiple languages, the Delivery API can resolve localized content. When querying content by `id`, the `Accept-Language` header can be used to request variant content. ```http -GET /umbraco/delivery/api/v1/content/item/11fb598b-5c51-4d1a-8f2e-0c7594361d15 +GET /umbraco/delivery/api/v2/content/item/11fb598b-5c51-4d1a-8f2e-0c7594361d15 Accept-Language: en-US ``` @@ -352,7 +254,7 @@ The output produced by the Delivery API can either represent a specific content When referring to a specific content item in your API requests, the `id` parameter always refers to the item’s key (GUID) and not its integer node id. {% endhint %} -{% swagger method="get" path="/content/item/{id}" baseUrl="/umbraco/delivery/api/v1" summary="Gets a content item by id" %} +{% swagger method="get" path="/content/item/{id}" baseUrl="/umbraco/delivery/api/v2" summary="Gets a content item by id" %} {% swagger-description %} Returns a single item. {% endswagger-description %} @@ -381,6 +283,10 @@ URL segment or GUID of the root content item Which properties to expand and therefore include in the output if they refer to another piece of content {% endswagger-parameter %} +{% swagger-parameter in="query" name="fields" type="String" required="false" %} +Which properties to include in the response (_by default all properties are included_) +{% endswagger-parameter %} + {% swagger-response status="200: OK" description="Content item" %} {% endswagger-response %} @@ -394,7 +300,7 @@ Which properties to expand and therefore include in the output if they refer to {% endswagger-response %} {% endswagger %} -{% swagger method="get" path="/content/item/{path}" baseUrl="/umbraco/delivery/api/v1" summary="Gets a content item by route" %} +{% swagger method="get" path="/content/item/{path}" baseUrl="/umbraco/delivery/api/v2" summary="Gets a content item by route" %} {% swagger-description %} Returns a single item. {% endswagger-description %} @@ -423,6 +329,10 @@ URL segment or GUID of the root content item Which properties to expand and therefore include in the output if they refer to another piece of content {% endswagger-parameter %} +{% swagger-parameter in="query" name="fields" type="String" required="false" %} +Which properties to include in the response (_by default all properties are included_) +{% endswagger-parameter %} + {% swagger-response status="200: OK" description="Content item" %} {% endswagger-response %} @@ -436,7 +346,7 @@ Which properties to expand and therefore include in the output if they refer to {% endswagger-response %} {% endswagger %} -{% swagger method="get" path="/content/item" baseUrl="/umbraco/delivery/api/v1" summary="Gets content item(s) by id" %} +{% swagger method="get" path="/content/items" baseUrl="/umbraco/delivery/api/v2" summary="Gets content item(s) by id" %} {% swagger-description %} Returns single or multiple items by id. {% endswagger-description %} @@ -465,6 +375,10 @@ URL segment or GUID of the root content item Which properties to expand in the response {% endswagger-parameter %} +{% swagger-parameter in="query" name="fields" type="String" required="false" %} +Which properties to include in the response (_by default all properties are included_) +{% endswagger-parameter %} + {% swagger-response status="200: OK" description="List of content items" %} {% endswagger-response %} @@ -474,7 +388,7 @@ Which properties to expand in the response {% endswagger-response %} {% endswagger %} -{% swagger method="get" path="/content" baseUrl="/umbraco/delivery/api/v1" summary="Gets content item(s) from a query" %} +{% swagger method="get" path="/content" baseUrl="/umbraco/delivery/api/v2" summary="Gets content item(s) from a query" %} {% swagger-description %} Returns single or multiple items. {% endswagger-description %} @@ -519,6 +433,10 @@ URL segment or GUID of the root content item Which properties to expand and therefore include in the output if they refer to another piece of content {% endswagger-parameter %} +{% swagger-parameter in="query" name="fields" type="String" required="false" %} +Which properties to include in the response (_by default all properties are included_) +{% endswagger-parameter %} + {% swagger-response status="200: OK" description="Paginated list of content items" %} {% endswagger-response %} @@ -536,7 +454,7 @@ All endpoints are documented in a Swagger document at `{yourdomain}/umbraco/swag ### Query parameters -The Content Delivery API provides a number of query parameters that allow you to customize the content returned by the API to fit your needs. For each endpoint, the relevant query parameters are already specified within their corresponding documentation above. In addition to standard parameters like `skip` and `take`, the API provides different possibilities for the value of `expand`, `fetch`, `filter` and `sort` parameters. Below are the options supported out of the box. +The Content Delivery API provides a number of query parameters that allow you to customize the content returned by the API to fit your needs. For each endpoint, the relevant query parameters are already specified within their corresponding documentation above. In addition to standard parameters like `skip` and `take`, the API provides different possibilities for the value of `expand`, `fields`, `fetch`, `filter` and `sort` parameters. Below are the options supported out of the box. {% hint style="info" %} You can extend the built-in selector, filter, and sorting capabilities of the Delivery API by creating your own custom query handlers. @@ -545,21 +463,42 @@ You can extend the built-in selector, filter, and sorting capabilities of the De {% tabs %} {% tab title="expand" %} {% hint style="info" %} -Refer to the [Output expansion](./#output-expansion) concept for more information about the benefits of this parameter. +Refer to the [Property expansion and limiting](./#property-expansion-and-limiting) concept for more information about this parameter. {% endhint %} -**`?expand=all`**\ +**`?expand=properties[$all]`**\ All expandable properties on the retrieved content item will be expanded. -**`?expand=property:alias1`**\ +**`?expand=properties[alias1]`**\ A specific expandable property with the property alias _`alias1`_ will be expanded. -**`?expand=property:alias1,alias2,alias3`**\ +**`?expand=properties[alias1,alias2,alias3]`**\ Multiple expandable properties with the specified property aliases will be expanded. + +**`?expand=properties[alias1[properties[nestedAlias1,nestedAlias2]]]`**\ +The property with the property alias _`alias1`_ will be expanded, and likewise the properties _`nestedAlias1`_ and _`nestedAlias2`_ of the expanded _`alias1`_ property. +{% endtab %} + +{% tab title="fields" %} +{% hint style="info" %} +Refer to the [Property expansion and limiting](./#property-expansion-and-limiting) concept for more information about this parameter. +{% endhint %} + +**`?fields=properties[$all]`**\ +Includes all properties of the retrieved content item in the output. + +**`?fields=properties[alias1]`**\ +Includes only the property with the property alias _`alias1`_ in the output. + +**`?fields=properties[alias1,alias2,alias3]`**\ +Includes only the properties with the specified property aliases in the output. + +**`?fields=properties[alias1[properties[nestedAlias1,nestedAlias2]]]`**\ +Includes only the property with the property alias _`alias1`_ in the output. If this property is expanded, only the properties _`nestedAlias1`_ and _`nestedAlias2`_ of the expanded _`alias1`_ property are included in the output. {% endtab %} {% tab title="fetch" %} -To query content items based on their structure, you can apply a selector option to the `/umbraco/delivery/api/v1/content` endpoint. The selector allows you to fetch different subsets of items based on a GUID or path of a specific content item. If no `fetch` parameter is provided, the Delivery API will search across all available content items. The following built-in selectors can be used out-of-the-box: +To query content items based on their structure, you can apply a selector option to the `/umbraco/delivery/api/v2/content` endpoint. The selector allows you to fetch different subsets of items based on a GUID or path of a specific content item. If no `fetch` parameter is provided, the Delivery API will search across all available content items. The following built-in selectors can be used out-of-the-box: **`?fetch=ancestors:id/path`**\ All ancestors of a content item specified by either its _`id`_ or _`path`_ will be retrieved. @@ -579,7 +518,7 @@ For example, the following API call will attempt to retrieve all the content ite **Request** ```http -GET /umbraco/delivery/api/v1/content?fetch=children:dc1f43da-49c6-4d87-b104-a5864eca8152 +GET /umbraco/delivery/api/v2/content?fetch=children:dc1f43da-49c6-4d87-b104-a5864eca8152 ``` {% endtab %} @@ -619,7 +558,7 @@ Multiple filters can be applied to the same request in addition to other query p **Request** ```http -GET /umbraco/delivery/api/v1/content?filter=contentType:article&filter=name:guide&skip=0&take=10 +GET /umbraco/delivery/api/v2/content?filter=contentType:article&filter=name:guide&skip=0&take=10 ``` This technique can also be used to perform range filtering. For example, fetch articles created in 2023: @@ -650,12 +589,12 @@ An option to sort the results based on the sort order of the content item in eit **`?sort=updateDate:asc/desc`**\ An option to sort the results based on the last update date of the content item in either _`asc`_ or _`desc`_ order. -Different sorting options can be combined for the `/umbraco/delivery/api/v1/content` endpoint, allowing for more advanced sorting functionality. Here is an example: +Different sorting options can be combined for the `/umbraco/delivery/api/v2/content` endpoint, allowing for more advanced sorting functionality. Here is an example: **Request** ```http -GET /umbraco/delivery/api/v1/content?sort=name:asc&sort=createDate:asc +GET /umbraco/delivery/api/v2/content?sort=name:asc&sort=createDate:asc ``` {% endtab %} {% endtabs %} diff --git a/14/umbraco-cms/reference/routing/README.md b/14/umbraco-cms/reference/routing/README.md index fc354413bbf..b6afde8b1a8 100644 --- a/14/umbraco-cms/reference/routing/README.md +++ b/14/umbraco-cms/reference/routing/README.md @@ -12,7 +12,7 @@ Explains how Umbraco builds its URLs and how the URLs are mapped back to content ## [Routing Properties](routing-properties.md) -Describes the various Umbraco special/reserved Property Type aliases that can be used to directly manipulate Umbraco's default routing pipeline. These special Property Type aliases can be very useful when creating an Umbraco website. +Describes the Umbraco special/reserved Property Type aliases that can be used to directly manipulate Umbraco's default routing pipeline. These special Property Type aliases can be useful when creating an Umbraco website. ## [Surface Controllers](surface-controllers/) @@ -24,7 +24,7 @@ What is an API Controller and how to use them? ## [Custom Controllers (hijacking routes)](custom-controllers.md) -Creating custom controllers to have 100% full control over how your pages are rendered. AKA: Hijacking Umbraco Routes +Creating custom controllers to have 100% full control over how your pages are rendered. Also known as: Hijacking Umbraco Routes ## [Custom Routes](custom-routes.md) diff --git a/14/umbraco-cms/reference/routing/custom-middleware.md b/14/umbraco-cms/reference/routing/custom-middleware.md index af3073ba694..0a6e4b4205d 100644 --- a/14/umbraco-cms/reference/routing/custom-middleware.md +++ b/14/umbraco-cms/reference/routing/custom-middleware.md @@ -62,6 +62,6 @@ This should return the following:

Browser result image

-An additional bonus is that this doesn't require any changes in your `Startup.cs` file. It also allows packages to enable Cross-Origin Resource Sharing (CORS) and configure their own policies. +An additional bonus is that this doesn't require any changes in your `Program.cs` file. It also allows packages to enable Cross-Origin Resource Sharing (CORS) and configure their own policies. Users that currently use `WithCustomMiddleware()` will need to add calls to `RunPreRouting()` and `RunPostRouting()`. This is similar to Umbraco adding additional middleware in future versions. diff --git a/14/umbraco-cms/reference/routing/request-pipeline/README.md b/14/umbraco-cms/reference/routing/request-pipeline/README.md index cb3d4b5e78a..212435cea18 100644 --- a/14/umbraco-cms/reference/routing/request-pipeline/README.md +++ b/14/umbraco-cms/reference/routing/request-pipeline/README.md @@ -4,13 +4,13 @@ description: What the Umbraco Request Pipeline is # Routing in Umbraco -_This section describes what the Umbraco Request Pipeline is, how Umbraco matches a document to a given request and how it generates a URL for a document._ +_This section describes what the Umbraco Request Pipeline is. It explains how Umbraco matches a document to a given request and how it generates a URL for a document._ ## Request pipeline ### What is the pipeline -The request pipeline is the process of building up the URL for a node, resolving a request to a specified node and making sure that the right content is sent back. +The request pipeline is the process of building up the URL for a node and resolving a request to a specified node. It ensures that the right content is sent back. ![what is the pipeline](../../../../../10/umbraco-cms/reference/routing/request-pipeline/images/what-is-the-pipeline.png) diff --git a/14/umbraco-cms/reference/routing/request-pipeline/icontentfinder.md b/14/umbraco-cms/reference/routing/request-pipeline/icontentfinder.md index d146d152a53..7063ab1de9d 100644 --- a/14/umbraco-cms/reference/routing/request-pipeline/icontentfinder.md +++ b/14/umbraco-cms/reference/routing/request-pipeline/icontentfinder.md @@ -15,7 +15,7 @@ public interface IContentFinder and use either an Umbraco builder extension, or a composer to add it to it to the `ContentFindersCollection`. -Umbraco runs all content finders in the collection 'in order', until one of the IContentFinders returns true, the request is then handled by that finder, and no further IContentFinders are executed. Therefore the order in which ContentFinders are added to the ContentFinderCollection is important. +Umbraco runs all content finders in the collection 'in order', until one of the IContentFinders returns true. Once this occurs, the request is then handled by that finder, and no further IContentFinders are executed. Therefore the order in which ContentFinders are added to the ContentFinderCollection is important. The ContentFinder can set the PublishedContent item for the request, or template or even execute a redirect. diff --git a/14/umbraco-cms/reference/routing/request-pipeline/inbound-pipeline.md b/14/umbraco-cms/reference/routing/request-pipeline/inbound-pipeline.md index 559b27cd07c..f98da3d49bd 100644 --- a/14/umbraco-cms/reference/routing/request-pipeline/inbound-pipeline.md +++ b/14/umbraco-cms/reference/routing/request-pipeline/inbound-pipeline.md @@ -24,7 +24,7 @@ public DomainAndUri Domain { get; } public CultureInfo Culture { get; } ``` -Domain is a DomainAndUri object i.e. a standard Domain plus the fully qualified uri. For example, the Domain may contain "example.com" whereas the Uri will be fully qualified e.g. "https://example.com/". +Domain is a DomainAndUri object that is a standard Domain plus the fully qualified uri. For example, the Domain may contain "example.com" whereas the Uri will be fully qualified for example "https://example.com/". It contains the content to render: @@ -43,9 +43,9 @@ public string GetTemplateAlias { get; } public ITemplate Template {get; } ``` -The published request is created using the `PublishedRequestBuilder` which implements `IPublishedRequestBuilder`, it's only in this builder that it's possible to set values, such as domain, culture, published content, redirects and so on. +The published request is created using the `PublishedRequestBuilder`, which implements `IPublishedRequestBuilder`. It's only in this builder that it's possible to set values, such as domain, culture, published content, redirects, and so on. -You can subscribe to the 'routing request' notification, which is published right after the `PublishedRequestBuilder` has been prepared, but before the request is built, and processed. Here you can modify anything in the request before it is built and processed! e.g. content, template, etc: +You can subscribe to the 'routing request' notification, which is published right after the `PublishedRequestBuilder` has been prepared, but before the request is built, and processed. Here you can modify anything in the request before it is built and processed! For example content, template, etc: ```csharp using Umbraco.Cms.Core.Events; diff --git a/14/umbraco-cms/reference/searching/README.md b/14/umbraco-cms/reference/searching/README.md index 6d49f5cc3a4..123bd76edc0 100644 --- a/14/umbraco-cms/reference/searching/README.md +++ b/14/umbraco-cms/reference/searching/README.md @@ -1,6 +1,6 @@ # Searching -_Search in Umbraco is powered by Examine out of the box, which is a Lucene-based search and index engine for Umbraco. Umbraco provides everything required to have powerful and fast search up and running on your website, but you can also extend or replace the available configuration to exactly match your requirements. This documentation focuses on the Examine implementation._ +_Search in Umbraco is powered by Examine out of the box, which is a Lucene-based search and index engine for Umbraco. Umbraco provides everything required to have powerful and fast search up and running on your website. You can also extend or replace the available configuration to exactly match your requirements. This documentation focuses on the Examine implementation._ ## [Examine](examine/) diff --git a/14/umbraco-cms/reference/searching/examine/README.md b/14/umbraco-cms/reference/searching/examine/README.md index d3635536fe5..b8c4b8f30e7 100644 --- a/14/umbraco-cms/reference/searching/examine/README.md +++ b/14/umbraco-cms/reference/searching/examine/README.md @@ -6,7 +6,7 @@ _Examine uses Lucene as its search and index engine. Searching using Examine wit The Examine documentation is found here [https://shazwazza.github.io/Examine/](https://shazwazza.github.io/Examine/) and the source code repository for Examine is here [https://github.com/Shazwazza/Examine](https://github.com/Shazwazza/Examine). -Examine allows you to index and search data quickly. Examine is a library that sits on top of [Lucene.Net](https://lucenenet.apache.org/), a high performance search engine library. Examine provides APIs to make searching and indexing as straight forward as possible. Umbraco provides a further layer on top, UmbracoExamine, that opens up the Umbraco-specific APIs for indexing and searching content and media out of the box. +Examine allows you to index and search data quickly. Examine is a library that sits on top of [Lucene.Net](https://lucenenet.apache.org/), a high performance search engine library. Examine provides APIs to make searching and indexing as straight forward as possible. Umbraco provides a further layer on top, UmbracoExamine. This opens up the Umbraco-specific APIs for indexing and searching content and media out of the box. Examine is provider based so it is extensible and allows you to configure your own custom indexes if required. The backoffice search in Umbraco also uses this same search engine, so you can trust that you're in good hands. diff --git a/14/umbraco-cms/reference/searching/examine/examine-manager.md b/14/umbraco-cms/reference/searching/examine/examine-manager.md index 4c44d231e60..3334994d864 100644 --- a/14/umbraco-cms/reference/searching/examine/examine-manager.md +++ b/14/umbraco-cms/reference/searching/examine/examine-manager.md @@ -33,7 +33,7 @@ This returns an active instance of the ExamineManager which exposes operations s ## Searching -Important to note that the `Search` methods on the ExamineManager will call the Search methods of the **default** search provider specified in config. If you want to search using a specified provider, you can retrieve it from the `SearchProviderCollection` (see example below). +It's important to highlight that the `Search` methods on the ExamineManager will call the Search methods of the **default** search provider specified in config. If you wish to search using a specified provider, you can retrieve it from the `SearchProviderCollection` (see example below). You can access any of the searchers by their name, for example: diff --git a/14/umbraco-cms/reference/security/README.md b/14/umbraco-cms/reference/security/README.md index 600a6ab42f9..6b63681a13e 100644 --- a/14/umbraco-cms/reference/security/README.md +++ b/14/umbraco-cms/reference/security/README.md @@ -38,7 +38,7 @@ Out of the box Umbraco ships with a custom ASP.NET Core Identity implementation ### [External login providers](external-login-providers.md) -The Umbraco users and members supports external login providers (OAuth) for performing authentication of your users/members. This could be any OpenIDConnect provider such as Azure Active Directory, Identity Server, Google or Facebook. +The Umbraco users and members supports external login providers (OAuth) for performing authentication of your users/members. This could be any OpenIDConnect provider such as Entra ID/Azure Active Directory, Identity Server, Google or Facebook. ### [Two-factor authentication](two-factor-authentication.md) diff --git a/14/umbraco-cms/reference/security/external-login-providers.md b/14/umbraco-cms/reference/security/external-login-providers.md index 10daf6231bc..1252779cc59 100644 --- a/14/umbraco-cms/reference/security/external-login-providers.md +++ b/14/umbraco-cms/reference/security/external-login-providers.md @@ -6,7 +6,7 @@ description: >- # External login providers -Both the Umbraco backoffice users and website members support external login providers (OAuth) for performing authentication. This could be any OpenIDConnect provider such as Azure Active Directory, Identity Server, Google, or Facebook. +Both the Umbraco backoffice users and website members support external login providers (OAuth) for performing authentication. This could be any OpenIDConnect provider such as Entra ID/Azure Active Directory, Identity Server, Google, or Facebook. {% hint style="info" %} Unlike previous major releases of Umbraco the use of the Identity Extensions package is no longer required. @@ -23,8 +23,8 @@ Install an appropriate Nuget package for the provider you wish to use. Some popu ## Try it out -{% content-ref url="../../tutorials/add-azure-active-directory-authentication.md" %} -[configuration](../../tutorials/add-azure-active-directory-authentication.md) +{% content-ref url="../../tutorials/add-microsoft-entra-id-authentication.md" %} +[configuration](../../tutorials/add-microsoft-entra-id-authentication.md) {% endcontent-ref %} {% content-ref url="../../tutorials/add-google-authentication.md" %} @@ -433,6 +433,7 @@ template.innerHTML = ` }
+

My Company's Provider

If you have signed up with MyProvider, you can sign in to Umbraco by clicking the button below.

@@ -453,6 +454,7 @@ export class MyCustomView extends HTMLElement { connectedCallback() { this.shadowRoot.querySelector('form').setAttribute('action', this.externalLoginUrl); + this.shadowRoot.querySelector('input[name="provider"]').setAttribute('value', this.providerName); } } diff --git a/14/umbraco-cms/reference/security/two-factor-authentication.md b/14/umbraco-cms/reference/security/two-factor-authentication.md index fec099f9839..cda029a3265 100644 --- a/14/umbraco-cms/reference/security/two-factor-authentication.md +++ b/14/umbraco-cms/reference/security/two-factor-authentication.md @@ -195,9 +195,7 @@ Umbraco controls how the UI is for user login and user edits, but will still nee In the following example, we will use the [GoogleAuthenticator NuGet Package](https://www.nuget.org/packages/GoogleAuthenticator/). Despite the name, this package works for both Google and Microsoft authenticator apps. It can be used to generate the QR code needed to activate the app for the website. ```csharp -using System; using System.Runtime.Serialization; -using System.Threading.Tasks; using Google.Authenticator; using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Core.Security; diff --git a/14/umbraco-cms/tutorials/add-google-authentication.md b/14/umbraco-cms/tutorials/add-google-authentication.md index 87157718662..94b59c7d704 100644 --- a/14/umbraco-cms/tutorials/add-google-authentication.md +++ b/14/umbraco-cms/tutorials/add-google-authentication.md @@ -6,7 +6,7 @@ description: >- # Add Google Authentication (Users) -The Umbraco Backoffice supports external login providers (OAuth) for performing authentication of your users. This could be any OpenIDConnect provider such as Azure Active Directory, Identity Server, Google, or Facebook. +The Umbraco Backoffice supports external login providers (OAuth) for performing authentication of your users. This could be any OpenIDConnect provider such as Entra ID/Azure Active Directory, Identity Server, Google, or Facebook. In this tutorial, we will take you through the steps of setting up a Google login for the Umbraco CMS backoffice. diff --git a/14/umbraco-cms/tutorials/add-microsoft-entra-id-authentication.md b/14/umbraco-cms/tutorials/add-microsoft-entra-id-authentication.md new file mode 100644 index 00000000000..04c459f5b23 --- /dev/null +++ b/14/umbraco-cms/tutorials/add-microsoft-entra-id-authentication.md @@ -0,0 +1,180 @@ +--- +description: >- + Learn how to use Microsoft Entra ID (Azure Active Directory) credentials to login to Umbraco as a + member. +--- + +# Add Microsoft Entra ID (Azure Active Directory) authentication (Members) + +This tutorial takes you through configuring Microsoft Entra ID (Azure Active Directory/Azure AD) for the member login on your Umbraco CMS website. + +{% hint style="warning" %} +Entra ID conflicts with Umbraco ID which is the main authentication method used on all Umbraco Cloud projects. + +Due to this, we **highly recommend not using Azure AD for backoffice authentication on your Umbraco Cloud projects**. + +It is still possible to use other [External Login Providers](../reference/security/external-login-providers.md) like Google Auth and OpenIdConnect, with Umbraco Cloud. +{% endhint %} + +## Prerequisites + +* A project with a setup for Members. +* Visual Studio, or another Integrated Development Environment (IDE). + +## Step 1: Configure Entra ID + +Before your applications can interact with Entra ID B2C, they must be registered with a tenant that you manage. For more information, see [Microsoft's Tutorial: Create an Azure Active Directory B2C tenant](https://learn.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-tenant). + +## Step 2: Install the NuGet package + +You need to install the `Microsoft.AspNetCore.Authentication.MicrosoftAccount` NuGet package. There are two approaches to installing the packages: + +1. Use your favorite Integrated Development Environment (IDE) and open up the **NuGet Package Manager** to search and install the packages. +2. Use the command line to install the package. + +## Step 3: Implement the Entra ID Authentication + +1. Create a new class for custom configuration options: `EntraIDB2CMembersExternalLoginProviderOptions.cs`. + +{% code title="EntraIDB2CMembersExternalLoginProviderOptions.cs" lineNumbers="true" %} +```csharp +using Microsoft.Extensions.Options; +using Umbraco.Cms.Core; +using Umbraco.Cms.Web.Common.Security; + +namespace MyApp; + +public class EntraIDB2CMembersExternalLoginProviderOptions : IConfigureNamedOptions +{ + public const string SchemeName = "ActiveDirectoryB2C"; + + public void Configure(string? name, MemberExternalLoginProviderOptions options) + { + if (name != Constants.Security.MemberExternalAuthenticationTypePrefix + SchemeName) + { + return; + } + + Configure(options); + } + + public void Configure(MemberExternalLoginProviderOptions options) + { + // The following options are relevant if you + // want to configure auto-linking on the authentication. + options.AutoLinkOptions = new MemberExternalSignInAutoLinkOptions( + + // Set to true to enable auto-linking + autoLinkExternalAccount: true, + + // [OPTIONAL] + // Default: The culture specified in appsettings.json. + // Specify the default culture to create the Member as. + // It can be dynamically assigned in the OnAutoLinking callback. + defaultCulture: null, + + // [OPTIONAL] + // Specify the default "IsApproved" status. + // Must be true for auto-linking. + defaultIsApproved: true, + + // [OPTIONAL] + // Default: "Member" + // Specify the Member Type alias. + defaultMemberTypeAlias: Constants.Security.DefaultMemberTypeAlias + + ) + { + // [OPTIONAL] Callbacks + OnAutoLinking = (autoLinkUser, loginInfo) => + { + // Customize the Member before it's linked. + // Modify the Members groups based on the Claims returned + // in the external login info. + }, + OnExternalLogin = (user, loginInfo) => + { + // Customize the Member before it is saved whenever they have + // logged in with the external provider. + // Sync the Members name based on the Claims returned + // in the external login info + + // Returns a boolean indicating if sign-in should continue or not. + return true; + } + }; + } +} +``` +{% endcode %} + +2. Create a new static extension class called `MemberAuthenticationExtensions.cs`. + +{% code title="MemberAuthenticationExtensions.cs" lineNumbers="true" %} +```csharp +namespace MyApp; + +public static class MemberAuthenticationExtensions +{ + public static IUmbracoBuilder ConfigureAuthenticationMembers(this IUmbracoBuilder builder) + { + builder.Services.ConfigureOptions(); + builder.AddMemberExternalLogins(logins => + { + builder.Services.ConfigureOptions(); + builder.AddMemberExternalLogins(logins => + { + logins.AddMemberLogin( + membersAuthenticationBuilder => + { + membersAuthenticationBuilder.AddMicrosoftAccount( + + // The scheme must be set with this method to work for the external login. + membersAuthenticationBuilder.SchemeForMembers(EntraIDB2CMembersExternalLoginProviderOptions.SchemeName), + options => + { + // Callbackpath: Represents the URL to which the browser should be redirected to. + // The default value is /signin-oidc. + // This needs to be unique. + options.CallbackPath = "/umbraco-b2c-members-signin"; + + //Obtained from the ENTRA ID B2C WEB APP + options.ClientId = "YOURCLIENTID"; + //Obtained from the ENTRA ID B2C WEB APP + options.ClientSecret = "YOURCLIENTSECRET"; + + options.SaveTokens = true; + }); + }); + }); + }); + return builder; + }); + } +} +``` +{% endcode %} + +{% hint style="info" %} +Ensure to replace `YOURCLIENTID` and `YOURCLIENTSECRET` in the code with the values from the Entra ID tenant. +{% endhint %} + +4. Add the Members authentication configuration in the `Program.cs` file: + +{% code title="Program.cs" lineNumbers="true" %} +```csharp +builder.CreateUmbracoBuilder() + .AddBackOffice() + .AddWebsite() + .AddDeliveryApi() + .AddComposers() + //Add Members ConfigureAuthentication + .ConfigureAuthenticationMembers() + .Build(); +``` +{% endcode %} + +5. Build the project. +6. Run the website. + +![Entra ID Login Screen](<../../../10/umbraco-cms/reference/security/images/AD\_Login\_Members (1).png>) diff --git a/14/umbraco-cms/tutorials/custom-error-page.md b/14/umbraco-cms/tutorials/custom-error-page.md index 4536a08e510..c2df632824d 100644 --- a/14/umbraco-cms/tutorials/custom-error-page.md +++ b/14/umbraco-cms/tutorials/custom-error-page.md @@ -204,7 +204,7 @@ To **test this locally**, in Visual Studio replace `app.UseDeveloperExceptionPag #### Trigger a 500 error -You can trigger a simple 500 error on your frontend by changing a Model.Value property in your template. For example, on a document type with a property called `test`. The way to render it in the frontend would be `Model.Value("test");` To trigger a 500 error page you can add anything after Value such as `Model.ValueTest("test");` +You can trigger a 500 error on your frontend by changing a Model.Value property in your template. For example, on a Document Type with a property called `test`. The way to render it in the frontend would be `Model.Value("test");` To trigger a 500 error page you can add anything after Value such as `Model.ValueTest("test");` ## Maintenance Page diff --git a/14/umbraco-cms/tutorials/getting-started-with-entity-framework-core.md b/14/umbraco-cms/tutorials/getting-started-with-entity-framework-core.md index ab38fbef082..bedfd4a63db 100644 --- a/14/umbraco-cms/tutorials/getting-started-with-entity-framework-core.md +++ b/14/umbraco-cms/tutorials/getting-started-with-entity-framework-core.md @@ -1,5 +1,4 @@ --- - meta.Title: Umbraco Database description: >- This tutorial will show you how to get started with creating custom database @@ -96,10 +95,16 @@ We need to register the `DbContext` to be able to use it in Umbraco. To do this we can use this helpful extension method: ```csharp -services.AddUmbracoEFCoreContext("{YOUR CONNECTIONSTRING HERE}", "{YOUR PROVIDER NAME HERE}"); +builder.Services.AddUmbracoDbContext(options => +{ + options.UseSqlServer("{YOUR CONNECTIONSTRING HERE}"); + //If you are using SQlite, replace UseSqlServer with UseSqlite +}); ``` -Add the method in the `Program.cs` file: +If you are using SQlite, replace `UseSqlServer` with `UseSqlite`. + +1. Add the method in the `Program.cs` file: ```csharp builder.CreateUmbracoBuilder() @@ -109,18 +114,21 @@ builder.CreateUmbracoBuilder() .AddComposers() .Build(); -builder.Services.AddUmbracoEFCoreContext("{YOUR CONNECTIONSTRING HERE}", "{YOUR PROVIDER NAME HERE}"); +builder.Services.AddUmbracoDbContext(options => +{ + options.UseSqlServer("{YOUR CONNECTIONSTRING HERE}"); + //If you are using SQlite, replace UseSqlServer with UseSqlite +}); ``` -{% hint style="warning" %} -The registration of the `DbContext` must be done after the `AddUmbraco` method, but only if your connection string contains "|DataDirectory|". -This is because we cannot translate the "|DataDirectory|" part of the connection string to the correct path until the Umbraco environment has been initialized. -{% endhint %} - We can then access the database via the `BlogContext.` First, we need to migrate the database to add our tables. With EFCore, we can autogenerate the migrations with the terminal. -1. Open your terminal and navigate to your project folder -2. Generate the migration by running `dotnet ef migrations add InitialCreate --context BlogContext` +2. Open your terminal and navigate to your project folder. +3. Generate the migration by running: + +```bash +dotnet ef migrations add InitialCreate --context BlogContext +``` {% hint style="warning" %} In this example, we have named the migration `InitialCreate`. However, you can choose the name you like. @@ -128,8 +136,6 @@ In this example, we have named the migration `InitialCreate`. However, you can c We've named the DbContext class`BlogContext`, however, if you have renamed it to something else, make sure to also change it when running the command. {% endhint %} -You should now have a `Migrations` folder in your project, containing the `InitialCreate` migration (or the name of your choice). - {% hint style="warning" %} This might be confusing at first, as when working with EFCore you would inject your `Context` class. You can still do that, it is however not the recommended approach in Umbraco.