Skip to content

Commit

Permalink
V14: Reintroduce umbraco api controller as obsolete (#16263)
Browse files Browse the repository at this point in the history
* Revert "v14: Remove mentions of UmbracoApiController (#15863)"

This reverts commit 30e2dea.

* Obsolete UmbracoApiController

* Added a few more obsoletion messages

* Removed some of the reintroduced stuff again

* Add obsoletion to FrontEndRoutes controller

---------

Co-authored-by: kjac <kja@umbraco.dk>
  • Loading branch information
bergmania and kjac authored May 13, 2024
1 parent b4b512d commit 87c7347
Show file tree
Hide file tree
Showing 17 changed files with 581 additions and 9 deletions.
16 changes: 11 additions & 5 deletions src/Umbraco.Cms.Api.Management/Routing/BackOfficeAreaRoutes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ namespace Umbraco.Cms.Api.Management.Routing;
/// </summary>
public sealed class BackOfficeAreaRoutes : IAreaRoutes
{
private readonly GlobalSettings _globalSettings;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IRuntimeState _runtimeState;
private readonly string _umbracoPathSegment;

Expand All @@ -32,10 +30,18 @@ public BackOfficeAreaRoutes(
IHostingEnvironment hostingEnvironment,
IRuntimeState runtimeState)
{
_globalSettings = globalSettings.Value;
_hostingEnvironment = hostingEnvironment;
_runtimeState = runtimeState;
_umbracoPathSegment = _globalSettings.GetUmbracoMvcArea(_hostingEnvironment);
_umbracoPathSegment = globalSettings.Value.GetUmbracoMvcArea(hostingEnvironment);
}

[Obsolete("Use non-obsolete constructor. This will be removed in Umbraco 15.")]
public BackOfficeAreaRoutes(
IOptions<GlobalSettings> globalSettings,
IHostingEnvironment hostingEnvironment,
IRuntimeState runtimeState,
UmbracoApiControllerTypeCollection apiControllers) : this(globalSettings, hostingEnvironment, runtimeState)
{

}

/// <inheritdoc />
Expand Down
12 changes: 12 additions & 0 deletions src/Umbraco.Core/UmbracoApiControllerTypeCollection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Umbraco.Cms.Core.Composing;

namespace Umbraco.Cms.Core;

[Obsolete("This will be removed in Umbraco 15.")]
public class UmbracoApiControllerTypeCollection : BuilderCollectionBase<Type>
{
public UmbracoApiControllerTypeCollection(Func<IEnumerable<Type>> items)
: base(items)
{
}
}
10 changes: 10 additions & 0 deletions src/Umbraco.Web.Common/Attributes/UmbracoApiControllerAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Umbraco.Cms.Web.Common.ApplicationModels;

namespace Umbraco.Cms.Web.Common.Attributes;


[AttributeUsage(AttributeTargets.Class)]
[Obsolete("No-op attribute. Will be removed in Umbraco 15.")]
public sealed class UmbracoApiControllerAttribute : Attribute
{
}
26 changes: 26 additions & 0 deletions src/Umbraco.Web.Common/Controllers/UmbracoApiController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Umbraco.Cms.Core.Composing;

namespace Umbraco.Cms.Web.Common.Controllers;

/// <summary>
/// Provides a base class for auto-routed Umbraco API controllers.
/// </summary>
[Obsolete("""
WARNING
The UmbracoAPIController does not work exactly as in previous versions of Umbraco because serialization is now done using System.Text.Json.
Please verify your API responses still work as expect.
We recommend using regular ASP.NET Core ApiControllers for your APIs so that OpenAPI specifications are generated.
Read more about this here: https://learn.microsoft.com/en-us/aspnet/core/web-api/
UmbracoAPIController will be removed in Umbraco 15.
""")]
public abstract class UmbracoApiController : UmbracoApiControllerBase, IDiscoverable
{
/// <summary>
/// Initializes a new instance of the <see cref="UmbracoApiController" /> class.
/// </summary>
protected UmbracoApiController()
{
}
}
27 changes: 27 additions & 0 deletions src/Umbraco.Web.Common/Controllers/UmbracoApiControllerBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core.Features;
using Umbraco.Cms.Web.Common.Attributes;
using Umbraco.Cms.Web.Common.Authorization;

namespace Umbraco.Cms.Web.Common.Controllers;

/// <summary>
/// Provides a base class for Umbraco API controllers.
/// </summary>
/// <remarks>
/// <para>These controllers are NOT auto-routed.</para>
/// <para>The base class is <see cref="ControllerBase" /> which are netcore API controllers without any view support</para>
/// </remarks>
[Authorize(Policy = AuthorizationPolicies.UmbracoFeatureEnabled)]
[UmbracoApiController]
[Obsolete("This will be removed in Umbraco 15.")]
public abstract class UmbracoApiControllerBase : ControllerBase, IUmbracoFeature
{
/// <summary>
/// Initializes a new instance of the <see cref="UmbracoApiControllerBase" /> class.
/// </summary>
protected UmbracoApiControllerBase()
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Composing;

namespace Umbraco.Cms.Web.Common.Controllers;

[Obsolete("This will be removed in Umbraco 15.")]
public class UmbracoApiControllerTypeCollectionBuilder : TypeCollectionBuilderBase<
UmbracoApiControllerTypeCollectionBuilder, UmbracoApiControllerTypeCollection, UmbracoApiController>
{
protected override UmbracoApiControllerTypeCollectionBuilder This => this;
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
using Umbraco.Cms.Web.Common.AspNetCore;
using Umbraco.Cms.Web.Common.Blocks;
using Umbraco.Cms.Web.Common.Configuration;
using Umbraco.Cms.Web.Common.Controllers;
using Umbraco.Cms.Web.Common.DependencyInjection;
using Umbraco.Cms.Web.Common.FileProviders;
using Umbraco.Cms.Web.Common.Helpers;
Expand Down Expand Up @@ -287,6 +288,10 @@ public static IUmbracoBuilder AddWebComponents(this IUmbracoBuilder builder)
builder.Services.AddUnique<IUmbracoContextFactory, UmbracoContextFactory>();
builder.Services.AddUnique<IBackOfficeSecurityAccessor, BackOfficeSecurityAccessor>();

var umbracoApiControllerTypes = builder.TypeLoader.GetUmbracoApiControllers().ToList();
builder.WithCollectionBuilder<UmbracoApiControllerTypeCollectionBuilder>()
.Add(umbracoApiControllerTypes);

builder.Services.AddSingleton<UmbracoRequestLoggingMiddleware>();
builder.Services.AddSingleton<PreviewAuthenticationMiddleware>();
builder.Services.AddSingleton<UmbracoRequestMiddleware>();
Expand Down
52 changes: 52 additions & 0 deletions src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,36 @@ namespace Umbraco.Extensions;

public static class LinkGeneratorExtensions
{
/// <summary>
/// Return the Url for a Web Api service
/// </summary>
/// <typeparam name="T">The <see cref="UmbracoApiControllerBase" /></typeparam>
[Obsolete("This will be removed in Umbraco 15.")]
public static string? GetUmbracoApiService<T>(this LinkGenerator linkGenerator, string actionName, object? id = null)
where T : UmbracoApiControllerBase => linkGenerator.GetUmbracoControllerUrl(
actionName,
typeof(T),
new Dictionary<string, object?> { ["id"] = id });

[Obsolete("This will be removed in Umbraco 15.")]
public static string? GetUmbracoApiService<T>(this LinkGenerator linkGenerator, string actionName, IDictionary<string, object?>? values)
where T : UmbracoApiControllerBase => linkGenerator.GetUmbracoControllerUrl(actionName, typeof(T), values);

[Obsolete("This will be removed in Umbraco 15.")]
public static string? GetUmbracoApiServiceBaseUrl<T>(
this LinkGenerator linkGenerator,
Expression<Func<T, object?>> methodSelector)
where T : UmbracoApiControllerBase
{
MethodInfo? method = ExpressionHelper.GetMethodInfo(methodSelector);
if (method == null)
{
throw new MissingMethodException("Could not find the method " + methodSelector + " on type " + typeof(T) +
" or the result ");
}

return linkGenerator.GetUmbracoApiService<T>(method.Name)?.TrimEnd(method.Name);
}

/// <summary>
/// Return the Url for an Umbraco controller
Expand Down Expand Up @@ -101,4 +131,26 @@ public static class LinkGeneratorExtensions

return linkGenerator.GetUmbracoControllerUrl(actionName, ControllerExtensions.GetControllerName(controllerType), area, values);
}

[Obsolete("This will be removed in Umbraco 15.")]
public static string? GetUmbracoApiService<T>(
this LinkGenerator linkGenerator,
Expression<Func<T, object>> methodSelector)
where T : UmbracoApiController
{
MethodInfo? method = ExpressionHelper.GetMethodInfo(methodSelector);
IDictionary<string, object?>? methodParams = ExpressionHelper.GetMethodParams(methodSelector);
if (method == null)
{
throw new MissingMethodException(
$"Could not find the method {methodSelector} on type {typeof(T)} or the result ");
}

if (methodParams?.Any() == false)
{
return linkGenerator.GetUmbracoApiService<T>(method.Name);
}

return linkGenerator.GetUmbracoApiService<T>(method.Name, methodParams);
}
}
13 changes: 13 additions & 0 deletions src/Umbraco.Web.Common/Extensions/TypeLoaderExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Web.Common.Controllers;

namespace Umbraco.Extensions;

public static class TypeLoaderExtensions
{
/// <summary>
/// Gets all types implementing <see cref="UmbracoApiController" />.
/// </summary>
public static IEnumerable<Type> GetUmbracoApiControllers(this TypeLoader typeLoader)
=> typeLoader.GetTypes<UmbracoApiController>();
}
Loading

0 comments on commit 87c7347

Please sign in to comment.