Fixed issue: #U4-1726
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
@@ -13,5 +14,13 @@ namespace Umbraco.Web.Mvc
|
||||
/// <returns><c>true</c> if this instance can handle the specified request; otherwise, <c>false</c>.</returns>
|
||||
/// <remarks></remarks>
|
||||
bool CanHandle(RequestContext request);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the controller type for the controller name otherwise null if not found
|
||||
/// </summary>
|
||||
/// <param name="requestContext"></param>
|
||||
/// <param name="controllerName"></param>
|
||||
/// <returns></returns>
|
||||
Type GetControllerType(RequestContext requestContext, string controllerName);
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,23 @@ namespace Umbraco.Web.Mvc
|
||||
: 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 = _slaveFactories.Factories.FirstOrDefault(x => x.CanHandle(requestContext));
|
||||
return factory != null
|
||||
? factory.GetControllerType(requestContext, controllerName)
|
||||
: base.GetControllerType(requestContext, controllerName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the specified controller.
|
||||
/// </summary>
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace Umbraco.Web.Mvc
|
||||
/// <param name="requestContext"></param>
|
||||
/// <param name="controllerName"></param>
|
||||
/// <returns></returns>
|
||||
protected Type GetControllerType(RequestContext requestContext, string controllerName)
|
||||
public Type GetControllerType(RequestContext requestContext, string controllerName)
|
||||
{
|
||||
return _innerFactory.GetControllerType(requestContext, controllerName);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using System.Web.SessionState;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Configuration;
|
||||
@@ -184,7 +185,7 @@ namespace Umbraco.Web.Mvc
|
||||
requestContext.RouteData.Values["action"] = postedInfo.ActionName;
|
||||
requestContext.RouteData.DataTokens["area"] = postedInfo.Area;
|
||||
|
||||
IHttpHandler handler = new MvcHandler(requestContext);
|
||||
IHttpHandler handler = new UmbracoMvcHandler(requestContext);
|
||||
|
||||
//ensure the controllerType is set if found, meaning it is a plugin, not locally declared
|
||||
if (postedInfo.Area != standardArea)
|
||||
@@ -232,57 +233,53 @@ namespace Umbraco.Web.Mvc
|
||||
var def = new RouteDefinition
|
||||
{
|
||||
ControllerName = defaultControllerName,
|
||||
Controller = new RenderMvcController(UmbracoContext),
|
||||
ControllerType = typeof(RenderMvcController),
|
||||
PublishedContentRequest = publishedContentRequest,
|
||||
ActionName = ((Route)requestContext.RouteData.Route).Defaults["action"].ToString(),
|
||||
HasHijackedRoute = false
|
||||
};
|
||||
|
||||
//check that a template is defined), if it doesn't and there is a hijacked route it will just route
|
||||
// to the index Action
|
||||
if (publishedContentRequest.HasTemplate)
|
||||
{
|
||||
//the template Alias should always be already saved with a safe name.
|
||||
//if there are hyphens in the name and there is a hijacked route, then the Action will need to be attributed
|
||||
// with the action name attribute.
|
||||
var templateName = publishedContentRequest.TemplateAlias.Split('.')[0].ToSafeAlias();
|
||||
def.ActionName = templateName;
|
||||
}
|
||||
|
||||
//check if there's a custom controller assigned, base on the document type alias.
|
||||
var controller = _controllerFactory.CreateController(requestContext, publishedContentRequest.PublishedContent.DocumentTypeAlias);
|
||||
|
||||
|
||||
var controllerType = ((MasterControllerFactory)_controllerFactory).GetControllerTypeInternal(requestContext, publishedContentRequest.PublishedContent.DocumentTypeAlias);
|
||||
|
||||
//check if that controller exists
|
||||
if (controller != null)
|
||||
{
|
||||
if (controllerType != null)
|
||||
{
|
||||
//ensure the controller is of type 'RenderMvcController'
|
||||
if (controllerType.IsSubclassOf(typeof (RenderMvcController)))
|
||||
{
|
||||
//set the controller and name to the custom one
|
||||
def.ControllerType = controllerType;
|
||||
def.ControllerName = ControllerExtensions.GetControllerName(controllerType);
|
||||
if (def.ControllerName != defaultControllerName)
|
||||
{
|
||||
def.HasHijackedRoute = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Warn<RenderRouteHandler>(
|
||||
"The current Document Type {0} matches a locally declared controller of type {1}. Custom Controllers for Umbraco routing must inherit from '{2}'.",
|
||||
() => publishedContentRequest.PublishedContent.DocumentTypeAlias,
|
||||
() => controllerType.FullName,
|
||||
() => typeof (RenderMvcController).FullName);
|
||||
//exit as we cannnot route to the custom controller, just route to the standard one.
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
//ensure the controller is of type 'RenderMvcController'
|
||||
if (controller is RenderMvcController)
|
||||
{
|
||||
//set the controller and name to the custom one
|
||||
def.Controller = (ControllerBase)controller;
|
||||
def.ControllerName = ControllerExtensions.GetControllerName(controller.GetType());
|
||||
if (def.ControllerName != defaultControllerName)
|
||||
{
|
||||
def.HasHijackedRoute = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Warn<RenderRouteHandler>(
|
||||
"The current Document Type {0} matches a locally declared controller of type {1}. Custom Controllers for Umbraco routing must inherit from '{2}'.",
|
||||
() => publishedContentRequest.PublishedContent.DocumentTypeAlias,
|
||||
() => controller.GetType().FullName,
|
||||
() => typeof(RenderMvcController).FullName);
|
||||
//exit as we cannnot route to the custom controller, just route to the standard one.
|
||||
return def;
|
||||
}
|
||||
|
||||
//check that a template is defined), if it doesn't and there is a hijacked route it will just route
|
||||
// to the index Action
|
||||
if (publishedContentRequest.HasTemplate)
|
||||
{
|
||||
//the template Alias should always be already saved with a safe name.
|
||||
//if there are hyphens in the name and there is a hijacked route, then the Action will need to be attributed
|
||||
// with the action name attribute.
|
||||
var templateName = publishedContentRequest.TemplateAlias.Split('.')[0].ToSafeAlias();
|
||||
def.ActionName = templateName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return def;
|
||||
return def;
|
||||
}
|
||||
|
||||
internal IHttpHandler GetHandlerOnMissingTemplate(PublishedContentRequest pcr)
|
||||
@@ -365,11 +362,19 @@ namespace Umbraco.Web.Mvc
|
||||
requestContext.RouteData.Values["action"] = routeDef.ActionName;
|
||||
}
|
||||
|
||||
// Set the session state requirements
|
||||
requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext, routeDef.ControllerName));
|
||||
|
||||
// reset the friendly path so in the controllers and anything occuring after this point in time,
|
||||
//the URL is reset back to the original request.
|
||||
requestContext.HttpContext.RewritePath(UmbracoContext.OriginalRequestUrl.PathAndQuery);
|
||||
|
||||
return new MvcHandler(requestContext);
|
||||
return new UmbracoMvcHandler(requestContext);
|
||||
}
|
||||
|
||||
private SessionStateBehavior GetSessionStateBehavior(RequestContext requestContext, string controllerName)
|
||||
{
|
||||
return _controllerFactory.GetControllerSessionBehavior(requestContext, controllerName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Web.Mvc;
|
||||
using Umbraco.Web.Routing;
|
||||
|
||||
@@ -16,6 +17,12 @@ namespace Umbraco.Web.Mvc
|
||||
/// </summary>
|
||||
public ControllerBase Controller { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Controller type found for routing to
|
||||
/// </summary>
|
||||
public Type ControllerType { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The current RenderModel found for the request
|
||||
/// </summary>
|
||||
|
||||
57
src/Umbraco.Web/Mvc/UmbracoMvcHandler.cs
Normal file
57
src/Umbraco.Web/Mvc/UmbracoMvcHandler.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
|
||||
namespace Umbraco.Web.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// Mvc handler class to intercept creation of controller and store it for later use.
|
||||
/// This means we create two instances of the same controller to support some features later on.
|
||||
///
|
||||
/// The alternate option for this is to completely rewrite all MvcHandler methods.
|
||||
///
|
||||
/// This is currently needed for the 'return CurrentUmbracoPage()' surface controller functionality
|
||||
/// because it needs to send data back to the page controller.
|
||||
/// </summary>
|
||||
internal class UmbracoMvcHandler : MvcHandler
|
||||
{
|
||||
public UmbracoMvcHandler(RequestContext requestContext)
|
||||
: base(requestContext)
|
||||
{
|
||||
}
|
||||
|
||||
private void StoreControllerInRouteDefinition()
|
||||
{
|
||||
var routeDef = (RouteDefinition)RequestContext.RouteData.DataTokens["umbraco-route-def"];
|
||||
|
||||
if (routeDef == null) return;
|
||||
|
||||
// Get the factory and controller and create a new instance of the controller
|
||||
var factory = ControllerBuilder.Current.GetControllerFactory();
|
||||
var controller = factory.CreateController(RequestContext, routeDef.ControllerName) as ControllerBase;
|
||||
|
||||
// Store the controller
|
||||
routeDef.Controller = controller;
|
||||
}
|
||||
|
||||
protected override void ProcessRequest(HttpContextBase httpContext)
|
||||
{
|
||||
StoreControllerInRouteDefinition();
|
||||
|
||||
// Let MVC do its magic and continue the request
|
||||
base.ProcessRequest(httpContext);
|
||||
}
|
||||
|
||||
protected override IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback,
|
||||
object state)
|
||||
{
|
||||
StoreControllerInRouteDefinition();
|
||||
|
||||
return base.BeginProcessRequest(httpContext, callback, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -303,6 +303,7 @@
|
||||
<Compile Include="Mvc\UmbracoAuthorizeAttribute.cs" />
|
||||
<Compile Include="Mvc\UmbracoAuthorizedController.cs" />
|
||||
<Compile Include="Mvc\UmbracoController.cs" />
|
||||
<Compile Include="Mvc\UmbracoMvcHandler.cs" />
|
||||
<Compile Include="Mvc\UmbracoViewPage.cs" />
|
||||
<Compile Include="PublishedContentExtensions.cs" />
|
||||
<Compile Include="ExamineExtensions.cs" />
|
||||
|
||||
Reference in New Issue
Block a user