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

Upgrade to work with Umbraco 9.0.0+ / net5.0+ #30

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -250,4 +250,8 @@ Cached/
build/_nuget
src/Our.Umbraco.AuthU.TestHarness
src/Our.Umbraco.AuthU.Web
src/Our.Umbraco.AuthU.Matt.*
src/Our.Umbraco.AuthU.Matt.*

# Ignore umbraco folders restored by nuget
src/Our.Umbraco.HeadRest/wwwroot/umbraco
src/Our.Umbraco.HeadRest/umbraco
17 changes: 0 additions & 17 deletions src/Our.Umbraco.HeadRest/Composing/HeadRestComponent.cs

This file was deleted.

24 changes: 11 additions & 13 deletions src/Our.Umbraco.HeadRest/Composing/HeadRestComposer.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
using Our.Umbraco.HeadRest.Mapping;
using Microsoft.Extensions.DependencyInjection;
using Our.Umbraco.HeadRest.Mapping;
using Our.Umbraco.HeadRest.Web.Routing;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Mapping;
using Umbraco.Web.Routing;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Routing;

namespace Our.Umbraco.HeadRest.Composing
{
public class HeadRestComposer : IUserComposer
public class HeadRestComposer : IComposer
{
public void Compose(Composition composition)
public void Compose(IUmbracoBuilder builder)
{
composition.WithCollectionBuilder<UrlProviderCollectionBuilder>()
builder.WithCollectionBuilder<UrlProviderCollectionBuilder>()
.InsertBefore<DefaultUrlProvider, HeadRestUrlProvider>();

composition.WithCollectionBuilder<MapDefinitionCollectionBuilder>()
builder.WithCollectionBuilder<MapDefinitionCollectionBuilder>()
.Add<HeadRestMapDefinition>();

composition.Register<HeadRest>();

composition.Components()
.Append<HeadRestComponent>();
builder.Services.AddTransient<HeadRest>();
}
}
}
110 changes: 82 additions & 28 deletions src/Our.Umbraco.HeadRest/HeadRest.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
using System;
using System.Web.Routing;
using System.Collections.Concurrent;
using Umbraco.Web;
using Umbraco.Core;
using Our.Umbraco.HeadRest.Web.Routing;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using Our.Umbraco.HeadRest.Interfaces;
using Our.Umbraco.HeadRest.Web.Controllers;
using Umbraco.Core.Mapping;
using Our.Umbraco.HeadRest.Web.Models;
using Our.Umbraco.HeadRest.Web.Routing;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Web.Common.ApplicationBuilder;
using Umbraco.Extensions;

namespace Our.Umbraco.HeadRest
{
Expand All @@ -18,48 +25,54 @@ public class HeadRest

internal static ConcurrentDictionary<string, HeadRestConfig> Configs = new ConcurrentDictionary<string, HeadRestConfig>();

private readonly UmbracoMapper _mapper;

public HeadRest(UmbracoMapper mapper)
=> _mapper = mapper;

public void ConfigureEndpoint(HeadRestOptions options)
public void ConfigureEndpoint(IUmbracoBuilder builder, HeadRestOptions options)
{
ConfigureEndpoint("/", "/root/*[@isDoc][1]", options);
ConfigureEndpoint("/", "/root/*[@isDoc][1]", builder, options);
}

public void ConfigureEndpoint(string basePath, HeadRestOptions options)
public void ConfigureEndpoint(string basePath, IUmbracoBuilder builder, HeadRestOptions options)
{
ConfigureEndpoint(basePath, "/root/*[@isDoc][1]", options);
ConfigureEndpoint(basePath, "/root/*[@isDoc][1]", builder, options);
}

public void ConfigureEndpoint(string basePath, string rootNodeXPath, HeadRestOptions options)
public void ConfigureEndpoint(string basePath, string rootNodeXPath, IUmbracoBuilder builder, HeadRestOptions options)
{
var config = _mapper.Map<HeadRestConfig>(options);
var config = new HeadRestConfig(options);
config.BasePath = basePath;
config.RootNodeXPath = rootNodeXPath;
ConfigureEndpoint(config);
ConfigureEndpoint(builder, config);
}

private void ConfigureEndpoint(HeadRestConfig config)
private void ConfigureEndpoint(IUmbracoBuilder builder, HeadRestConfig config)
{
ValidateConfig(config);

if (!Configs.ContainsKey(config.BasePath))
{
if (Configs.TryAdd(config.BasePath, config))
{
RouteTable.Routes.MapUmbracoRoute(
$"HeadRest_{config.BasePath.Trim('/').Replace("/", "_")}",
config.BasePath.EnsureEndsWith("/").TrimStart("/") + "{*"+ RoutePathKey + "}",
new
// from https://docs.umbraco.com/umbraco-cms/reference/routing/custom-routes
builder.Services.Configure<UmbracoPipelineOptions>(options =>
{
var controllerName = config.ControllerType.Name;
options.AddFilter(new UmbracoPipelineFilter(controllerName)
{
controller = config.ControllerType.Name.TrimEnd("Controller"),
action = "Index",
headRestConfig = config
},
new HeadRestRouteHandler(config),
new { path = new UmbracoRoutesConstraint() });
Endpoints = app => app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
$"HeadRest_{config.BasePath.Trim('/').Replace("/", "_")}",
config.BasePath.EnsureEndsWith("/").TrimStart("/") + "{*" + RoutePathKey + "}",
new
{
controller = config.ControllerType.Name.TrimEnd("Controller"),
action = "Index",
headRestConfig = config
},
constraints: new { path = new UmbracoRoutesConstraint() }
).ForUmbracoPage(FindContent);
})
});
});
}
}
}
Expand All @@ -76,5 +89,46 @@ private static void ValidateConfig(HeadRestConfig config)
throw new Exception("ViewModelMappings can not be null");
}
}

