Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V14: Reintroduce umbraco api controller as obsolete #16263

Merged
merged 6 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading