2012-08-01 22:06:15 +06:00
|
|
|
|
using System;
|
2012-08-07 21:40:34 +06:00
|
|
|
|
using System.Collections.Generic;
|
2012-09-26 11:04:07 +07:00
|
|
|
|
using System.Linq;
|
2012-08-07 21:40:34 +06:00
|
|
|
|
using System.Web.Mvc;
|
|
|
|
|
|
using System.Web.Routing;
|
2012-08-01 22:06:15 +06:00
|
|
|
|
using Umbraco.Core;
|
2012-09-25 13:09:59 +07:00
|
|
|
|
using Umbraco.Core.Configuration;
|
2012-08-15 23:20:37 +06:00
|
|
|
|
using Umbraco.Core.Dictionary;
|
2012-08-17 04:27:47 +06:00
|
|
|
|
using Umbraco.Core.Dynamics;
|
2012-09-08 07:13:03 +07:00
|
|
|
|
using Umbraco.Core.PropertyEditors;
|
2012-08-15 23:20:37 +06:00
|
|
|
|
using Umbraco.Web.Dictionary;
|
2012-08-04 06:20:06 +06:00
|
|
|
|
using Umbraco.Web.Media.ThumbnailProviders;
|
2012-10-24 09:59:23 +05:00
|
|
|
|
using Umbraco.Web.Models;
|
2012-08-07 21:40:34 +06:00
|
|
|
|
using Umbraco.Web.Mvc;
|
2012-09-08 07:13:03 +07:00
|
|
|
|
using Umbraco.Web.PropertyEditors;
|
2012-08-01 22:06:15 +06:00
|
|
|
|
using Umbraco.Web.Routing;
|
|
|
|
|
|
using umbraco.businesslogic;
|
|
|
|
|
|
|
2012-09-25 13:09:59 +07:00
|
|
|
|
|
2012-08-01 22:06:15 +06:00
|
|
|
|
namespace Umbraco.Web
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// A bootstrapper for the Umbraco application which initializes all objects including the Web portion of the application
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
internal class WebBootManager : CoreBootManager
|
|
|
|
|
|
{
|
2012-10-02 02:33:19 +05:00
|
|
|
|
private readonly bool _isForTesting;
|
2012-08-14 12:03:34 +06:00
|
|
|
|
private readonly UmbracoApplication _umbracoApplication;
|
|
|
|
|
|
|
|
|
|
|
|
public WebBootManager(UmbracoApplication umbracoApplication)
|
2012-10-02 02:33:19 +05:00
|
|
|
|
: this(umbracoApplication, false)
|
2012-08-01 22:06:15 +06:00
|
|
|
|
{
|
2012-10-02 02:33:19 +05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructor for unit tests, ensures some resolvers are not initialized
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="umbracoApplication"></param>
|
|
|
|
|
|
/// <param name="isForTesting"></param>
|
|
|
|
|
|
internal WebBootManager(UmbracoApplication umbracoApplication, bool isForTesting)
|
|
|
|
|
|
{
|
|
|
|
|
|
_isForTesting = isForTesting;
|
2012-08-14 12:03:34 +06:00
|
|
|
|
_umbracoApplication = umbracoApplication;
|
|
|
|
|
|
if (umbracoApplication == null) throw new ArgumentNullException("umbracoApplication");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Boot()
|
2012-08-30 08:26:01 +07:00
|
|
|
|
{
|
2012-08-01 22:06:15 +06:00
|
|
|
|
InitializeResolvers();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Initialize objects before anything during the boot cycle happens
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public override IBootManager Initialize()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.Initialize();
|
|
|
|
|
|
|
|
|
|
|
|
// Backwards compatibility - set the path and URL type for ClientDependency 1.5.1 [LK]
|
|
|
|
|
|
ClientDependency.Core.CompositeFiles.Providers.XmlFileMapper.FileMapVirtualFolder = "~/App_Data/TEMP/ClientDependency";
|
|
|
|
|
|
ClientDependency.Core.CompositeFiles.Providers.BaseCompositeFileProcessingProvider.UrlTypeDefault = ClientDependency.Core.CompositeFiles.Providers.CompositeUrlType.Base64QueryStrings;
|
|
|
|
|
|
|
2012-08-07 21:40:34 +06:00
|
|
|
|
//set master controller factory
|
|
|
|
|
|
ControllerBuilder.Current.SetControllerFactory(
|
|
|
|
|
|
new MasterControllerFactory(FilteredControllerFactoriesResolver.Current));
|
|
|
|
|
|
|
|
|
|
|
|
//set the render view engine
|
|
|
|
|
|
ViewEngines.Engines.Add(new RenderViewEngine());
|
2012-10-01 23:22:23 +05:00
|
|
|
|
//set the plugin view engine
|
|
|
|
|
|
ViewEngines.Engines.Add(new PluginViewEngine());
|
2012-08-07 21:40:34 +06:00
|
|
|
|
|
|
|
|
|
|
//set model binder
|
|
|
|
|
|
ModelBinders.Binders.Add(new KeyValuePair<Type, IModelBinder>(typeof(RenderModel), new RenderModelBinder()));
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-08-14 12:03:34 +06:00
|
|
|
|
//find and initialize the application startup handlers, we need to initialize this resolver here because
|
|
|
|
|
|
//it is a special resolver where they need to be instantiated first before any other resolvers in order to bind to
|
|
|
|
|
|
//events and to call their events during bootup.
|
|
|
|
|
|
//ApplicationStartupHandler.RegisterHandlers();
|
2012-10-31 11:36:22 +06:00
|
|
|
|
//... and set the special flag to let us resolve before frozen resolution
|
2012-08-14 12:03:34 +06:00
|
|
|
|
ApplicationEventsResolver.Current = new ApplicationEventsResolver(
|
2012-10-31 11:36:22 +06:00
|
|
|
|
PluginManager.Current.ResolveApplicationStartupHandlers())
|
|
|
|
|
|
{
|
|
|
|
|
|
CanResolveBeforeFrozen = true
|
|
|
|
|
|
};
|
|
|
|
|
|
//add the internal types since we don't want to mark these public
|
|
|
|
|
|
ApplicationEventsResolver.Current.AddType<CacheHelperExtensions.CacheHelperApplicationEventListener>();
|
|
|
|
|
|
ApplicationEventsResolver.Current.AddType<LegacyScheduledTasks>();
|
2012-08-14 12:03:34 +06:00
|
|
|
|
|
|
|
|
|
|
//now we need to call the initialize methods
|
|
|
|
|
|
ApplicationEventsResolver.Current.ApplicationEventHandlers
|
|
|
|
|
|
.ForEach(x => x.OnApplicationInitialized(_umbracoApplication, ApplicationContext));
|
|
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Ensure that the OnApplicationStarting methods of the IApplicationEvents are called
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="afterStartup"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public override IBootManager Startup(Action<ApplicationContext> afterStartup)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.Startup(afterStartup);
|
|
|
|
|
|
|
|
|
|
|
|
//call OnApplicationStarting of each application events handler
|
|
|
|
|
|
ApplicationEventsResolver.Current.ApplicationEventHandlers
|
|
|
|
|
|
.ForEach(x => x.OnApplicationStarting(_umbracoApplication, ApplicationContext));
|
|
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Ensure that the OnApplicationStarted methods of the IApplicationEvents are called
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="afterComplete"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public override IBootManager Complete(Action<ApplicationContext> afterComplete)
|
|
|
|
|
|
{
|
2012-09-25 13:09:59 +07:00
|
|
|
|
//set routes
|
|
|
|
|
|
CreateRoutes();
|
|
|
|
|
|
|
2012-09-29 07:20:23 +07:00
|
|
|
|
base.Complete(afterComplete);
|
|
|
|
|
|
|
2012-08-14 12:03:34 +06:00
|
|
|
|
//call OnApplicationStarting of each application events handler
|
|
|
|
|
|
ApplicationEventsResolver.Current.ApplicationEventHandlers
|
|
|
|
|
|
.ForEach(x => x.OnApplicationStarted(_umbracoApplication, ApplicationContext));
|
2012-08-01 22:06:15 +06:00
|
|
|
|
|
2012-09-28 11:11:47 -02:00
|
|
|
|
// we're ready to serve content!
|
|
|
|
|
|
ApplicationContext.IsReady = true;
|
|
|
|
|
|
|
2012-08-01 22:06:15 +06:00
|
|
|
|
return this;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-08-14 23:35:34 +06:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Creates the routes
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected internal void CreateRoutes()
|
|
|
|
|
|
{
|
2012-10-16 01:33:35 +05:00
|
|
|
|
var umbracoPath = GlobalSettings.UmbracoMvcArea;
|
2012-09-25 13:09:59 +07:00
|
|
|
|
|
2012-10-16 01:33:35 +05:00
|
|
|
|
//Create the front-end route
|
2012-09-25 13:09:59 +07:00
|
|
|
|
var defaultRoute = RouteTable.Routes.MapRoute(
|
2012-08-14 23:35:34 +06:00
|
|
|
|
"Umbraco_default",
|
|
|
|
|
|
"Umbraco/RenderMvc/{action}/{id}",
|
|
|
|
|
|
new { controller = "RenderMvc", action = "Index", id = UrlParameter.Optional }
|
|
|
|
|
|
);
|
2012-09-25 13:09:59 +07:00
|
|
|
|
defaultRoute.RouteHandler = new RenderRouteHandler(ControllerBuilder.Current.GetControllerFactory());
|
|
|
|
|
|
|
2012-10-16 01:33:35 +05:00
|
|
|
|
//Create the install routes
|
|
|
|
|
|
var installPackageRoute = RouteTable.Routes.MapRoute(
|
|
|
|
|
|
"Umbraco_install_packages",
|
|
|
|
|
|
"Install/PackageInstaller/{action}/{id}",
|
|
|
|
|
|
new { controller = "InstallPackage", action = "Index", id = UrlParameter.Optional }
|
|
|
|
|
|
);
|
|
|
|
|
|
installPackageRoute.DataTokens.Add("area", umbracoPath);
|
2012-09-26 11:04:07 +07:00
|
|
|
|
|
|
|
|
|
|
//we need to find the surface controllers and route them
|
2012-09-26 13:42:03 +07:00
|
|
|
|
var surfaceControllers = SurfaceControllerResolver.Current.RegisteredSurfaceControllers.ToArray();
|
2012-09-26 11:04:07 +07:00
|
|
|
|
|
|
|
|
|
|
//local surface controllers do not contain the attribute
|
2012-09-26 13:42:03 +07:00
|
|
|
|
var localSurfaceControlleres = surfaceControllers.Where(x => PluginController.GetMetadata(x).AreaName.IsNullOrWhiteSpace());
|
2012-09-26 11:04:07 +07:00
|
|
|
|
foreach (var s in localSurfaceControlleres)
|
|
|
|
|
|
{
|
2012-09-26 13:42:03 +07:00
|
|
|
|
var meta = PluginController.GetMetadata(s);
|
2012-09-26 11:04:07 +07:00
|
|
|
|
var route = RouteTable.Routes.MapRoute(
|
|
|
|
|
|
string.Format("umbraco-{0}-{1}", "surface", meta.ControllerName),
|
|
|
|
|
|
umbracoPath + "/Surface/" + meta.ControllerName + "/{action}/{id}",//url to match
|
|
|
|
|
|
new { controller = meta.ControllerName, action = "Index", id = UrlParameter.Optional },
|
|
|
|
|
|
new[] { meta.ControllerNamespace }); //only match this namespace
|
|
|
|
|
|
route.DataTokens.Add("umbraco", "surface"); //ensure the umbraco token is set
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//need to get the plugin controllers that are unique to each area (group by)
|
|
|
|
|
|
//TODO: One day when we have more plugin controllers, we will need to do a group by on ALL of them to pass into the ctor of PluginControllerArea
|
2012-09-26 13:42:03 +07:00
|
|
|
|
var pluginSurfaceControlleres = surfaceControllers.Where(x => !PluginController.GetMetadata(x).AreaName.IsNullOrWhiteSpace());
|
|
|
|
|
|
var groupedAreas = pluginSurfaceControlleres.GroupBy(controller => PluginController.GetMetadata(controller).AreaName);
|
2012-09-26 11:04:07 +07:00
|
|
|
|
//loop through each area defined amongst the controllers
|
|
|
|
|
|
foreach(var g in groupedAreas)
|
|
|
|
|
|
{
|
|
|
|
|
|
//create an area for the controllers (this will throw an exception if all controllers are not in the same area)
|
2012-09-26 13:42:03 +07:00
|
|
|
|
var pluginControllerArea = new PluginControllerArea(g.Select(PluginController.GetMetadata));
|
2012-09-26 11:04:07 +07:00
|
|
|
|
//register it
|
|
|
|
|
|
RouteTable.Routes.RegisterArea(pluginControllerArea);
|
|
|
|
|
|
}
|
2012-08-14 23:35:34 +06:00
|
|
|
|
}
|
|
|
|
|
|
|
2012-09-25 13:09:59 +07:00
|
|
|
|
|
|
|
|
|
|
|
2012-08-01 22:06:15 +06:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Initializes all web based and core resolves
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected override void InitializeResolvers()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.InitializeResolvers();
|
|
|
|
|
|
|
2012-09-25 13:09:59 +07:00
|
|
|
|
SurfaceControllerResolver.Current = new SurfaceControllerResolver(
|
|
|
|
|
|
PluginManager.Current.ResolveSurfaceControllers());
|
|
|
|
|
|
|
2012-09-08 07:13:03 +07:00
|
|
|
|
//the base creates the PropertyEditorValueConvertersResolver but we want to modify it in the web app and replace
|
|
|
|
|
|
//the TinyMcePropertyEditorValueConverter with the RteMacroRenderingPropertyEditorValueConverter
|
|
|
|
|
|
PropertyEditorValueConvertersResolver.Current.RemoveType<TinyMcePropertyEditorValueConverter>();
|
|
|
|
|
|
PropertyEditorValueConvertersResolver.Current.AddType<RteMacroRenderingPropertyEditorValueConverter>();
|
|
|
|
|
|
|
2012-09-08 13:22:45 +07:00
|
|
|
|
PublishedContentStoreResolver.Current = new PublishedContentStoreResolver(new DefaultPublishedContentStore());
|
2012-09-14 09:09:23 +07:00
|
|
|
|
PublishedMediaStoreResolver.Current = new PublishedMediaStoreResolver(new DefaultPublishedMediaStore());
|
2012-08-10 13:38:02 +06:00
|
|
|
|
|
2012-08-07 21:40:34 +06:00
|
|
|
|
FilteredControllerFactoriesResolver.Current = new FilteredControllerFactoriesResolver(
|
|
|
|
|
|
//add all known factories, devs can then modify this list on application startup either by binding to events
|
|
|
|
|
|
//or in their own global.asax
|
|
|
|
|
|
new[]
|
|
|
|
|
|
{
|
|
|
|
|
|
typeof (RenderControllerFactory)
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2012-08-01 22:06:15 +06:00
|
|
|
|
LastChanceLookupResolver.Current = new LastChanceLookupResolver(new DefaultLastChanceLookup());
|
|
|
|
|
|
|
|
|
|
|
|
DocumentLookupsResolver.Current = new DocumentLookupsResolver(
|
|
|
|
|
|
//add all known resolvers in the correct order, devs can then modify this list on application startup either by binding to events
|
|
|
|
|
|
//or in their own global.asax
|
2012-08-07 21:40:34 +06:00
|
|
|
|
new[]
|
|
|
|
|
|
{
|
2012-08-30 08:26:01 +07:00
|
|
|
|
typeof (LookupByPageIdQuery),
|
2012-08-07 21:40:34 +06:00
|
|
|
|
typeof (LookupByNiceUrl),
|
2012-08-30 08:26:01 +07:00
|
|
|
|
typeof (LookupByIdPath),
|
2012-08-07 21:40:34 +06:00
|
|
|
|
typeof (LookupByNiceUrlAndTemplate),
|
|
|
|
|
|
typeof (LookupByProfile),
|
|
|
|
|
|
typeof (LookupByAlias)
|
|
|
|
|
|
});
|
2012-08-04 06:20:06 +06:00
|
|
|
|
|
2012-10-02 02:33:19 +05:00
|
|
|
|
RoutesCacheResolver.Current = new RoutesCacheResolver(new DefaultRoutesCache(_isForTesting == false));
|
2012-08-04 06:20:06 +06:00
|
|
|
|
|
|
|
|
|
|
ThumbnailProvidersResolver.Current = new ThumbnailProvidersResolver(
|
|
|
|
|
|
PluginManager.Current.ResolveThumbnailProviders());
|
2012-08-15 23:20:37 +06:00
|
|
|
|
|
|
|
|
|
|
CultureDictionaryFactoryResolver.Current = new CultureDictionaryFactoryResolver(
|
|
|
|
|
|
new DefaultCultureDictionaryFactory());
|
2012-08-17 04:27:47 +06:00
|
|
|
|
|
2012-08-01 22:06:15 +06:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|