2012-08-01 22:06:15 +06:00
using System ;
2012-08-07 21:40:34 +06:00
using System.Collections.Generic ;
2013-11-28 14:27:58 +11:00
using System.Collections.Specialized ;
2014-01-09 15:58:06 +11:00
using System.Configuration ;
2012-09-26 11:04:07 +07:00
using System.Linq ;
2013-03-11 23:46:47 +06:00
using System.Web ;
2014-01-09 15:58:06 +11:00
using System.Web.Configuration ;
2013-02-26 03:45:39 +06:00
using System.Web.Http ;
2014-06-27 13:34:15 +10:00
using System.Web.Http.Dispatcher ;
2015-12-18 14:45:28 +01:00
using System.Web.Mvc ;
2012-08-07 21:40:34 +06:00
using System.Web.Routing ;
2015-12-18 14:45:28 +01:00
using ClientDependency.Core.Config ;
using Examine ;
2015-12-20 17:09:46 +01:00
using LightInject ;
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 ;
2013-02-12 03:46:27 +06:00
using Umbraco.Core.Logging ;
2013-08-29 17:14:34 +10:00
using Umbraco.Core.Macros ;
2012-09-08 07:13:03 +07:00
using Umbraco.Core.PropertyEditors ;
2013-09-23 16:30:24 +02:00
using Umbraco.Core.PropertyEditors.ValueConverters ;
2013-02-12 03:46:27 +06:00
using Umbraco.Core.Sync ;
2012-08-15 23:20:37 +06:00
using Umbraco.Web.Dictionary ;
2014-02-26 04:15:14 +11:00
using Umbraco.Web.Install ;
2012-11-21 07:14:40 -01:00
using Umbraco.Web.Media ;
2012-08-04 06:20:06 +06:00
using Umbraco.Web.Media.ThumbnailProviders ;
2012-08-07 21:40:34 +06:00
using Umbraco.Web.Mvc ;
2013-02-05 06:31:13 -01:00
using Umbraco.Web.PublishedCache ;
2015-01-21 12:48:08 +11:00
using Umbraco.Web.PublishedCache.XmlPublishedCache ;
2012-08-01 22:06:15 +06:00
using Umbraco.Web.Routing ;
2013-07-31 18:21:27 +10:00
using Umbraco.Web.Security ;
2013-11-28 14:27:58 +11:00
using Umbraco.Web.UI.JavaScript ;
2013-02-26 22:14:32 +06:00
using Umbraco.Web.WebApi ;
2015-12-20 17:28:38 +01:00
using Umbraco.Core.Events ;
2016-01-22 17:09:44 +01:00
using Umbraco.Core.Cache ;
2015-07-23 20:04:40 +02:00
using Umbraco.Core.Services ;
2016-02-17 17:14:54 +01:00
using Umbraco.Web.Services ;
2016-01-20 16:57:31 +01:00
using Umbraco.Web.Editors ;
2016-02-17 17:14:54 +01:00
using Umbraco.Core.DependencyInjection ;
2016-06-30 11:30:52 +02:00
using Umbraco.Core.Persistence ;
2016-05-26 17:12:04 +02:00
using Umbraco.Core.Persistence.UnitOfWork ;
using Umbraco.Core.Services.Changes ;
2016-05-26 19:20:33 +02:00
using Umbraco.Core.Strings ;
2016-05-26 17:12:04 +02:00
using Umbraco.Web.Cache ;
2016-03-22 16:29:04 +01:00
using Umbraco.Web.DependencyInjection ;
2016-06-13 17:42:05 +02:00
using Umbraco.Web.HealthCheck ;
2016-03-17 15:28:46 +01:00
using Umbraco.Web._Legacy.Actions ;
2016-05-31 19:24:33 +02:00
using UmbracoExamine ;
2016-03-17 15:26:22 +01:00
using Action = System . Action ;
2015-03-04 12:16:28 +01:00
using GlobalSettings = Umbraco . Core . Configuration . GlobalSettings ;
2013-10-02 17:48:44 +02:00
using ProfilingViewEngine = Umbraco . Core . Profiling . ProfilingViewEngine ;
2016-05-18 23:34:56 +02:00
using TypeHelper = Umbraco . Core . Plugins . TypeHelper ;
2012-08-01 22:06:15 +06:00
2012-09-25 13:09:59 +07:00
2012-08-01 22:06:15 +06:00
namespace Umbraco.Web
{
2013-01-18 08:47:38 -01:00
/// <summary>
2016-01-28 14:19:32 +01:00
/// A bootstrapper for the Umbraco application which initializes all objects including the Web portion of the application
2013-01-18 08:47:38 -01:00
/// </summary>
2013-01-27 12:59:41 -01:00
public class WebBootManager : CoreBootManager
2013-01-18 08:47:38 -01:00
{
2016-04-22 23:23:27 +02:00
//TODO: Fix this - we need to manually perform re-indexing on startup when necessary Examine lib no longer does this
2014-12-09 19:07:14 +11:00
//NOTE: see the Initialize method for what this is used for
2016-04-22 23:23:27 +02:00
//private static readonly List<BaseIndexProvider> IndexesToRebuild = new List<BaseIndexProvider>();
2012-08-14 12:03:34 +06:00
2013-06-18 14:59:00 +10:00
public WebBootManager ( UmbracoApplicationBase umbracoApplication )
2015-07-22 12:44:29 +02:00
: base ( umbracoApplication )
2016-05-26 17:12:04 +02:00
{ }
2012-10-02 02:33:19 +05:00
2013-01-18 08:47:38 -01:00
/// <summary>
/// Constructor for unit tests, ensures some resolvers are not initialized
/// </summary>
/// <param name="umbracoApplication"></param>
2015-07-22 12:44:29 +02:00
/// <param name="logger"></param>
2013-01-18 08:47:38 -01:00
/// <param name="isForTesting"></param>
2015-07-22 12:44:29 +02:00
internal WebBootManager ( UmbracoApplicationBase umbracoApplication , ProfilingLogger logger , bool isForTesting )
: base ( umbracoApplication , logger )
2016-05-26 17:12:04 +02:00
{ }
2012-08-01 22:06:15 +06:00
2013-01-18 08:47:38 -01:00
/// <summary>
/// Initialize objects before anything during the boot cycle happens
/// </summary>
/// <returns></returns>
public override IBootManager Initialize ()
2013-06-18 14:59:00 +10:00
{
2016-04-22 23:23:27 +02:00
//TODO: Fix this - we need to manually perform re-indexing on startup when necessary Examine lib no longer does this
////This is basically a hack for this item: http://issues.umbraco.org/issue/U4-5976
// // when Examine initializes it will try to rebuild if the indexes are empty, however in many cases not all of Examine's
// // event handlers will be assigned during bootup when the rebuilding starts which is a problem. So with the examine 0.1.58.2941 build
// // it has an event we can subscribe to in order to cancel this rebuilding process, but what we'll do is cancel it and postpone the rebuilding until the
// // boot process has completed. It's a hack but it works.
//ExamineManager.Instance.BuildingEmptyIndexOnStartup += OnInstanceOnBuildingEmptyIndexOnStartup;
2014-12-09 19:07:14 +11:00
2013-01-18 08:47:38 -01:00
base . Initialize ();
2012-08-01 22:06:15 +06:00
2015-01-21 12:48:08 +11:00
//setup mvc and webapi services
SetupMvcAndWebApi ();
2013-01-18 08:47:38 -01:00
// 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
2014-01-09 15:58:06 +11:00
var section = ConfigurationManager . GetSection ( "system.web/httpRuntime" ) as HttpRuntimeSection ;
if ( section != null )
{
//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 );
}
2013-11-28 14:27:58 +11:00
//Register a custom renderer - used to process property editor dependencies
var renderer = new DependencyPathRenderer ();
2015-03-18 19:04:49 +11:00
renderer . Initialize ( "Umbraco.DependencyPathRenderer" , new NameValueCollection
{
{ "compositeFileHandlerPath" , ClientDependencySettings . Instance . CompositeFileHandlerPath }
});
2013-11-28 14:27:58 +11:00
ClientDependencySettings . Instance . MvcRendererCollection . Add ( renderer );
2016-01-28 14:19:32 +01:00
2015-12-08 21:19:41 +00:00
// Disable the X-AspNetMvc-Version HTTP Header
MvcHandler . DisableMvcResponseHeader = true ;
2013-11-28 14:27:58 +11:00
2016-06-09 11:57:13 +02:00
InstallHelper . DeleteLegacyInstaller ();
2014-03-07 12:09:30 +01:00
2013-01-18 08:47:38 -01:00
return this ;
}
2015-01-21 12:48:08 +11:00
2013-03-11 23:46:47 +06:00
/// <summary>
2016-01-28 14:19:32 +01:00
/// Override this method in order to ensure that the UmbracoContext is also created, this can only be
2013-03-11 23:46:47 +06:00
/// created after resolution is frozen!
/// </summary>
protected override void FreezeResolution ()
{
base . FreezeResolution ();
//before we do anything, we'll ensure the umbraco context
//see: http://issues.umbraco.org/issue/U4-1717
2013-07-31 18:21:27 +10:00
var httpContext = new HttpContextWrapper ( UmbracoApplication . Context );
UmbracoContext . EnsureContext (
2016-05-26 17:12:04 +02:00
httpContext , ApplicationContext ,
FacadeServiceResolver . Current . Service ,
2015-07-22 12:44:29 +02:00
new WebSecurity ( httpContext , ApplicationContext ),
2016-01-28 14:19:32 +01:00
UmbracoConfig . For . UmbracoSettings (),
UrlProviderResolver . Current . Providers ,
2015-07-22 12:44:29 +02:00
false );
2013-03-11 23:46:47 +06:00
}
2013-05-13 21:11:03 -10:00
/// <summary>
/// Ensure the current profiler is the web profiler
/// </summary>
2015-01-21 12:48:08 +11:00
protected override IProfiler CreateProfiler ()
2013-05-13 21:11:03 -10:00
{
2015-01-21 12:48:08 +11:00
return new WebProfiler ();
2015-12-18 14:24:17 +01:00
}
2015-12-20 17:28:38 +01:00
/// <summary>
2013-01-18 08:47:38 -01:00
/// Ensure that the OnApplicationStarted methods of the IApplicationEvents are called
/// </summary>
/// <param name="afterComplete"></param>
/// <returns></returns>
public override IBootManager Complete ( Action < ApplicationContext > afterComplete )
{
2014-02-26 04:15:14 +11:00
//Wrap viewengines in the profiling engine
WrapViewEngines ( ViewEngines . Engines );
2013-10-02 17:48:44 +02:00
2016-03-10 18:00:14 +01:00
//add global filters
ConfigureGlobalFilters ();
2014-02-26 04:15:14 +11:00
//set routes
2013-01-18 08:47:38 -01:00
CreateRoutes ();
2012-09-25 13:09:59 +07:00
2013-01-18 08:47:38 -01:00
base . Complete ( afterComplete );
2012-09-29 07:20:23 +07:00
2016-04-29 00:50:26 +02:00
//rebuild any empty indexes
//TODO: Do we want to make this optional? otherwise the only way to disable this on startup
// would be to implement a custom WebBootManager and override this method
RebuildIndexes ( true );
2013-02-14 23:26:29 +06:00
2015-05-08 19:13:58 +10:00
//Now ensure webapi is initialized after everything
GlobalConfiguration . Configuration . EnsureInitialized ();
2013-01-18 08:47:38 -01:00
return this ;
}
2012-08-01 22:06:15 +06:00
2016-03-10 18:00:14 +01:00
internal static void ConfigureGlobalFilters ()
{
GlobalFilters . Filters . Add ( new EnsurePartialViewMacroViewContextFilterAttribute ());
}
2014-02-26 04:15:14 +11:00
internal static void WrapViewEngines ( IList < IViewEngine > viewEngines )
{
if ( viewEngines == null || viewEngines . Count == 0 ) return ;
2013-10-03 11:01:37 +02:00
2014-02-26 04:15:14 +11:00
var originalEngines = viewEngines . Select ( e => e ). ToArray ();
viewEngines . Clear ();
foreach ( var engine in originalEngines )
{
var wrappedEngine = engine is ProfilingViewEngine ? engine : new ProfilingViewEngine ( engine );
viewEngines . Add ( wrappedEngine );
}
}
2013-10-03 11:01:37 +02:00
2014-02-26 04:15:14 +11:00
/// <summary>
2013-07-02 17:47:20 +10:00
/// Creates the application cache based on the HttpRuntime cache
/// </summary>
2015-01-21 12:48:08 +11:00
protected override CacheHelper CreateApplicationCache ()
2013-07-02 17:47:20 +10:00
{
2013-08-09 11:37:57 +10:00
//create a web-based cache helper
2016-01-22 17:09:44 +01:00
var cacheHelper = new CacheHelper (
2016-01-28 14:19:32 +01:00
//we need to have the dep clone runtime cache provider to ensure
2016-01-22 17:09:44 +01:00
//all entities are cached properly (cloned in and cloned out)
new DeepCloneRuntimeCacheProvider ( new HttpRuntimeCacheProvider ( HttpRuntime . Cache )),
new StaticCacheProvider (),
2016-02-24 14:16:48 +01:00
//we need request based cache when running in web-based context
new HttpRequestCacheProvider (),
2016-01-22 17:09:44 +01:00
new IsolatedRuntimeCache ( type =>
2016-01-28 14:19:32 +01:00
//we need to have the dep clone runtime cache provider to ensure
2016-01-22 17:09:44 +01:00
//all entities are cached properly (cloned in and cloned out)
new DeepCloneRuntimeCacheProvider ( new ObjectCacheRuntimeCacheProvider ())));
return cacheHelper ;
2013-07-02 17:47:20 +10:00
}
2013-01-18 08:47:38 -01:00
/// <summary>
/// Creates the routes
/// </summary>
protected internal void CreateRoutes ()
{
var umbracoPath = GlobalSettings . UmbracoMvcArea ;
2014-02-26 04:15:14 +11:00
2013-01-18 08:47:38 -01:00
//Create the front-end route
var defaultRoute = RouteTable . Routes . MapRoute (
"Umbraco_default" ,
2013-02-19 06:18:51 +06:00
umbracoPath + "/RenderMvc/{action}/{id}" ,
2013-01-18 08:47:38 -01:00
new { controller = "RenderMvc" , action = "Index" , id = UrlParameter . Optional }
);
defaultRoute . RouteHandler = new RenderRouteHandler ( ControllerBuilder . Current . GetControllerFactory ());
2012-09-25 13:09:59 +07:00
2014-02-26 04:15:14 +11:00
//register install routes
2014-03-05 22:42:51 +11:00
RouteTable . Routes . RegisterArea < UmbracoInstallArea >();
2014-02-26 04:15:14 +11:00
2013-06-03 21:38:43 -10:00
//register all back office routes
2014-03-05 22:42:51 +11:00
RouteTable . Routes . RegisterArea < BackOfficeArea >();
2012-09-26 11:04:07 +07:00
2013-05-29 20:25:29 -10:00
//plugin controllers must come first because the next route will catch many things
RoutePluginControllers ();
2013-06-03 21:38:43 -10:00
}
2015-01-21 12:48:08 +11:00
2013-02-26 03:45:39 +06:00
private void RoutePluginControllers ()
{
var umbracoPath = GlobalSettings . UmbracoMvcArea ;
2012-09-26 11:04:07 +07:00
2013-02-26 03:45:39 +06:00
//we need to find the plugin controllers and route them
var pluginControllers =
SurfaceControllerResolver . Current . RegisteredSurfaceControllers . Concat (
UmbracoApiControllerResolver . Current . RegisteredUmbracoApiControllers ). ToArray ();
2013-06-10 10:36:59 -02:00
//local controllers do not contain the attribute
2013-02-26 03:45:39 +06:00
var localControllers = pluginControllers . Where ( x => PluginController . GetMetadata ( x ). AreaName . IsNullOrWhiteSpace ());
foreach ( var s in localControllers )
2013-01-18 08:47:38 -01:00
{
2013-02-26 03:45:39 +06:00
if ( TypeHelper . IsTypeAssignableFrom < SurfaceController >( s ))
{
RouteLocalSurfaceController ( s , umbracoPath );
}
else if ( TypeHelper . IsTypeAssignableFrom < UmbracoApiController >( s ))
{
RouteLocalApiController ( s , umbracoPath );
}
2013-01-18 08:47:38 -01:00
}
2012-08-14 23:35:34 +06:00
2013-01-18 08:47:38 -01:00
//need to get the plugin controllers that are unique to each area (group by)
2015-12-20 17:28:38 +01:00
var pluginSurfaceControlleres = pluginControllers . Where ( x => PluginController . GetMetadata ( x ). AreaName . IsNullOrWhiteSpace () == false );
2013-01-18 08:47:38 -01:00
var groupedAreas = pluginSurfaceControlleres . GroupBy ( controller => PluginController . GetMetadata ( controller ). AreaName );
//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)
var pluginControllerArea = new PluginControllerArea ( g . Select ( PluginController . GetMetadata ));
//register it
RouteTable . Routes . RegisterArea ( pluginControllerArea );
}
}
2012-09-25 13:09:59 +07:00
2013-02-26 03:45:39 +06:00
private void RouteLocalApiController ( Type controller , string umbracoPath )
{
var meta = PluginController . GetMetadata ( controller );
2014-01-15 13:17:38 +11:00
//url to match
var routePath = meta . IsBackOffice == false
? umbracoPath + "/Api/" + meta . ControllerName + "/{action}/{id}"
: umbracoPath + "/BackOffice/Api/" + meta . ControllerName + "/{action}/{id}" ;
2014-02-26 04:15:14 +11:00
2013-02-26 03:45:39 +06:00
var route = RouteTable . Routes . MapHttpRoute (
string . Format ( "umbraco-{0}-{1}" , "api" , meta . ControllerName ),
2014-02-26 04:15:14 +11:00
routePath ,
2014-03-05 22:42:51 +11:00
new { controller = meta . ControllerName , id = UrlParameter . Optional },
new [] { meta . ControllerNamespace });
2013-02-26 03:45:39 +06:00
//web api routes don't set the data tokens object
if ( route . DataTokens == null )
2014-02-26 04:15:14 +11:00
{
2013-02-26 03:45:39 +06:00
route . DataTokens = new RouteValueDictionary ();
}
2016-02-16 11:17:47 +01:00
route . DataTokens . Add ( Core . Constants . Web . UmbracoDataToken , "api" ); //ensure the umbraco token is set
2013-02-26 03:45:39 +06:00
}
2015-07-23 20:04:40 +02:00
2013-02-26 03:45:39 +06:00
private void RouteLocalSurfaceController ( Type controller , string umbracoPath )
{
var meta = PluginController . GetMetadata ( controller );
var route = RouteTable . Routes . MapRoute (
string . Format ( "umbraco-{0}-{1}" , "surface" , meta . ControllerName ),
umbracoPath + "/Surface/" + meta . ControllerName + "/{action}/{id}" , //url to match
2014-02-26 04:15:14 +11:00
new { controller = meta . ControllerName , action = "Index" , id = UrlParameter . Optional },
2013-02-26 03:45:39 +06:00
new [] { meta . ControllerNamespace }); //look in this namespace to create the controller
2016-02-16 11:17:47 +01:00
route . DataTokens . Add ( Core . Constants . Web . UmbracoDataToken , "surface" ); //ensure the umbraco token is set
2013-06-03 21:38:43 -10:00
route . DataTokens . Add ( "UseNamespaceFallback" , false ); //Don't look anywhere else except this namespace!
2013-02-26 03:45:39 +06:00
//make it use our custom/special SurfaceMvcHandler
route . RouteHandler = new SurfaceRouteHandler ();
}
2012-11-12 10:50:23 +05:00
2015-01-21 12:48:08 +11:00
/// <summary>
2015-12-20 20:09:25 +01:00
/// Build the core container which contains all core things requird to build an app context
2015-01-21 12:48:08 +11:00
/// </summary>
2015-12-20 20:09:25 +01:00
internal override void ConfigureCoreServices ( ServiceContainer container )
2015-01-21 12:48:08 +11:00
{
2015-12-20 20:09:25 +01:00
base . ConfigureCoreServices ( container );
2015-01-21 12:48:08 +11:00
2016-05-30 19:54:36 +02:00
// configure the temp. Current
Current . Container = container ;
2016-06-09 11:57:13 +02:00
// register model mappers
2016-03-22 16:29:04 +01:00
container . RegisterFrom < WebModelMappersCompositionRoot >();
2016-06-09 11:57:13 +02:00
// support web request scope
// note: everything that is PerRequestLifeTime will be disposed by LightInject at the end of the request
2015-12-21 15:02:21 +01:00
container . EnablePerWebRequestScope ();
2016-06-09 11:57:13 +02:00
// register the http context and umbraco context accessors
2016-06-09 18:45:16 +02:00
// we *should* use the HttpContextUmbracoContextAccessor, however there are cases when
// we have no http context, eg when booting Umbraco or in background threads, so instead
// let's use an hybrid accessor that can fall back to a ThreadStatic context.
2016-06-09 11:57:13 +02:00
container . RegisterSingleton < IHttpContextAccessor , AspNetHttpContextAccessor >(); // replaces HttpContext.Current
2016-06-09 18:45:16 +02:00
container . RegisterSingleton < IUmbracoContextAccessor , HybridUmbracoContextAccessor >();
2016-05-26 17:12:04 +02:00
2016-06-09 11:57:13 +02:00
// register a per-request HttpContextBase object
// is per-request so only one wrapper is created per request
container . Register < HttpContextBase >( factory => new HttpContextWrapper ( factory . GetInstance < IHttpContextAccessor >(). HttpContext ), new PerRequestLifeTime ());
// register the facade accessor - the "current" facade is in the umbraco context
container . RegisterSingleton < IFacadeAccessor , UmbracoContextFacadeAccessor >();
2016-06-30 11:30:52 +02:00
// register the umbraco database accessor
// have to use the hybrid thing...
container . RegisterSingleton < IUmbracoDatabaseAccessor , HybridUmbracoDatabaseAccessor >();
2016-06-09 11:57:13 +02:00
// register the XML facade service
//container.RegisterSingleton<IFacadeService>(factory => new PublishedCache.XmlPublishedCache.FacadeService(
2016-05-27 14:26:28 +02:00
// factory.GetInstance<ServiceContext>(),
// factory.GetInstance<IDatabaseUnitOfWorkProvider>(),
// factory.GetInstance<CacheHelper>().RequestCache,
2016-06-09 11:57:13 +02:00
// factory.GetAllInstances<IUrlSegmentProvider>(),
// factory.GetInstance<IFacadeAccessor>()));
// register the NuCache facade service
2016-05-27 14:26:28 +02:00
container . RegisterSingleton < IFacadeService >( factory => new PublishedCache . NuCache . FacadeService (
new PublishedCache . NuCache . FacadeService . Options { FacadeCacheIsApplicationRequestCache = true },
factory . GetInstance < ApplicationContext >(). MainDom ,
2016-05-26 17:12:04 +02:00
factory . GetInstance < ServiceContext >(),
factory . GetInstance < IDatabaseUnitOfWorkProvider >(),
2016-06-09 11:57:13 +02:00
factory . GetInstance < IFacadeAccessor >(),
2016-05-27 14:26:28 +02:00
factory . GetInstance < ILogger >()));
2015-12-21 17:09:31 +01:00
2016-06-09 11:57:13 +02:00
// register a per-request UmbracoContext object
// no real need to be per request but assuming it is faster
container . Register ( factory => factory . GetInstance < IUmbracoContextAccessor >(). UmbracoContext , new PerRequestLifeTime ());
// register the umbraco helper
2016-02-17 17:14:54 +01:00
container . RegisterSingleton < UmbracoHelper >();
2015-12-21 15:02:21 +01:00
2016-06-09 11:57:13 +02:00
// replace some services
2016-06-30 11:30:52 +02:00
container . RegisterSingleton < IEventMessagesFactory , DefaultEventMessagesFactory >();
container . RegisterSingleton < IEventMessagesAccessor , HybridEventMessagesAccessor >();
2016-02-17 17:14:54 +01:00
container . RegisterSingleton < IApplicationTreeService , ApplicationTreeService >();
container . RegisterSingleton < ISectionService , SectionService >();
2016-05-31 19:24:33 +02:00
container . RegisterSingleton < IExamineIndexCollectionAccessor , ExamineIndexCollectionAccessor >();
2015-12-20 20:09:25 +01:00
}
2015-12-20 17:28:38 +01:00
2015-12-20 20:09:25 +01:00
/// <summary>
/// Called to customize the IoC container
/// </summary>
/// <param name="container"></param>
internal override void ConfigureApplicationServices ( ServiceContainer container )
{
base . ConfigureApplicationServices ( container );
2016-06-09 11:57:13 +02:00
// IoC setup for LightInject for MVC/WebApi
2015-12-20 17:28:38 +01:00
Container . EnableMvc ();
2016-06-09 11:57:13 +02:00
Container . RegisterMvcControllers ( PluginManager );
2015-01-21 12:48:08 +11:00
container . EnableWebApi ( GlobalConfiguration . Configuration );
container . RegisterApiControllers ( PluginManager );
}
2013-01-18 08:47:38 -01:00
/// <summary>
2016-01-28 14:19:32 +01:00
/// Initializes all web based and core resolves
2013-01-18 08:47:38 -01:00
/// </summary>
protected override void InitializeResolvers ()
{
base . InitializeResolvers ();
2013-02-06 09:53:13 +06:00
2015-01-21 12:48:08 +11:00
XsltExtensionsResolver . Current = new XsltExtensionsResolver ( ServiceProvider , ProfilingLogger . Logger , () => PluginManager . ResolveXsltExtensions ());
2013-08-29 17:14:34 +10:00
2016-01-20 16:57:31 +01:00
EditorValidationResolver . Current = new EditorValidationResolver ( ServiceProvider , LoggerResolver . Current . Logger , () => PluginManager . ResolveTypes < IEditorValidator >());
2013-08-29 17:14:34 +10:00
2013-04-28 16:09:24 -10:00
//set the default RenderMvcController
DefaultRenderMvcControllerResolver . Current = new DefaultRenderMvcControllerResolver ( typeof ( RenderMvcController ));
2015-07-15 17:27:01 +02:00
//Override the default server messenger, we need to check if the legacy dist calls is enabled, if that is the
// case, then we'll set the default messenger to be the old one, otherwise we'll set it to the db messenger
// which will always be on.
if ( UmbracoConfig . For . UmbracoSettings (). DistributedCall . Enabled )
2013-02-12 03:46:27 +06:00
{
2015-07-15 17:27:01 +02:00
//set the legacy one by default - this maintains backwards compat
ServerMessengerResolver . Current . SetServerMessenger ( new BatchedWebServiceServerMessenger (() =>
2014-02-26 04:15:14 +11:00
{
2016-01-28 14:19:32 +01:00
//we should not proceed to change this if the app/database is not configured since there will
2015-07-15 17:27:01 +02:00
// be no user, plus we don't need to have server messages sent if this is the case.
if ( ApplicationContext . IsConfigured && ApplicationContext . DatabaseContext . IsDatabaseConfigured )
2015-03-04 12:16:28 +01:00
{
2015-07-15 17:27:01 +02:00
//disable if they are not enabled
if ( UmbracoConfig . For . UmbracoSettings (). DistributedCall . Enabled == false )
{
return null ;
}
2015-03-04 12:16:28 +01:00
2015-07-15 17:27:01 +02:00
try
{
var user = ApplicationContext . Services . UserService . GetUserById ( UmbracoConfig . For . UmbracoSettings (). DistributedCall . UserId );
return new Tuple < string , string >( user . Username , user . RawPasswordValue );
}
catch ( Exception e )
{
2015-01-21 12:48:08 +11:00
ProfilingLogger . Logger . Error < WebBootManager >( "An error occurred trying to set the IServerMessenger during application startup" , e );
2015-07-15 17:27:01 +02:00
return null ;
}
2013-03-16 01:37:05 +06:00
}
2015-01-21 12:48:08 +11:00
ProfilingLogger . Logger . Warn < WebBootManager >( "Could not initialize the DefaultServerMessenger, the application is not configured or the database is not configured" );
2015-07-15 17:27:01 +02:00
return null ;
}));
}
else
{
2015-07-24 18:07:20 +02:00
2015-07-15 17:27:01 +02:00
ServerMessengerResolver . Current . SetServerMessenger ( new BatchedDatabaseServerMessenger (
2016-01-28 12:14:30 +01:00
ApplicationContext ,
true ,
//Default options for web including the required callbacks to build caches
new DatabaseServerMessengerOptions
2013-03-16 01:37:05 +06:00
{
2016-01-28 12:14:30 +01:00
//These callbacks will be executed if the server has not been synced
// (i.e. it is a new server or the lastsynced.txt file has been removed)
InitializingCallbacks = new Action []
{
//rebuild the xml cache file if the server is not synced
2016-05-26 17:12:04 +02:00
() =>
{
// rebuild the facade caches entirely, if the server is not synced
// this is equivalent to DistributedCache RefreshAllFacade but local only
// (we really should have a way to reuse RefreshAllFacade... locally)
// note: refresh all content & media caches does refresh content types too
IFacadeService svc = FacadeServiceResolver . Current . Service ;
bool ignored1 , ignored2 ;
2016-06-08 14:19:15 +02:00
svc . Notify ( new [] { new DomainCacheRefresher . JsonPayload ( 0 , DomainChangeTypes . RefreshAll ) });
2016-05-26 17:12:04 +02:00
svc . Notify ( new [] { new ContentCacheRefresher . JsonPayload ( 0 , TreeChangeTypes . RefreshAll ) }, out ignored1 , out ignored2 );
svc . Notify ( new [] { new MediaCacheRefresher . JsonPayload ( 0 , TreeChangeTypes . RefreshAll ) }, out ignored1 );
},
2016-01-28 12:14:30 +01:00
//rebuild indexes if the server is not synced
2016-01-28 14:19:32 +01:00
// NOTE: This will rebuild ALL indexes including the members, if developers want to target specific
// indexes then they can adjust this logic themselves.
2016-04-29 00:50:26 +02:00
() => RebuildIndexes ( false )
2016-01-28 12:14:30 +01:00
}
}));
2015-07-15 17:27:01 +02:00
}
2014-02-26 04:15:14 +11:00
2016-03-17 15:26:22 +01:00
ActionsResolver . Current = new ActionsResolver (
ServiceProvider , ProfilingLogger . Logger ,
() => PluginManager . ResolveActions ());
2013-01-18 08:47:38 -01:00
SurfaceControllerResolver . Current = new SurfaceControllerResolver (
2015-01-21 12:48:08 +11:00
ServiceProvider , ProfilingLogger . Logger ,
PluginManager . ResolveSurfaceControllers ());
2012-08-10 13:38:02 +06:00
2013-02-26 03:45:39 +06:00
UmbracoApiControllerResolver . Current = new UmbracoApiControllerResolver (
2015-01-21 12:48:08 +11:00
ServiceProvider , ProfilingLogger . Logger ,
PluginManager . ResolveUmbracoApiControllers ());
2013-02-26 03:45:39 +06:00
2013-09-23 16:30:24 +02:00
// both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be
// discovered when CoreBootManager configures the converters. We HAVE to remove one of them
// here because there cannot be two converters for one property editor - and we want the full
// RteMacroRenderingValueConverter that converts macros, etc. So remove TinyMceValueConverter.
2013-10-04 20:14:38 +02:00
// (the limited one, defined in Core, is there for tests)
2013-09-05 17:47:13 +02:00
PropertyValueConvertersResolver . Current . RemoveType < TinyMceValueConverter >();
2013-10-04 20:14:38 +02:00
// same for other converters
2016-05-26 17:12:04 +02:00
PropertyValueConvertersResolver . Current . RemoveType < TextStringValueConverter >();
PropertyValueConvertersResolver . Current . RemoveType < MarkdownEditorValueConverter >();
PropertyValueConvertersResolver . Current . RemoveType < ImageCropperValueConverter >();
2013-01-18 08:47:38 -01:00
2016-05-26 17:12:04 +02:00
FacadeServiceResolver . Current = new FacadeServiceResolver ( Container );
2014-06-27 13:34:15 +10:00
2013-01-18 08:47:38 -01:00
FilteredControllerFactoriesResolver . Current = new FilteredControllerFactoriesResolver (
2015-01-21 12:48:08 +11:00
ServiceProvider , ProfilingLogger . Logger ,
2013-01-31 10:06:25 -01:00
// add all known factories, devs can then modify this list on application
// startup either by binding to events or in their own global.asax
2013-01-18 08:47:38 -01:00
new []
2012-08-07 21:40:34 +06:00
{
typeof ( RenderControllerFactory )
});
2013-01-31 10:06:25 -01:00
UrlProviderResolver . Current = new UrlProviderResolver (
2015-05-05 19:14:56 +10:00
Container , ProfilingLogger . Logger ,
2016-06-13 23:27:22 +02:00
//typeof(AliasUrlProvider), // not enabled by default
2014-10-29 18:20:01 +10:00
typeof ( DefaultUrlProvider ),
typeof ( CustomRouteUrlProvider )
2013-01-31 10:06:25 -01:00
);
2015-01-21 12:48:08 +11:00
ContentLastChanceFinderResolver . Current = new ContentLastChanceFinderResolver ( Container , typeof ( ContentFinderByLegacy404 ));
2012-08-01 22:06:15 +06:00
2014-02-26 04:15:14 +11:00
ContentFinderResolver . Current = new ContentFinderResolver (
2015-01-21 12:48:08 +11:00
Container , ProfilingLogger . Logger ,
2013-08-26 15:47:48 +02:00
// all built-in finders in the correct order, devs can then modify this list
2016-06-13 23:27:22 +02:00
// on application startup, via an application event handler.
2014-02-26 04:15:14 +11:00
typeof ( ContentFinderByPageIdQuery ),
typeof ( ContentFinderByNiceUrl ),
typeof ( ContentFinderByIdPath ),
2015-01-21 12:48:08 +11:00
typeof ( ContentFinderByNiceUrlAndTemplate ),
typeof ( ContentFinderByProfile ),
2016-07-08 16:32:06 +02:00
typeof ( ContentFinderByUrlAlias ),
typeof ( ContentFinderByRedirectUrl )
2014-02-26 04:15:14 +11:00
);
2012-08-04 06:20:06 +06:00
2015-01-21 12:48:08 +11:00
SiteDomainHelperResolver . Current = new SiteDomainHelperResolver ( Container , typeof ( SiteDomainHelper ));
2013-02-19 06:37:25 -01:00
2013-01-18 08:47:38 -01:00
ThumbnailProvidersResolver . Current = new ThumbnailProvidersResolver (
2015-01-21 12:48:08 +11:00
Container , ProfilingLogger . Logger ,
PluginManager . ResolveThumbnailProviders ());
2012-08-15 23:20:37 +06:00
2012-11-21 07:14:40 -01:00
ImageUrlProviderResolver . Current = new ImageUrlProviderResolver (
2015-01-21 12:48:08 +11:00
ServiceProvider , ProfilingLogger . Logger ,
PluginManager . ResolveImageUrlProviders ());
2012-11-21 07:14:40 -01:00
2015-01-21 12:48:08 +11:00
CultureDictionaryFactoryResolver . Current = new CultureDictionaryFactoryResolver ( Container , typeof ( DefaultCultureDictionaryFactory ));
2016-07-08 17:58:01 +02:00
2016-07-20 12:44:15 +02:00
HealthCheckResolver . Current = new HealthCheckResolver ( Container , ProfilingLogger . Logger ,
() => PluginManager . ResolveTypes < HealthCheck . HealthCheck >()); // fixme XML cache vs NuCache?!
2013-01-18 08:47:38 -01:00
}
2012-08-01 22:06:15 +06:00
2015-01-21 12:48:08 +11:00
/// <summary>
/// Sets up MVC/WebApi services
/// </summary>
private void SetupMvcAndWebApi ()
{
2015-01-21 13:21:36 +11:00
//don't output the MVC version header (security)
MvcHandler . DisableMvcResponseHeader = true ;
2015-01-21 12:48:08 +11:00
//set master controller factory
ControllerBuilder . Current . SetControllerFactory (
new MasterControllerFactory ( FilteredControllerFactoriesResolver . Current ));
//set the render view engine
ViewEngines . Engines . Add ( new RenderViewEngine ());
//set the plugin view engine
ViewEngines . Engines . Add ( new PluginViewEngine ());
//set model binder
2016-06-30 19:06:44 +02:00
ModelBinderProviders . BinderProviders . Add ( new ContentModelBinder ()); // is a provider
2015-01-21 12:48:08 +11:00
////add the profiling action filter
//GlobalFilters.Filters.Add(new ProfilingActionFilter());
GlobalConfiguration . Configuration . Services . Replace ( typeof ( IHttpControllerSelector ),
new NamespaceHttpControllerSelector ( GlobalConfiguration . Configuration ));
}
2016-04-29 00:50:26 +02:00
protected virtual void RebuildIndexes ( bool onlyEmptyIndexes )
2016-01-28 12:14:30 +01:00
{
2016-04-29 00:50:26 +02:00
if ( ApplicationContext . IsConfigured == false || ApplicationContext . DatabaseContext . IsDatabaseConfigured == false )
{
return ;
}
2016-01-28 14:19:32 +01:00
2016-04-29 00:50:26 +02:00
foreach ( var indexer in ExamineManager . Instance . IndexProviders )
{
if ( onlyEmptyIndexes == false || indexer . Value . IsIndexNew ())
{
indexer . Value . RebuildIndex ();
}
}
2016-01-28 14:19:32 +01:00
2016-01-28 12:14:30 +01:00
}
2013-01-18 08:47:38 -01:00
}
2012-08-01 22:06:15 +06:00
}
2016-01-20 16:57:31 +01:00