using System; using System.Collections.Concurrent; using System.Web.Mvc; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Composing; using Umbraco.Core.Services; using Umbraco.Web.Security; using Umbraco.Web.WebApi; namespace Umbraco.Web.Mvc { /// /// Provides a base class for plugin controllers. /// public abstract class PluginController : Controller, IDiscoverable { private static readonly ConcurrentDictionary MetadataStorage = new ConcurrentDictionary(); private UmbracoHelper _umbracoHelper; // for debugging purposes internal Guid InstanceId { get; } = Guid.NewGuid(); // note // properties marked as [Inject] below will be property-injected (vs constructor-injected) in // order to keep the constuctor as light as possible, so that ppl implementing eg a SurfaceController // don't need to implement complex constructors + need to refactor them each time we change ours. // this means that these properties have a setter. // what can go wrong? /// /// Gets or sets the Umbraco context. /// public virtual UmbracoContext UmbracoContext { get; } /// /// Gets or sets the database context. /// public IUmbracoDatabaseFactory DatabaseFactory { get; } /// /// Gets or sets the services context. /// public ServiceContext Services { get; } /// /// Gets or sets the application cache. /// public CacheHelper ApplicationCache { get; } /// /// Gets or sets the logger. /// public ILogger Logger { get; } /// /// Gets or sets the profiling logger. /// public ProfilingLogger ProfilingLogger { get; } /// /// Gets the membership helper. /// public MembershipHelper Members => Umbraco.MembershipHelper; /// /// Gets the Umbraco helper. /// public UmbracoHelper Umbraco { get { return _umbracoHelper ?? (_umbracoHelper = new UmbracoHelper(UmbracoContext, Services, ApplicationCache)); } internal set // tests { _umbracoHelper = value; } } /// /// Gets metadata for this instance. /// internal PluginControllerMetadata Metadata => GetMetadata(GetType()); protected PluginController() : this( Current.Container.GetInstance(), Current.Container.GetInstance(), Current.Container.GetInstance(), Current.Container.GetInstance(), Current.Container.GetInstance(), Current.Container.GetInstance() ) { } protected PluginController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) { UmbracoContext = umbracoContext; DatabaseFactory = databaseFactory; Services = services; ApplicationCache = applicationCache; Logger = logger; ProfilingLogger = profilingLogger; } /// /// Gets metadata for a controller type. /// /// The controller type. /// Metadata for the controller type. internal static PluginControllerMetadata GetMetadata(Type controllerType) { return MetadataStorage.GetOrAdd(controllerType, type => { // plugin controller? back-office controller? var pluginAttribute = controllerType.GetCustomAttribute(false); var backOfficeAttribute = controllerType.GetCustomAttribute(true); return new PluginControllerMetadata { AreaName = pluginAttribute?.AreaName, ControllerName = ControllerExtensions.GetControllerName(controllerType), ControllerNamespace = controllerType.Namespace, ControllerType = controllerType, IsBackOffice = backOfficeAttribute != null }; }); } } }