114 lines
5.2 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|