diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 5e09893485..2b00ea75cf 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -38,6 +38,8 @@ namespace Umbraco.Tests.Routing protected override void FreezeResolution() { + DefaultRenderMvcControllerResolver.Current = new DefaultRenderMvcControllerResolver(typeof(RenderMvcController)); + SurfaceControllerResolver.Current = new SurfaceControllerResolver( PluginManager.Current.ResolveSurfaceControllers()); UmbracoApiControllerResolver.Current = new UmbracoApiControllerResolver( diff --git a/src/Umbraco.Web/Mvc/DefaultRenderMvcControllerResolver.cs b/src/Umbraco.Web/Mvc/DefaultRenderMvcControllerResolver.cs new file mode 100644 index 0000000000..7db655f5a8 --- /dev/null +++ b/src/Umbraco.Web/Mvc/DefaultRenderMvcControllerResolver.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web.Mvc; +using Umbraco.Core; +using Umbraco.Core.ObjectResolution; + +namespace Umbraco.Web.Mvc +{ + /// + /// A resolver used to resolve the default RenderMvcController that is used to render any front-end + /// Umbraco page when using MVC when there are no routes hijacked. + /// + public class DefaultRenderMvcControllerResolver : SingleObjectResolverBase + { + /// + /// Constructor accepting the default RenderMvcController + /// + /// + public DefaultRenderMvcControllerResolver(Type value) + : base(value) + { + ValidateType(value); + } + + /// + /// Returns the Default RenderMvcController type + /// + /// + public Type GetDefaultControllerType() + { + return Value; + } + + /// + /// Returns an instance of the default controller instance. + /// + public RenderMvcController GetControllerInstance() + { + //try the dependency resolver, then the activator + var instance = DependencyResolver.Current.GetService(Value) ?? Activator.CreateInstance(Value); + var result = instance as RenderMvcController; + if (result == null) + { + throw new InvalidOperationException("Could not create an instance of " + Value + " for the default RenderMvcController"); + } + return result; + } + + /// + /// Sets the default RenderMvcController type + /// + /// + public void SetDefaultControllerType(Type controllerType) + { + ValidateType(controllerType); + Value = controllerType; + } + + /// + /// Ensures that the type passed in is of type RenderMvcController + /// + /// + private void ValidateType(Type type) + { + if (TypeHelper.IsTypeAssignableFrom(type) == false) + { + throw new InvalidOperationException("The Type specified (" + type + ") is not of type " + typeof(RenderMvcController)); + } + } + + } +} diff --git a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs index 85fbdd4ead..ddf6d9b618 100644 --- a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs @@ -236,12 +236,13 @@ namespace Umbraco.Web.Mvc /// internal virtual RouteDefinition GetUmbracoRouteDefinition(RequestContext requestContext, PublishedContentRequest publishedContentRequest) { - var defaultControllerName = ControllerExtensions.GetControllerName(); + var defaultControllerType = DefaultRenderMvcControllerResolver.Current.GetDefaultControllerType(); + var defaultControllerName = ControllerExtensions.GetControllerName(defaultControllerType); //creates the default route definition which maps to the 'UmbracoController' controller var def = new RouteDefinition { ControllerName = defaultControllerName, - ControllerType = typeof(RenderMvcController), + ControllerType = defaultControllerType, PublishedContentRequest = publishedContentRequest, ActionName = ((Route)requestContext.RouteData.Route).Defaults["action"].ToString(), HasHijackedRoute = false @@ -260,12 +261,12 @@ namespace Umbraco.Web.Mvc //check if there's a custom controller assigned, base on the document type alias. var controllerType = _controllerFactory.GetControllerTypeInternal(requestContext, publishedContentRequest.PublishedContent.DocumentTypeAlias); - + //check if that controller exists if (controllerType != null) { //ensure the controller is of type 'RenderMvcController' - if (controllerType.IsSubclassOf(typeof (RenderMvcController))) + if (TypeHelper.IsTypeAssignableFrom(controllerType)) { //set the controller and name to the custom one def.ControllerType = controllerType; diff --git a/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs b/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs index a8f3817b6c..63eaaa5e9a 100644 --- a/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs +++ b/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs @@ -29,8 +29,11 @@ namespace Umbraco.Web.Mvc /// The request context.The name of the controller. public virtual IController CreateController(RequestContext requestContext, string controllerName) { - Type controllerType = GetControllerType(requestContext, controllerName) ?? - _innerFactory.GetControllerType(requestContext, ControllerExtensions.GetControllerName(typeof(RenderMvcController))); + var controllerType = GetControllerType(requestContext, controllerName) ?? + _innerFactory.GetControllerType( + requestContext, + ControllerExtensions.GetControllerName( + DefaultRenderMvcControllerResolver.Current.GetDefaultControllerType())); return _innerFactory.GetControllerInstance(requestContext, controllerType); } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index a9f2aa9765..29b5bf5307 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -330,6 +330,7 @@ + diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index 6561c6f5ab..47160eb695 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -8,11 +8,30 @@ using System.Web.Hosting; using System.Web.Mvc; using Umbraco.Core; using Umbraco.Core.Logging; +using Umbraco.Web.Mvc; using Umbraco.Web.Routing; using umbraco.businesslogic; namespace Umbraco.Web { + public class CustomRenderController : RenderMvcController + { + public override ActionResult Index(Models.RenderModel model) + { + HttpContext.Response.ContentType = "text/plain"; + return base.Index(model); + } + } + + public class CustomApplicationEventHandler : ApplicationEventHandler + { + protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + { + DefaultRenderMvcControllerResolver.Current.SetDefaultControllerType(typeof(CustomRenderController)); + base.ApplicationStarting(umbracoApplication, applicationContext); + } + } + /// /// The Umbraco global.asax class /// diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs index b9a27ee694..719f2861ad 100644 --- a/src/Umbraco.Web/WebBootManager.cs +++ b/src/Umbraco.Web/WebBootManager.cs @@ -235,6 +235,9 @@ namespace Umbraco.Web { base.InitializeResolvers(); + //set the default RenderMvcController + DefaultRenderMvcControllerResolver.Current = new DefaultRenderMvcControllerResolver(typeof(RenderMvcController)); + //Override the ServerMessengerResolver to set a username/password for the distributed calls ServerMessengerResolver.Current.SetServerMessenger(new DefaultServerMessenger(() => {