diff --git a/src/Umbraco.Web/Mvc/EnsurePartialViewMacroViewContextFilterAttribute.cs b/src/Umbraco.Web/Mvc/EnsurePartialViewMacroViewContextFilterAttribute.cs index afd40330ea..625b67b2b2 100644 --- a/src/Umbraco.Web/Mvc/EnsurePartialViewMacroViewContextFilterAttribute.cs +++ b/src/Umbraco.Web/Mvc/EnsurePartialViewMacroViewContextFilterAttribute.cs @@ -21,20 +21,46 @@ namespace Umbraco.Web.Mvc /// internal class EnsurePartialViewMacroViewContextFilterAttribute : ActionFilterAttribute { + /// + /// Ensures the custom ViewContext datatoken is set before the RenderController action is invoked, + /// this ensures that any calls to GetPropertyValue with regards to RTE or Grid editors can still + /// render any PartialViewMacro with a form and maintain ModelState + /// + /// public override void OnActionExecuting(ActionExecutingContext filterContext) { //ignore anything that is not IRenderController - if ((filterContext.Controller is IRenderController) == false) + if ((filterContext.Controller is IRenderController) == false && filterContext.IsChildAction == false) return; + SetViewContext(filterContext); + } + + /// + /// Ensures that the custom ViewContext datatoken is set after the RenderController action is invoked, + /// this ensures that any custom ModelState that may have been added in the RenderController itself is + /// passed onwards in case it is required when rendering a PartialViewMacro with a form + /// + /// The filter context. + public override void OnResultExecuting(ResultExecutingContext filterContext) + { + //ignore anything that is not IRenderController + if ((filterContext.Controller is IRenderController) == false && filterContext.IsChildAction == false) + return; + + SetViewContext(filterContext); + } + + private void SetViewContext(ControllerContext controllerContext) + { var viewCtx = new ViewContext( - filterContext.Controller.ControllerContext, - new DummyView(), - filterContext.Controller.ViewData, filterContext.Controller.TempData, + controllerContext, + new DummyView(), + controllerContext.Controller.ViewData, controllerContext.Controller.TempData, new StringWriter()); //set the special data token - filterContext.RequestContext.RouteData.DataTokens[Constants.DataTokenCurrentViewContext] = viewCtx; + controllerContext.RequestContext.RouteData.DataTokens[Constants.DataTokenCurrentViewContext] = viewCtx; } private class DummyView : IView diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index 0c45c24c4a..3d1a41d289 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -120,9 +120,13 @@ namespace Umbraco.Web.Mvc base.InitializePage(); if (ViewContext.IsChildAction == false) { - //always ensure the special data token is set - this is used purely for partial view macros that contain forms - // and mostly just when rendered within the RTE - ViewContext.RouteData.DataTokens[Constants.DataTokenCurrentViewContext] = ViewContext; + //this is used purely for partial view macros that contain forms + // and mostly just when rendered within the RTE - This should already be set with the + // EnsurePartialViewMacroViewContextFilterAttribute + if (ViewContext.RouteData.DataTokens.ContainsKey(Constants.DataTokenCurrentViewContext) == false) + { + ViewContext.RouteData.DataTokens.Add(Constants.DataTokenCurrentViewContext, ViewContext); + } } }