@@ -37,11 +37,11 @@
RequiredThe confirmed password doesn't match the new password!
-
+
-
-
-
-
-
+
@@ -169,7 +169,7 @@
-
-
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js
index 63a60dc5b0..59fb5afa34 100644
--- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js
@@ -1,7 +1,7 @@
(function () {
"use strict";
- function PublishController($scope, localizationService) {
+ function PublishController($scope, localizationService, contentEditingHelper) {
var vm = this;
vm.loading = true;
@@ -129,8 +129,9 @@
_.each(vm.variants,
function (variant) {
-
- variant.compositeId = variant.language.culture + "_" + (variant.segment ? variant.segment : "");
+
+ variant.compositeId = contentEditingHelper.buildCompositeVariantId(variant);
+
variant.htmlId = "_content_variant_" + variant.compositeId;
// reset to not be published
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.controller.js
index 9d3a8a87e5..aacea9fe0e 100644
--- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.controller.js
@@ -1,7 +1,7 @@
(function () {
"use strict";
- function SaveContentController($scope, localizationService) {
+ function SaveContentController($scope, localizationService, contentEditingHelper) {
var vm = this;
vm.loading = true;
@@ -75,7 +75,7 @@
_.each(vm.variants,
function (variant) {
- variant.compositeId = variant.language.culture + "_" + (variant.segment ? variant.segment : "");
+ variant.compositeId = contentEditingHelper.buildCompositeVariantId(variant);
variant.htmlId = "_content_variant_" + variant.compositeId;
//check for pristine variants
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.controller.js
index d97bfc77b1..5aa7eff1ef 100644
--- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.controller.js
@@ -1,7 +1,7 @@
(function () {
"use strict";
- function ScheduleContentController($scope, $timeout, localizationService, dateHelper, userService) {
+ function ScheduleContentController($scope, $timeout, localizationService, dateHelper, userService, contentEditingHelper) {
var vm = this;
@@ -45,7 +45,7 @@
_.each(vm.variants,
function (variant) {
- variant.compositeId = variant.language.culture + "_" + (variant.segment ? variant.segment : "");
+ variant.compositeId = contentEditingHelper.buildCompositeVariantId(variant);
variant.htmlId = "_content_variant_" + variant.compositeId;
//check for pristine variants
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/sendtopublish.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/overlays/sendtopublish.controller.js
index 555d98e68f..c85e8d7013 100644
--- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/sendtopublish.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/sendtopublish.controller.js
@@ -1,7 +1,7 @@
(function () {
"use strict";
- function SendToPublishController($scope, localizationService) {
+ function SendToPublishController($scope, localizationService, contentEditingHelper) {
var vm = this;
vm.loading = true;
@@ -25,7 +25,7 @@
if (vm.variants.length !== 0) {
_.each(vm.variants,
function (variant) {
- variant.compositeId = variant.language.culture + "_" + (variant.segment ? variant.segment : "");
+ variant.compositeId = contentEditingHelper.buildCompositeVariantId(variant);
variant.htmlId = "_content_variant_" + variant.compositeId;
});
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/unpublish.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/overlays/unpublish.controller.js
index 20c0f4874f..3011bf49ee 100644
--- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/unpublish.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/unpublish.controller.js
@@ -1,7 +1,7 @@
(function () {
"use strict";
- function UnpublishController($scope, localizationService) {
+ function UnpublishController($scope, localizationService, contentEditingHelper) {
var vm = this;
var autoSelectedVariants = [];
@@ -23,7 +23,7 @@
_.each(vm.variants,
function (variant) {
- variant.compositeId = variant.language.culture + "_" + (variant.segment ? variant.segment : "");
+ variant.compositeId = contentEditingHelper.buildCompositeVariantId(variant);
variant.htmlId = "_content_variant_" + variant.compositeId;
});
@@ -57,7 +57,7 @@
});
$scope.model.disableSubmitButton = !firstSelected; //disable submit button if there is none selected
- // if a mandatory variant is selected we want to selet all other variants
+ // if a mandatory variant is selected we want to select all other variants
// and disable selection for the others
if(selectedVariant.save && selectedVariant.language.isMandatory) {
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js
index 6099c5dad4..b61452245b 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js
@@ -17,12 +17,13 @@ angular.module("umbraco")
if (!editorConfig || angular.isString(editorConfig)) {
editorConfig = tinyMceService.defaultPrevalues();
}
-
- var promises = [];
- if (!editorConfig.maxImageSize && editorConfig.maxImageSize != 0) {
+ //make sure there's a max image size
+ if (!editorConfig.maxImageSize && editorConfig.maxImageSize !== 0) {
editorConfig.maxImageSize = tinyMceService.defaultPrevalues().maxImageSize;
}
+ var promises = [];
+
//queue file loading
if (typeof tinymce === "undefined") { // Don't reload tinymce if already loaded
promises.push(assetsService.loadJs("lib/tinymce/tinymce.min.js", $scope));
@@ -43,7 +44,7 @@ angular.module("umbraco")
var standardConfig = result[promises.length - 1];
- //create a baseline Config to exten upon
+ //create a baseline Config to extend upon
var baseLineConfigObj = {
maxImageSize: editorConfig.maxImageSize
};
diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
index 8cb9912890..8fb0dc6cd9 100644
--- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
+++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
@@ -105,7 +105,7 @@
- 8.0.1
+ 8.0.4
diff --git a/src/Umbraco.Web.UI/Umbraco/assets/img/login.jpg b/src/Umbraco.Web.UI/Umbraco/assets/img/login.jpg
new file mode 100644
index 0000000000..06204510d0
Binary files /dev/null and b/src/Umbraco.Web.UI/Umbraco/assets/img/login.jpg differ
diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.Release.config b/src/Umbraco.Web.UI/config/umbracoSettings.Release.config
index 1420063cd6..f647e1ae1e 100644
--- a/src/Umbraco.Web.UI/config/umbracoSettings.Release.config
+++ b/src/Umbraco.Web.UI/config/umbracoSettings.Release.config
@@ -53,8 +53,8 @@
ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd,swf,xml,xhtml,html,htm,php,htaccess
-
- assets/img/installer.jpg
+
+ assets/img/login.jpg
@@ -93,9 +93,9 @@
@validateAlternativeTemplates
By default you can add a altTemplate querystring or append a template name to the current URL which
will make Umbraco render the content on the current page with the template you requested, for example:
- http://mysite.com/about-us/?altTemplate=Home and http://mysite.com/about-us/Home would render the
- "About Us" page with a template with the alias Home. Setting this setting to true will ensure that
- only templates that have been permitted on the document type will be allowed
+ http://mysite.com/about-us/?altTemplate=Home and http://mysite.com/about-us/Home would render the
+ "About Us" page with a template with the alias Home. Setting this setting to true will ensure that
+ only templates that have been permitted on the document type will be allowed
@disableFindContentByIdPath
By default you can call any content Id in the url and show the content with that id, for example:
http://mysite.com/1092 or http://mysite.com/1092.aspx would render the content with id 1092. Setting
diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.config b/src/Umbraco.Web.UI/config/umbracoSettings.config
index 1420063cd6..f647e1ae1e 100644
--- a/src/Umbraco.Web.UI/config/umbracoSettings.config
+++ b/src/Umbraco.Web.UI/config/umbracoSettings.config
@@ -53,8 +53,8 @@
ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd,swf,xml,xhtml,html,htm,php,htaccess
-
- assets/img/installer.jpg
+
+ assets/img/login.jpg
@@ -93,9 +93,9 @@
@validateAlternativeTemplates
By default you can add a altTemplate querystring or append a template name to the current URL which
will make Umbraco render the content on the current page with the template you requested, for example:
- http://mysite.com/about-us/?altTemplate=Home and http://mysite.com/about-us/Home would render the
- "About Us" page with a template with the alias Home. Setting this setting to true will ensure that
- only templates that have been permitted on the document type will be allowed
+ http://mysite.com/about-us/?altTemplate=Home and http://mysite.com/about-us/Home would render the
+ "About Us" page with a template with the alias Home. Setting this setting to true will ensure that
+ only templates that have been permitted on the document type will be allowed
@disableFindContentByIdPath
By default you can call any content Id in the url and show the content with that id, for example:
http://mysite.com/1092 or http://mysite.com/1092.aspx would render the content with id 1092. Setting
diff --git a/src/Umbraco.Web/ContentApps/ContentEditorContentAppFactory.cs b/src/Umbraco.Web/ContentApps/ContentEditorContentAppFactory.cs
index b1d5d373c0..9d186b02f8 100644
--- a/src/Umbraco.Web/ContentApps/ContentEditorContentAppFactory.cs
+++ b/src/Umbraco.Web/ContentApps/ContentEditorContentAppFactory.cs
@@ -28,7 +28,7 @@ namespace Umbraco.Web.ContentApps
Weight = Weight
});
- case IMedia media when !media.ContentType.IsContainer && media.ContentType.Alias != Core.Constants.Conventions.MediaTypes.Folder:
+ case IMedia media when !media.ContentType.IsContainer || media.Properties.Count > 0:
return _mediaApp ?? (_mediaApp = new ContentApp
{
Alias = "umbContent",
diff --git a/src/Umbraco.Web/Routing/CustomRouteUrlProvider.cs b/src/Umbraco.Web/Routing/CustomRouteUrlProvider.cs
deleted file mode 100644
index 0c6998e7e1..0000000000
--- a/src/Umbraco.Web/Routing/CustomRouteUrlProvider.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Umbraco.Core.Models.PublishedContent;
-using Umbraco.Web.Mvc;
-
-namespace Umbraco.Web.Routing
-{
- ///
- /// This url provider is used purely to deal with umbraco custom routes that utilize and will return
- /// the URL returned from the current PublishedContentRequest.PublishedContent (virtual node) if the request is in fact a virtual route and
- /// the id that is being requested matches the id of the current PublishedContentRequest.PublishedContent.
- ///
- internal class CustomRouteUrlProvider : IUrlProvider
- {
- ///
- /// This will return the URL that is returned by the assigned custom if this is a custom route
- ///
- public UrlInfo GetUrl(UmbracoContext umbracoContext, IPublishedContent content, UrlProviderMode mode, string culture, Uri current)
- {
- if (umbracoContext?.PublishedRequest?.PublishedContent == null) return null;
- if (umbracoContext.HttpContext?.Request?.RequestContext?.RouteData?.DataTokens == null) return null;
- if (umbracoContext.HttpContext.Request.RequestContext.RouteData.DataTokens.ContainsKey(Core.Constants.Web.CustomRouteDataToken) == false) return null;
-
-
- //If we get this far, it means it's a custom route with published content assigned, check if the id being requested for is the same id as the assigned published content
- //NOTE: This looks like it might cause an infinite loop because PublishedContentBase.Url calls into UmbracoContext.Current.UrlProvider.GetUrl which calls back into the IUrlProvider pipeline
- // but the specific purpose of this is that a developer is using their own IPublishedContent that returns a specific Url and doesn't go back into the UrlProvider pipeline.
- // TODO: We could put a try/catch here just in case, else we could do some reflection checking to see if the implementation is PublishedContentBase and the Url property is not overridden.
- return UrlInfo.Url(
- content.Id == umbracoContext.PublishedRequest.PublishedContent.Id
- ? umbracoContext.PublishedRequest.PublishedContent.GetUrl(culture)
- : null,
- culture);
- }
-
- ///
- /// This always returns an empty result because this url provider is used purely to deal with Umbraco custom routes with
- /// UmbracoVirtualNodeRouteHandler, we really only care about the normal URL so that RedirectToCurrentUmbracoPage() works
- /// with SurfaceControllers
- ///
- ///
- ///
- ///
- ///
- public IEnumerable GetOtherUrls(UmbracoContext umbracoContext, int id, Uri current)
- {
- yield break;
- }
- }
-}
diff --git a/src/Umbraco.Web/Routing/UrlInfo.cs b/src/Umbraco.Web/Routing/UrlInfo.cs
index ae5c4b412c..8385ab54a9 100644
--- a/src/Umbraco.Web/Routing/UrlInfo.cs
+++ b/src/Umbraco.Web/Routing/UrlInfo.cs
@@ -93,5 +93,10 @@ namespace Umbraco.Web.Routing
{
return !Equals(left, right);
}
+
+ public override string ToString()
+ {
+ return Text;
+ }
}
}
diff --git a/src/Umbraco.Web/Runtime/WebFinalComponent.cs b/src/Umbraco.Web/Runtime/WebFinalComponent.cs
index 4673cc02e4..42ff0ee5e6 100644
--- a/src/Umbraco.Web/Runtime/WebFinalComponent.cs
+++ b/src/Umbraco.Web/Runtime/WebFinalComponent.cs
@@ -1,17 +1,130 @@
-using System.Web.Http;
+using System;
+using System.Linq;
+using System.Web.Http;
+using System.Web.Mvc;
+using System.Web.Routing;
+using Umbraco.Core;
using Umbraco.Core.Composing;
+using Umbraco.Core.Configuration;
+using Umbraco.Web.Install;
+using Umbraco.Web.Mvc;
+using Umbraco.Web.WebApi;
namespace Umbraco.Web.Runtime
{
public class WebFinalComponent : IComponent
{
+ private readonly IUmbracoContextAccessor _umbracoContextAccessor;
+ private readonly SurfaceControllerTypeCollection _surfaceControllerTypes;
+ private readonly UmbracoApiControllerTypeCollection _apiControllerTypes;
+ private readonly IGlobalSettings _globalSettings;
+
+ public WebFinalComponent(IUmbracoContextAccessor umbracoContextAccessor, SurfaceControllerTypeCollection surfaceControllerTypes, UmbracoApiControllerTypeCollection apiControllerTypes, IGlobalSettings globalSettings)
+ {
+ _umbracoContextAccessor = umbracoContextAccessor;
+ _surfaceControllerTypes = surfaceControllerTypes;
+ _apiControllerTypes = apiControllerTypes;
+ _globalSettings = globalSettings;
+ }
+
public void Initialize()
{
+ // set routes
+ CreateRoutes(_umbracoContextAccessor, _globalSettings, _surfaceControllerTypes, _apiControllerTypes);
+
// ensure WebAPI is initialized, after everything
GlobalConfiguration.Configuration.EnsureInitialized();
}
public void Terminate()
{ }
+
+ // internal for tests
+ internal static void CreateRoutes(
+ IUmbracoContextAccessor umbracoContextAccessor,
+ IGlobalSettings globalSettings,
+ SurfaceControllerTypeCollection surfaceControllerTypes,
+ UmbracoApiControllerTypeCollection apiControllerTypes)
+ {
+ var umbracoPath = globalSettings.GetUmbracoMvcArea();
+
+ // create the front-end route
+ var defaultRoute = RouteTable.Routes.MapRoute(
+ "Umbraco_default",
+ umbracoPath + "/RenderMvc/{action}/{id}",
+ new { controller = "RenderMvc", action = "Index", id = UrlParameter.Optional }
+ );
+ defaultRoute.RouteHandler = new RenderRouteHandler(umbracoContextAccessor, ControllerBuilder.Current.GetControllerFactory());
+
+ // register install routes
+ RouteTable.Routes.RegisterArea();
+
+ // register all back office routes
+ RouteTable.Routes.RegisterArea(new BackOfficeArea(globalSettings));
+
+ // plugin controllers must come first because the next route will catch many things
+ RoutePluginControllers(globalSettings, surfaceControllerTypes, apiControllerTypes);
+ }
+
+ private static void RoutePluginControllers(
+ IGlobalSettings globalSettings,
+ SurfaceControllerTypeCollection surfaceControllerTypes,
+ UmbracoApiControllerTypeCollection apiControllerTypes)
+ {
+ var umbracoPath = globalSettings.GetUmbracoMvcArea();
+
+ // need to find the plugin controllers and route them
+ var pluginControllers = surfaceControllerTypes.Concat(apiControllerTypes).ToArray();
+
+ // local controllers do not contain the attribute
+ var localControllers = pluginControllers.Where(x => PluginController.GetMetadata(x).AreaName.IsNullOrWhiteSpace());
+ foreach (var s in localControllers)
+ {
+ if (TypeHelper.IsTypeAssignableFrom(s))
+ RouteLocalSurfaceController(s, umbracoPath);
+ else if (TypeHelper.IsTypeAssignableFrom(s))
+ RouteLocalApiController(s, umbracoPath);
+ }
+
+ // get the plugin controllers that are unique to each area (group by)
+ var pluginSurfaceControlleres = pluginControllers.Where(x => PluginController.GetMetadata(x).AreaName.IsNullOrWhiteSpace() == false);
+ var groupedAreas = pluginSurfaceControlleres.GroupBy(controller => PluginController.GetMetadata(controller).AreaName);
+ // loop through each area defined amongst the controllers
+ foreach (var g in groupedAreas)
+ {
+ // create & register an area for the controllers (this will throw an exception if all controllers are not in the same area)
+ var pluginControllerArea = new PluginControllerArea(globalSettings, g.Select(PluginController.GetMetadata));
+ RouteTable.Routes.RegisterArea(pluginControllerArea);
+ }
+ }
+
+ private static void RouteLocalApiController(Type controller, string umbracoPath)
+ {
+ var meta = PluginController.GetMetadata(controller);
+ var url = umbracoPath + (meta.IsBackOffice ? "/BackOffice" : "") + "/Api/" + meta.ControllerName + "/{action}/{id}";
+ var route = RouteTable.Routes.MapHttpRoute(
+ $"umbraco-api-{meta.ControllerName}",
+ url, // url to match
+ new { controller = meta.ControllerName, id = UrlParameter.Optional },
+ new[] { meta.ControllerNamespace });
+ if (route.DataTokens == null) // web api routes don't set the data tokens object
+ route.DataTokens = new RouteValueDictionary();
+ route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "api"); //ensure the umbraco token is set
+ }
+
+ private static void RouteLocalSurfaceController(Type controller, string umbracoPath)
+ {
+ var meta = PluginController.GetMetadata(controller);
+ var url = umbracoPath + "/Surface/" + meta.ControllerName + "/{action}/{id}";
+ var route = RouteTable.Routes.MapRoute(
+ $"umbraco-surface-{meta.ControllerName}",
+ url, // url to match
+ new { controller = meta.ControllerName, action = "Index", id = UrlParameter.Optional },
+ new[] { meta.ControllerNamespace }); // look in this namespace to create the controller
+ route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "surface"); // ensure the umbraco token is set
+ route.DataTokens.Add("UseNamespaceFallback", false); // don't look anywhere else except this namespace!
+ // make it use our custom/special SurfaceMvcHandler
+ route.RouteHandler = new SurfaceRouteHandler();
+ }
}
}
diff --git a/src/Umbraco.Web/Runtime/WebInitialComponent.cs b/src/Umbraco.Web/Runtime/WebInitialComponent.cs
index 3aaa8892eb..e1e0f4d80a 100644
--- a/src/Umbraco.Web/Runtime/WebInitialComponent.cs
+++ b/src/Umbraco.Web/Runtime/WebInitialComponent.cs
@@ -8,14 +8,12 @@ using System.Web.Configuration;
using System.Web.Http;
using System.Web.Http.Dispatcher;
using System.Web.Mvc;
-using System.Web.Routing;
using ClientDependency.Core.CompositeFiles.Providers;
using ClientDependency.Core.Config;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
-using Umbraco.Web.Install;
using Umbraco.Web.JavaScript;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi;
@@ -26,20 +24,10 @@ namespace Umbraco.Web.Runtime
{
public sealed class WebInitialComponent : IComponent
{
- private readonly IUmbracoContextAccessor _umbracoContextAccessor;
- private readonly SurfaceControllerTypeCollection _surfaceControllerTypes;
- private readonly UmbracoApiControllerTypeCollection _apiControllerTypes;
private readonly IGlobalSettings _globalSettings;
- public WebInitialComponent(
- IUmbracoContextAccessor umbracoContextAccessor,
- SurfaceControllerTypeCollection surfaceControllerTypes,
- UmbracoApiControllerTypeCollection apiControllerTypes,
- IGlobalSettings globalSettings)
+ public WebInitialComponent(IGlobalSettings globalSettings)
{
- _umbracoContextAccessor = umbracoContextAccessor;
- _surfaceControllerTypes = surfaceControllerTypes;
- _apiControllerTypes = apiControllerTypes;
_globalSettings = globalSettings;
}
@@ -63,9 +51,6 @@ namespace Umbraco.Web.Runtime
// add global filters
ConfigureGlobalFilters();
-
- // set routes
- CreateRoutes(_umbracoContextAccessor, _globalSettings, _surfaceControllerTypes, _apiControllerTypes);
}
public void Terminate()
@@ -90,94 +75,6 @@ namespace Umbraco.Web.Runtime
}
}
- // internal for tests
- internal static void CreateRoutes(
- IUmbracoContextAccessor umbracoContextAccessor,
- IGlobalSettings globalSettings,
- SurfaceControllerTypeCollection surfaceControllerTypes,
- UmbracoApiControllerTypeCollection apiControllerTypes)
- {
- var umbracoPath = globalSettings.GetUmbracoMvcArea();
-
- // create the front-end route
- var defaultRoute = RouteTable.Routes.MapRoute(
- "Umbraco_default",
- umbracoPath + "/RenderMvc/{action}/{id}",
- new { controller = "RenderMvc", action = "Index", id = UrlParameter.Optional }
- );
- defaultRoute.RouteHandler = new RenderRouteHandler(umbracoContextAccessor, ControllerBuilder.Current.GetControllerFactory());
-
- // register install routes
- RouteTable.Routes.RegisterArea();
-
- // register all back office routes
- RouteTable.Routes.RegisterArea(new BackOfficeArea(globalSettings));
-
- // plugin controllers must come first because the next route will catch many things
- RoutePluginControllers(globalSettings, surfaceControllerTypes, apiControllerTypes);
- }
-
- private static void RoutePluginControllers(
- IGlobalSettings globalSettings,
- SurfaceControllerTypeCollection surfaceControllerTypes,
- UmbracoApiControllerTypeCollection apiControllerTypes)
- {
- var umbracoPath = globalSettings.GetUmbracoMvcArea();
-
- // need to find the plugin controllers and route them
- var pluginControllers = surfaceControllerTypes.Concat(apiControllerTypes).ToArray();
-
- // local controllers do not contain the attribute
- var localControllers = pluginControllers.Where(x => PluginController.GetMetadata(x).AreaName.IsNullOrWhiteSpace());
- foreach (var s in localControllers)
- {
- if (TypeHelper.IsTypeAssignableFrom(s))
- RouteLocalSurfaceController(s, umbracoPath);
- else if (TypeHelper.IsTypeAssignableFrom(s))
- RouteLocalApiController(s, umbracoPath);
- }
-
- // get the plugin controllers that are unique to each area (group by)
- var pluginSurfaceControlleres = pluginControllers.Where(x => PluginController.GetMetadata(x).AreaName.IsNullOrWhiteSpace() == false);
- var groupedAreas = pluginSurfaceControlleres.GroupBy(controller => PluginController.GetMetadata(controller).AreaName);
- // loop through each area defined amongst the controllers
- foreach (var g in groupedAreas)
- {
- // create & register an area for the controllers (this will throw an exception if all controllers are not in the same area)
- var pluginControllerArea = new PluginControllerArea(globalSettings, g.Select(PluginController.GetMetadata));
- RouteTable.Routes.RegisterArea(pluginControllerArea);
- }
- }
-
- private static void RouteLocalApiController(Type controller, string umbracoPath)
- {
- var meta = PluginController.GetMetadata(controller);
- var url = umbracoPath + (meta.IsBackOffice ? "/BackOffice" : "") + "/Api/" + meta.ControllerName + "/{action}/{id}";
- var route = RouteTable.Routes.MapHttpRoute(
- $"umbraco-api-{meta.ControllerName}",
- url, // url to match
- new { controller = meta.ControllerName, id = UrlParameter.Optional },
- new[] { meta.ControllerNamespace });
- if (route.DataTokens == null) // web api routes don't set the data tokens object
- route.DataTokens = new RouteValueDictionary();
- route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "api"); //ensure the umbraco token is set
- }
-
- private static void RouteLocalSurfaceController(Type controller, string umbracoPath)
- {
- var meta = PluginController.GetMetadata(controller);
- var url = umbracoPath + "/Surface/" + meta.ControllerName + "/{action}/{id}";
- var route = RouteTable.Routes.MapRoute(
- $"umbraco-surface-{meta.ControllerName}",
- url, // url to match
- new { controller = meta.ControllerName, action = "Index", id = UrlParameter.Optional },
- new[] { meta.ControllerNamespace }); // look in this namespace to create the controller
- route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "surface"); // ensure the umbraco token is set
- route.DataTokens.Add("UseNamespaceFallback", false); // don't look anywhere else except this namespace!
- // make it use our custom/special SurfaceMvcHandler
- route.RouteHandler = new SurfaceRouteHandler();
- }
-
private static void SetupMvcAndWebApi()
{
//don't output the MVC version header (security)
diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs
index 5f95ab2b8e..f1c8fcc12f 100644
--- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs
+++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs
@@ -181,8 +181,7 @@ namespace Umbraco.Web.Runtime
composition.WithCollectionBuilder()
.Append()
- .Append()
- .Append();
+ .Append();
composition.RegisterUnique();
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 985532984f..09cc7d856a 100755
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -877,7 +877,6 @@
-
diff --git a/src/Umbraco.Web/UmbracoContextFactory.cs b/src/Umbraco.Web/UmbracoContextFactory.cs
index a4acd49f1e..9bb2a79411 100644
--- a/src/Umbraco.Web/UmbracoContextFactory.cs
+++ b/src/Umbraco.Web/UmbracoContextFactory.cs
@@ -28,13 +28,13 @@ namespace Umbraco.Web
private readonly IUmbracoSettingsSection _umbracoSettings;
private readonly IGlobalSettings _globalSettings;
- private readonly IEnumerable _urlProviders;
+ private readonly UrlProviderCollection _urlProviders;
private readonly IUserService _userService;
///
/// Initializes a new instance of the class.
///
- public UmbracoContextFactory(IUmbracoContextAccessor umbracoContextAccessor, IPublishedSnapshotService publishedSnapshotService, IVariationContextAccessor variationContextAccessor, IDefaultCultureAccessor defaultCultureAccessor, IUmbracoSettingsSection umbracoSettings, IGlobalSettings globalSettings, IEnumerable urlProviders, IUserService userService)
+ public UmbracoContextFactory(IUmbracoContextAccessor umbracoContextAccessor, IPublishedSnapshotService publishedSnapshotService, IVariationContextAccessor variationContextAccessor, IDefaultCultureAccessor defaultCultureAccessor, IUmbracoSettingsSection umbracoSettings, IGlobalSettings globalSettings, UrlProviderCollection urlProviders, IUserService userService)
{
_umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
_publishedSnapshotService = publishedSnapshotService ?? throw new ArgumentNullException(nameof(publishedSnapshotService));
@@ -65,7 +65,7 @@ namespace Umbraco.Web
if (currentUmbracoContext != null)
return new UmbracoContextReference(currentUmbracoContext, false, _umbracoContextAccessor);
-
+
httpContext = httpContext ?? new HttpContextWrapper(HttpContext.Current ?? new HttpContext(new SimpleWorkerRequest("null.aspx", "", NullWriterInstance)));
var umbracoContext = CreateUmbracoContext(httpContext);