Files
Umbraco-CMS/src/Umbraco.Web/Mvc/MasterControllerFactory.cs
2018-06-29 19:52:40 +02:00

114 lines
5.2 KiB
C#

using System;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
namespace Umbraco.Web.Mvc
{
/// <summary>
/// A controller factory which uses an internal list of <see cref="IFilteredControllerFactory"/> in order to invoke
/// different controller factories dependent upon their implementation of <see cref="IFilteredControllerFactory.CanHandle"/> for the current
/// request. Allows circumvention of MVC3's singly registered IControllerFactory.
/// </summary>
/// <remarks></remarks>
internal class MasterControllerFactory : DefaultControllerFactory
{
private readonly Func<FilteredControllerFactoryCollection> _factoriesAccessor;
private FilteredControllerFactoryCollection _factories;
/// <summary>
/// Initializes a new instance of the <see cref="MasterControllerFactory"/> with a factories accessor.
/// </summary>
/// <param name="factoriesAccessor">The factories accessor.</param>
public MasterControllerFactory(Func<FilteredControllerFactoryCollection> factoriesAccessor)
{
// note
// because the MasterControllerFactory needs to be ctored to be assigned to
// ControllerBuilder.Current when setting up Mvc and WebApi, it cannot be ctored by
// the IoC container - and yet we don't want that ctor to resolve the factories
// as that happen before everything is configured - so, passing a factories
// accessor func.
_factoriesAccessor = factoriesAccessor;
}
private IFilteredControllerFactory FactoryForRequest(RequestContext context)
{
if (_factories == null) _factories = _factoriesAccessor();
return _factories.FirstOrDefault(x => x.CanHandle(context));
}
/// <summary>
/// Creates the specified controller by using the specified request context.
/// </summary>
/// <param name="requestContext">The context of the HTTP request, which includes the HTTP context and route data.</param>
/// <param name="controllerName">The name of the controller.</param>
/// <returns>The controller.</returns>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="requestContext"/> parameter is null.</exception>
///
/// <exception cref="T:System.ArgumentException">The <paramref name="controllerName"/> parameter is null or empty.</exception>
/// <remarks></remarks>
public override IController CreateController(RequestContext requestContext, string controllerName)
{
var factory = FactoryForRequest(requestContext);
return factory != null
? factory.CreateController(requestContext, controllerName)
: base.CreateController(requestContext, controllerName);
}
/// <summary>
/// Retrieves the controller type for the specified name and request context.
/// </summary>
///
/// <returns>
/// The controller type.
/// </returns>
/// <param name="requestContext">The context of the HTTP request, which includes the HTTP context and route data.</param>
/// <param name="controllerName">The name of the controller.</param>
internal Type GetControllerTypeInternal(RequestContext requestContext, string controllerName)
{
var factory = FactoryForRequest(requestContext);
if (factory != null)
{
//check to see if the factory is of type UmbracoControllerFactory which exposes the GetControllerType method so we don't have to create
// an instance of the controller to figure out what it is. This is a work around for not having a breaking change for:
// http://issues.umbraco.org/issue/U4-1726
var umbFactory = factory as UmbracoControllerFactory;
if (umbFactory != null)
{
return umbFactory.GetControllerType(requestContext, controllerName);
}
//we have no choice but to instantiate the controller
var instance = factory.CreateController(requestContext, controllerName);
return instance?.GetType();
}
return GetControllerType(requestContext, controllerName);
}
/// <summary>
/// Releases the specified controller.
/// </summary>
/// <param name="icontroller">The controller to release.</param>
/// <remarks></remarks>
public override void ReleaseController(IController icontroller)
{
var released = false;
var controller = icontroller as Controller;
if (controller != null)
{
var requestContext = controller.ControllerContext.RequestContext;
var factory = FactoryForRequest(requestContext);
if (factory != null)
{
factory.ReleaseController(controller);
released = true;
}
}
if (released == false)
base.ReleaseController(icontroller);
}
}
}