Upgrade to ModelsBuilder 8.0.2, support Custom Tool (#4881)
* Upgrade to ModelsBuilder 8.0.2, support Custom Tool
* Upgrade to ModelsBuilder 8.0.3
* Fix controllers
* Upgrade MB
* Fix previous commit
(cherry picked from commit c85c055424)
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.4.0, 2.999999)" />
|
||||
<dependency id="Umbraco.ModelsBuilder.Ui" version="[8.0.1]" />
|
||||
<dependency id="Umbraco.ModelsBuilder.Ui" version="[8.0.4]" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.10.0.100,4.999999)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.5.0.100,2.999999)" />
|
||||
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[2.0.1,2.999999)" />
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
/// <summary>
|
||||
/// Compose.
|
||||
/// </summary>
|
||||
/// <param name="composition"></param>
|
||||
void Compose(Composition composition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,8 @@
|
||||
/// Represents a core <see cref="IComposer"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>All core composers are required by (compose before) all user composers,
|
||||
/// and require (compose after) all runtime composers.</para>
|
||||
/// <para>Core composers compose after the initial composer, and before user composers.</para>
|
||||
/// </remarks>
|
||||
[ComposeAfter(typeof(IRuntimeComposer))]
|
||||
public interface ICoreComposer : IComposer
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a runtime <see cref="IComposer"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>All runtime composers are required by (compose before) all core composers</para>
|
||||
/// </remarks>
|
||||
public interface IRuntimeComposer : IComposer
|
||||
{ }
|
||||
}
|
||||
@@ -4,9 +4,9 @@
|
||||
/// Represents a user <see cref="IComposer"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>All user composers require (compose after) all core composers.</para>
|
||||
/// <para>User composers compose after core composers, and before the final composer.</para>
|
||||
/// </remarks>
|
||||
[ComposeAfter(typeof(ICoreComposer))]
|
||||
public interface IUserComposer : IComposer
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,11 @@ using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core.Runtime
|
||||
{
|
||||
public class CoreRuntimeComponent : IComponent
|
||||
public class CoreInitialComponent : IComponent
|
||||
{
|
||||
private readonly IEnumerable<Profile> _mapperProfiles;
|
||||
|
||||
public CoreRuntimeComponent(IEnumerable<Profile> mapperProfiles)
|
||||
public CoreInitialComponent(IEnumerable<Profile> mapperProfiles)
|
||||
{
|
||||
_mapperProfiles = mapperProfiles;
|
||||
}
|
||||
@@ -24,7 +24,9 @@ using IntegerValidator = Umbraco.Core.PropertyEditors.Validators.IntegerValidato
|
||||
|
||||
namespace Umbraco.Core.Runtime
|
||||
{
|
||||
public class CoreRuntimeComposer : ComponentComposer<CoreRuntimeComponent>, IRuntimeComposer
|
||||
// core's initial composer composes before all core composers
|
||||
[ComposeBefore(typeof(ICoreComposer))]
|
||||
public class CoreInitialComposer : ComponentComposer<CoreInitialComponent>
|
||||
{
|
||||
public override void Compose(Composition composition)
|
||||
{
|
||||
@@ -168,7 +168,6 @@
|
||||
<Compile Include="Composing\EnableComposerAttribute.cs" />
|
||||
<Compile Include="Composing\IComposer.cs" />
|
||||
<Compile Include="Composing\ICoreComposer.cs" />
|
||||
<Compile Include="Composing\IRuntimeComposer.cs" />
|
||||
<Compile Include="Composing\IComponent.cs" />
|
||||
<Compile Include="Composing\IUserComposer.cs" />
|
||||
<Compile Include="Compose\ManifestWatcherComposer.cs" />
|
||||
@@ -532,7 +531,7 @@
|
||||
<Compile Include="RuntimeLevelReason.cs" />
|
||||
<Compile Include="RuntimeOptions.cs" />
|
||||
<Compile Include="Runtime\CoreRuntime.cs" />
|
||||
<Compile Include="Runtime\CoreRuntimeComponent.cs" />
|
||||
<Compile Include="Runtime\CoreInitialComponent.cs" />
|
||||
<Compile Include="CustomBooleanTypeConverter.cs" />
|
||||
<Compile Include="Migrations\Expressions\Common\ExecutableBuilder.cs" />
|
||||
<Compile Include="Migrations\Expressions\Common\IExecutableBuilder.cs" />
|
||||
@@ -1313,7 +1312,7 @@
|
||||
<Compile Include="ReflectionUtilities.cs" />
|
||||
<Compile Include="RuntimeLevel.cs" />
|
||||
<Compile Include="RuntimeState.cs" />
|
||||
<Compile Include="Runtime\CoreRuntimeComposer.cs" />
|
||||
<Compile Include="Runtime\CoreInitialComposer.cs" />
|
||||
<Compile Include="SafeCallContext.cs" />
|
||||
<Compile Include="Scoping\IInstanceIdentifiable.cs" />
|
||||
<Compile Include="Scoping\IScope.cs" />
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Umbraco.Tests.Routing
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
WebRuntimeComponent.CreateRoutes(
|
||||
WebFinalComponent.CreateRoutes(
|
||||
new TestUmbracoContextAccessor(),
|
||||
TestObjects.GetGlobalSettings(),
|
||||
new SurfaceControllerTypeCollection(Enumerable.Empty<Type>()),
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace Umbraco.Tests.Runtimes
|
||||
|
||||
var composerTypes = typeLoader.GetTypes<IComposer>() // all of them
|
||||
.Where(x => !x.FullName.StartsWith("Umbraco.Tests.")) // exclude test components
|
||||
.Where(x => x != typeof(WebRuntimeComposer)); // exclude web runtime
|
||||
.Where(x => x != typeof(WebInitialComposer)); // exclude web runtime
|
||||
var composers = new Composers(composition, composerTypes, profilingLogger);
|
||||
composers.Compose();
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Umbraco.Tests.Runtimes
|
||||
new PluginViewEngine()
|
||||
};
|
||||
|
||||
WebRuntimeComponent.WrapViewEngines(engines);
|
||||
WebInitialComponent.WrapViewEngines(engines);
|
||||
|
||||
Assert.That(engines.Count, Is.EqualTo(2));
|
||||
Assert.That(engines[0], Is.InstanceOf<ProfilingViewEngine>());
|
||||
@@ -34,7 +34,7 @@ namespace Umbraco.Tests.Runtimes
|
||||
new PluginViewEngine()
|
||||
};
|
||||
|
||||
WebRuntimeComponent.WrapViewEngines(engines);
|
||||
WebInitialComponent.WrapViewEngines(engines);
|
||||
|
||||
Assert.That(engines.Count, Is.EqualTo(2));
|
||||
Assert.That(((ProfilingViewEngine)engines[0]).Inner, Is.InstanceOf<RenderViewEngine>());
|
||||
@@ -50,7 +50,7 @@ namespace Umbraco.Tests.Runtimes
|
||||
profiledEngine
|
||||
};
|
||||
|
||||
WebRuntimeComponent.WrapViewEngines(engines);
|
||||
WebInitialComponent.WrapViewEngines(engines);
|
||||
|
||||
Assert.That(engines[0], Is.SameAs(profiledEngine));
|
||||
}
|
||||
@@ -58,7 +58,7 @@ namespace Umbraco.Tests.Runtimes
|
||||
[Test]
|
||||
public void WrapViewEngines_CollectionIsNull_DoesNotThrow()
|
||||
{
|
||||
Assert.DoesNotThrow(() => WebRuntimeComponent.WrapViewEngines(null));
|
||||
Assert.DoesNotThrow(() => WebInitialComponent.WrapViewEngines(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
<PackageReference Include="MiniProfiler" Version="4.0.138" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||
<PackageReference Include="Umbraco.ModelsBuilder.Ui">
|
||||
<Version>8.0.1</Version>
|
||||
<Version>8.0.4</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Umbraco.SqlServerCE" Version="4.0.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
130
src/Umbraco.Web/Runtime/WebFinalComponent.cs
Normal file
130
src/Umbraco.Web/Runtime/WebFinalComponent.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
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<UmbracoInstallArea>();
|
||||
|
||||
// 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<SurfaceController>(s))
|
||||
RouteLocalSurfaceController(s, umbracoPath);
|
||||
else if (TypeHelper.IsTypeAssignableFrom<UmbracoApiController>(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();
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/Umbraco.Web/Runtime/WebFinalComposer.cs
Normal file
9
src/Umbraco.Web/Runtime/WebFinalComposer.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Web.Runtime
|
||||
{
|
||||
// web's final composer composes after all user composers
|
||||
[ComposeAfter(typeof(IUserComposer))]
|
||||
public class WebFinalComposer : ComponentComposer<WebFinalComponent>
|
||||
{ }
|
||||
}
|
||||
135
src/Umbraco.Web/Runtime/WebInitialComponent.cs
Normal file
135
src/Umbraco.Web/Runtime/WebInitialComponent.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Http;
|
||||
using System.Web.Http.Dispatcher;
|
||||
using System.Web.Mvc;
|
||||
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.JavaScript;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi;
|
||||
|
||||
using Current = Umbraco.Web.Composing.Current;
|
||||
|
||||
namespace Umbraco.Web.Runtime
|
||||
{
|
||||
public sealed class WebInitialComponent : IComponent
|
||||
{
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
|
||||
public WebInitialComponent(IGlobalSettings globalSettings)
|
||||
{
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
// setup mvc and webapi services
|
||||
SetupMvcAndWebApi();
|
||||
|
||||
// When using a non-web runtime and this component is loaded ClientDependency explodes because it'll
|
||||
// want to access HttpContext.Current, which doesn't exist
|
||||
if (IOHelper.IsHosted)
|
||||
{
|
||||
ConfigureClientDependency(_globalSettings);
|
||||
}
|
||||
|
||||
// Disable the X-AspNetMvc-Version HTTP Header
|
||||
MvcHandler.DisableMvcResponseHeader = true;
|
||||
|
||||
// wrap view engines in the profiling engine
|
||||
WrapViewEngines(ViewEngines.Engines);
|
||||
|
||||
// add global filters
|
||||
ConfigureGlobalFilters();
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{ }
|
||||
|
||||
private static void ConfigureGlobalFilters()
|
||||
{
|
||||
GlobalFilters.Filters.Add(new EnsurePartialViewMacroViewContextFilterAttribute());
|
||||
}
|
||||
|
||||
// internal for tests
|
||||
internal static void WrapViewEngines(IList<IViewEngine> viewEngines)
|
||||
{
|
||||
if (viewEngines == null || viewEngines.Count == 0) return;
|
||||
|
||||
var originalEngines = viewEngines.ToList();
|
||||
viewEngines.Clear();
|
||||
foreach (var engine in originalEngines)
|
||||
{
|
||||
var wrappedEngine = engine is ProfilingViewEngine ? engine : new ProfilingViewEngine(engine);
|
||||
viewEngines.Add(wrappedEngine);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetupMvcAndWebApi()
|
||||
{
|
||||
//don't output the MVC version header (security)
|
||||
MvcHandler.DisableMvcResponseHeader = true;
|
||||
|
||||
// set master controller factory
|
||||
var controllerFactory = new MasterControllerFactory(() => Current.FilteredControllerFactories);
|
||||
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
|
||||
|
||||
// set the render & plugin view engines
|
||||
ViewEngines.Engines.Add(new RenderViewEngine());
|
||||
ViewEngines.Engines.Add(new PluginViewEngine());
|
||||
|
||||
//set model binder
|
||||
ModelBinderProviders.BinderProviders.Add(ContentModelBinder.Instance); // is a provider
|
||||
|
||||
////add the profiling action filter
|
||||
//GlobalFilters.Filters.Add(new ProfilingActionFilter());
|
||||
|
||||
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector),
|
||||
new NamespaceHttpControllerSelector(GlobalConfiguration.Configuration));
|
||||
}
|
||||
|
||||
private static void ConfigureClientDependency(IGlobalSettings globalSettings)
|
||||
{
|
||||
// Backwards compatibility - set the path and URL type for ClientDependency 1.5.1 [LK]
|
||||
XmlFileMapper.FileMapDefaultFolder = SystemDirectories.TempData.EnsureEndsWith('/') + "ClientDependency";
|
||||
BaseCompositeFileProcessingProvider.UrlTypeDefault = CompositeUrlType.Base64QueryStrings;
|
||||
|
||||
// Now we need to detect if we are running 'Umbraco.Core.LocalTempStorage' as EnvironmentTemp and in that case we want to change the CDF file
|
||||
// location to be there
|
||||
if (globalSettings.LocalTempStorageLocation == LocalTempStorage.EnvironmentTemp)
|
||||
{
|
||||
var cachePath = globalSettings.LocalTempPath;
|
||||
|
||||
//set the file map and composite file default location to the %temp% location
|
||||
BaseCompositeFileProcessingProvider.CompositeFilePathDefaultFolder
|
||||
= XmlFileMapper.FileMapDefaultFolder
|
||||
= Path.Combine(cachePath, "ClientDependency");
|
||||
}
|
||||
|
||||
if (ConfigurationManager.GetSection("system.web/httpRuntime") is HttpRuntimeSection section)
|
||||
{
|
||||
//set the max url length for CDF to be the smallest of the max query length, max request length
|
||||
ClientDependency.Core.CompositeFiles.CompositeDependencyHandler.MaxHandlerUrlLength = Math.Min(section.MaxQueryStringLength, section.MaxRequestLength);
|
||||
}
|
||||
|
||||
//Register a custom renderer - used to process property editor dependencies
|
||||
var renderer = new DependencyPathRenderer();
|
||||
renderer.Initialize("Umbraco.DependencyPathRenderer", new NameValueCollection
|
||||
{
|
||||
{ "compositeFileHandlerPath", ClientDependencySettings.Instance.CompositeFileHandlerPath }
|
||||
});
|
||||
|
||||
ClientDependencySettings.Instance.MvcRendererCollection.Add(renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,8 +44,10 @@ using Current = Umbraco.Web.Composing.Current;
|
||||
|
||||
namespace Umbraco.Web.Runtime
|
||||
{
|
||||
[ComposeAfter(typeof(CoreRuntimeComposer))]
|
||||
public sealed class WebRuntimeComposer : ComponentComposer<WebRuntimeComponent>, IRuntimeComposer
|
||||
// web's initial composer composes after core's, and before all core composers
|
||||
[ComposeAfter(typeof(CoreInitialComposer))]
|
||||
[ComposeBefore(typeof(ICoreComposer))]
|
||||
public sealed class WebInitialComposer : ComponentComposer<WebInitialComponent>
|
||||
{
|
||||
public override void Compose(Composition composition)
|
||||
{
|
||||
@@ -1,265 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
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.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Install;
|
||||
using Umbraco.Web.JavaScript;
|
||||
using Umbraco.Web.Models.Trees;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Security;
|
||||
using Umbraco.Web.Trees;
|
||||
using Umbraco.Web.WebApi;
|
||||
|
||||
using Current = Umbraco.Web.Composing.Current;
|
||||
|
||||
namespace Umbraco.Web.Runtime
|
||||
{
|
||||
public sealed class WebRuntimeComponent : IComponent
|
||||
{
|
||||
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
|
||||
private readonly SurfaceControllerTypeCollection _surfaceControllerTypes;
|
||||
private readonly UmbracoApiControllerTypeCollection _apiControllerTypes;
|
||||
private readonly IPublishedSnapshotService _publishedSnapshotService;
|
||||
private readonly IUserService _userService;
|
||||
private readonly IUmbracoSettingsSection _umbracoSettings;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
private readonly IVariationContextAccessor _variationContextAccessor;
|
||||
private readonly UrlProviderCollection _urlProviders;
|
||||
|
||||
public WebRuntimeComponent(
|
||||
IUmbracoContextAccessor umbracoContextAccessor,
|
||||
SurfaceControllerTypeCollection surfaceControllerTypes,
|
||||
UmbracoApiControllerTypeCollection apiControllerTypes,
|
||||
IPublishedSnapshotService publishedSnapshotService,
|
||||
IUserService userService,
|
||||
IUmbracoSettingsSection umbracoSettings,
|
||||
IGlobalSettings globalSettings,
|
||||
IVariationContextAccessor variationContextAccessor,
|
||||
UrlProviderCollection urlProviders)
|
||||
{
|
||||
_umbracoContextAccessor = umbracoContextAccessor;
|
||||
_surfaceControllerTypes = surfaceControllerTypes;
|
||||
_apiControllerTypes = apiControllerTypes;
|
||||
_publishedSnapshotService = publishedSnapshotService;
|
||||
_userService = userService;
|
||||
_umbracoSettings = umbracoSettings;
|
||||
_globalSettings = globalSettings;
|
||||
_variationContextAccessor = variationContextAccessor;
|
||||
_urlProviders = urlProviders;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
// setup mvc and webapi services
|
||||
SetupMvcAndWebApi();
|
||||
|
||||
// When using a non-web runtime and this component is loaded ClientDependency explodes because it'll
|
||||
// want to access HttpContext.Current, which doesn't exist
|
||||
if (IOHelper.IsHosted)
|
||||
{
|
||||
ConfigureClientDependency(_globalSettings);
|
||||
}
|
||||
|
||||
// Disable the X-AspNetMvc-Version HTTP Header
|
||||
MvcHandler.DisableMvcResponseHeader = true;
|
||||
|
||||
// wrap view engines in the profiling engine
|
||||
WrapViewEngines(ViewEngines.Engines);
|
||||
|
||||
// add global filters
|
||||
ConfigureGlobalFilters();
|
||||
|
||||
// set routes
|
||||
CreateRoutes(_umbracoContextAccessor, _globalSettings, _surfaceControllerTypes, _apiControllerTypes);
|
||||
|
||||
// ensure WebAPI is initialized, after everything
|
||||
GlobalConfiguration.Configuration.EnsureInitialized();
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{ }
|
||||
|
||||
private static void ConfigureGlobalFilters()
|
||||
{
|
||||
GlobalFilters.Filters.Add(new EnsurePartialViewMacroViewContextFilterAttribute());
|
||||
}
|
||||
|
||||
// internal for tests
|
||||
internal static void WrapViewEngines(IList<IViewEngine> viewEngines)
|
||||
{
|
||||
if (viewEngines == null || viewEngines.Count == 0) return;
|
||||
|
||||
var originalEngines = viewEngines.ToList();
|
||||
viewEngines.Clear();
|
||||
foreach (var engine in originalEngines)
|
||||
{
|
||||
var wrappedEngine = engine is ProfilingViewEngine ? engine : new ProfilingViewEngine(engine);
|
||||
viewEngines.Add(wrappedEngine);
|
||||
}
|
||||
}
|
||||
|
||||
// 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<UmbracoInstallArea>();
|
||||
|
||||
// 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<SurfaceController>(s))
|
||||
RouteLocalSurfaceController(s, umbracoPath);
|
||||
else if (TypeHelper.IsTypeAssignableFrom<UmbracoApiController>(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)
|
||||
MvcHandler.DisableMvcResponseHeader = true;
|
||||
|
||||
// set master controller factory
|
||||
var controllerFactory = new MasterControllerFactory(() => Current.FilteredControllerFactories);
|
||||
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
|
||||
|
||||
// set the render & plugin view engines
|
||||
ViewEngines.Engines.Add(new RenderViewEngine());
|
||||
ViewEngines.Engines.Add(new PluginViewEngine());
|
||||
|
||||
//set model binder
|
||||
ModelBinderProviders.BinderProviders.Add(ContentModelBinder.Instance); // is a provider
|
||||
|
||||
////add the profiling action filter
|
||||
//GlobalFilters.Filters.Add(new ProfilingActionFilter());
|
||||
|
||||
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector),
|
||||
new NamespaceHttpControllerSelector(GlobalConfiguration.Configuration));
|
||||
}
|
||||
|
||||
private static void ConfigureClientDependency(IGlobalSettings globalSettings)
|
||||
{
|
||||
// Backwards compatibility - set the path and URL type for ClientDependency 1.5.1 [LK]
|
||||
XmlFileMapper.FileMapDefaultFolder = SystemDirectories.TempData.EnsureEndsWith('/') + "ClientDependency";
|
||||
BaseCompositeFileProcessingProvider.UrlTypeDefault = CompositeUrlType.Base64QueryStrings;
|
||||
|
||||
// Now we need to detect if we are running 'Umbraco.Core.LocalTempStorage' as EnvironmentTemp and in that case we want to change the CDF file
|
||||
// location to be there
|
||||
if (globalSettings.LocalTempStorageLocation == LocalTempStorage.EnvironmentTemp)
|
||||
{
|
||||
var cachePath = globalSettings.LocalTempPath;
|
||||
|
||||
//set the file map and composite file default location to the %temp% location
|
||||
BaseCompositeFileProcessingProvider.CompositeFilePathDefaultFolder
|
||||
= XmlFileMapper.FileMapDefaultFolder
|
||||
= Path.Combine(cachePath, "ClientDependency");
|
||||
}
|
||||
|
||||
if (ConfigurationManager.GetSection("system.web/httpRuntime") is HttpRuntimeSection section)
|
||||
{
|
||||
//set the max url length for CDF to be the smallest of the max query length, max request length
|
||||
ClientDependency.Core.CompositeFiles.CompositeDependencyHandler.MaxHandlerUrlLength = Math.Min(section.MaxQueryStringLength, section.MaxRequestLength);
|
||||
}
|
||||
|
||||
//Register a custom renderer - used to process property editor dependencies
|
||||
var renderer = new DependencyPathRenderer();
|
||||
renderer.Initialize("Umbraco.DependencyPathRenderer", new NameValueCollection
|
||||
{
|
||||
{ "compositeFileHandlerPath", ClientDependencySettings.Instance.CompositeFileHandlerPath }
|
||||
});
|
||||
|
||||
ClientDependencySettings.Instance.MvcRendererCollection.Add(renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,7 +254,7 @@
|
||||
<Compile Include="PropertyEditors\PropertyEditorsComposer.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\NuCacheComposer.cs" />
|
||||
<Compile Include="Routing\RedirectTrackingComposer.cs" />
|
||||
<Compile Include="Runtime\WebRuntimeComposer.cs" />
|
||||
<Compile Include="Runtime\WebInitialComposer.cs" />
|
||||
<Compile Include="Scheduling\SchedulerComposer.cs" />
|
||||
<Compile Include="Search\ExamineComposer.cs" />
|
||||
<Compile Include="Search\GenericIndexDiagnostics.cs" />
|
||||
@@ -607,7 +607,7 @@
|
||||
<Compile Include="WebApi\UmbracoApiControllerTypeCollectionBuilder.cs" />
|
||||
<Compile Include="WebApi\UnhandedExceptionLoggerConfigurationAttribute.cs" />
|
||||
<Compile Include="WebApi\UnhandledExceptionLogger.cs" />
|
||||
<Compile Include="Runtime\WebRuntimeComponent.cs" />
|
||||
<Compile Include="Runtime\WebInitialComponent.cs" />
|
||||
<Compile Include="Editors\PublishedStatusController.cs" />
|
||||
<Compile Include="Editors\NuCacheStatusController.cs" />
|
||||
<Compile Include="Actions\ActionAssignDomain.cs" />
|
||||
@@ -1188,6 +1188,8 @@
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="WebViewPageExtensions.cs" />
|
||||
<Compile Include="Runtime\WebFinalComponent.cs" />
|
||||
<Compile Include="Runtime\WebFinalComposer.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="JavaScript\Resources.resx">
|
||||
|
||||
Reference in New Issue
Block a user