private static IPublishedContent FindContent(ActionExecutingContext actionExecutingContext)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been moved from the old HeadRestRouteHandler

{
var config = actionExecutingContext.RouteData.Values[HeadRest.ControllerConfigKey] as IHeadRestConfig;

var nodeXPath = config.RootNodeXPath;

if (actionExecutingContext.RouteData?.Values != null)
{
if (actionExecutingContext.RouteData.Values.ContainsKey(HeadRest.RoutePathKey)
&& actionExecutingContext.RouteData.Values[HeadRest.RoutePathKey] != null)
{
var path = actionExecutingContext.RouteData.Values[HeadRest.RoutePathKey].ToString();

// Check for a configured custom route
if (config.CustomRouteMappings != null)
{
var match = config.CustomRouteMappings.GetRouteMapFor(path);
if (match != null)
{
path = match.Target;

actionExecutingContext.RouteData.Values.Add(HeadRest.RouteMapMatchKey, match);
}
}

// Construct xpath from path
var pathParts = path.Trim('/').Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var pathPart in pathParts)
{
nodeXPath += $"/*[@urlName='{pathPart}'][1]";
}
}
}

var ctx = actionExecutingContext.HttpContext.RequestServices.GetRequiredService<IUmbracoContextAccessor>();

var node = ctx.GetRequiredUmbracoContext().Content.GetSingleByXPath(nodeXPath);

return node ?? new NotFoundPublishedContent();
}
}
}
11 changes: 11 additions & 0 deletions src/Our.Umbraco.HeadRest/HeadRestConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ namespace Our.Umbraco.HeadRest
{
internal class HeadRestConfig : HeadRestOptions, IHeadRestConfig
{
public HeadRestConfig() { }

public HeadRestConfig(HeadRestOptions options) : base()
{
Mode = options.Mode;
ControllerType = options.ControllerType;
Mapper = options.Mapper;
ViewModelMappings = options.ViewModelMappings;
CustomRouteMappings = options.CustomRouteMappings;
}

public string BasePath { get; set; }
public string RootNodeXPath { get; set; }
}
Expand Down
17 changes: 10 additions & 7 deletions src/Our.Umbraco.HeadRest/HeadRestOptions.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using NPoco;
using Our.Umbraco.HeadRest.Interfaces;
using Our.Umbraco.HeadRest.Web.Controllers;
using Our.Umbraco.HeadRest.Web.Mapping;
using Our.Umbraco.HeadRest.Web.Routing;
using Umbraco.Core.Composing;
using Umbraco.Core.Mapping;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Extensions;

namespace Our.Umbraco.HeadRest
{
Expand All @@ -21,7 +23,9 @@ public HeadRestOptions()
{
Mode = HeadRestEndpointMode.Dedicated;
ControllerType = typeof(HeadRestController);
Mapper = (ctx) => {
Mapper = (ctx) =>
{
var mapper = ctx.HttpContext.RequestServices.GetRequiredService<IUmbracoMapper>();

// Currently have to call the UmbracoMapper.Map function
// via reflection as there are no non-generic versions
Expand All @@ -30,8 +34,8 @@ public HeadRestOptions()
// on https://github.com/umbraco/Umbraco-CMS/issues/6250
// and if this ever changes, we should switch to use the
// map methods instead
var mapFunc = typeof(UmbracoMapper).GetMethods()
.First(m => m.Name == "Map"
var mapFunc = mapper.GetType().GetMethods()
.First(m => m.Name == nameof(mapper.Map)
&& m.GetGenericArguments().Count() == 1
&& m.GetParameters()
.Select(p => p.ParameterType)
Expand All @@ -44,8 +48,7 @@ public HeadRestOptions()

var ctxAction = new Action<MapperContext>(x => x.SetHeadRestMappingContext(ctx));

return mapFunc.Invoke(Current.Mapper, new object[] { ctx.Content, ctxAction });

return mapFunc.Invoke(mapper, new object[] { ctx.Content, ctxAction });
};
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/Our.Umbraco.HeadRest/Mapping/HeadRestMapDefinition.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using Umbraco.Core.Mapping;
using Umbraco.Cms.Core.Mapping;

namespace Our.Umbraco.HeadRest.Mapping
{
public class HeadRestMapDefinition : IMapDefinition
{
public void DefineMaps(UmbracoMapper mapper)
public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define<HeadRestOptions, HeadRestConfig>(
(src, ctx) => new HeadRestConfig(),
Expand Down
Loading