I'm in the process of migrating the code base from a v8 site to v11. Under v8 I could declare a surface controller that implemented OnActionExecuting so I could add whatever code needed to be run on every page request. e.g.
public abstract class SomeController : SurfaceController
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.RouteData.DataTokens.TryGetValue("ParentActionViewContext", out var val))
{
if (val is ViewContext ctx)
{
if (ctx.Controller is RenderMvcController)
{
// if it gets here we have an umbraco page, so CurrentPage is available for use
var noCache = CurrentPage.GetCustomPropertyValue<bool>("noBrowserCache");
if (noCache)
{
Response.Cache.SetCacheability(HttpCacheability.NoCache); // HTTP 1.1.
Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
Response.AppendHeader("Expires", "0"); // Proxies.
}
}
}
}
}
}
I've transferred the controller over but it's behaviour is different in v11, it no longer fires on every request. Although I've managed to implement a custom filter to achieve the same thing I no longer have access to any umbraco objects e.g. in my custom filter:
public void OnActionExecuting(ActionExecutingContext context)
{
if (context.RouteData.DataTokens.TryGetValue("umbraco-current-view-context", out var val))
{
if (val is ViewContext ctx)
{
if (context.Controller is RenderController ctrlr)
{
// how do I get access to the page properties/values?
//var noCache = ctrlr.CurrentPage.GetCustomPropertyValue<bool>("noBrowserCache");
// if (noCache)
// {
// Response.Cache.SetCacheability(HttpCacheability.NoCache); // HTTP 1.1.
// Response.Cache.AppendCacheExtension("no-store, must-revalidate");
// Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
// Response.AppendHeader("Expires", "0"); // Proxies.
// }
}
}
}
}
Although ctrlr does have a CurrentPage object, its private. Is there a better way to achieve this or will I have to use reflection to get it? Wondering if anyone has implemented anything similar/better?
Found a solution with help from a bit of deconstructing the Umbraco objects, so putting this here in case anyone else finds it useful. So the above OnActionExecuting code is as follows (to ensure this only runs from the page request):
if (context.RouteData.DataTokens.TryGetValue("umbraco-current-view-context", out var val))
{
if (val is ViewContext)
{
if (context.Controller is RenderController)
{
var routeValues = context.HttpContext.Features.Get<UmbracoRouteValues>(); // this is what the private CurrentPage property is really doing
if (routeValues != null)
{
var page = routeValues.PublishedRequest.PublishedContent;
var noCache = page.GetCustomPropertyValue<bool>("noBrowserCache");
if (noCache)
{
// do stuff
}
}
}
}
}
Just for reference GetCustomPropertyValue
public static T GetCustomPropertyValue<T>(this IPublishedContent content, string propertyAlias)
{
var prop = content?.Properties.FirstOrDefault(x => x.Alias == propertyAlias);
if (prop == null || !prop.HasValue()) return default;
var val = prop.GetValue();
if (val is T) return (T) val;
try
{
return (T)Convert.ChangeType(val, typeof(T));
}
catch (InvalidCastException)
{
return default;
}
}
Umbraco 11 surface controllers / OnActionExecuting
I'm in the process of migrating the code base from a v8 site to v11. Under v8 I could declare a surface controller that implemented OnActionExecuting so I could add whatever code needed to be run on every page request. e.g.
I've transferred the controller over but it's behaviour is different in v11, it no longer fires on every request. Although I've managed to implement a custom filter to achieve the same thing I no longer have access to any umbraco objects e.g. in my custom filter:
Although ctrlr does have a CurrentPage object, its private. Is there a better way to achieve this or will I have to use reflection to get it? Wondering if anyone has implemented anything similar/better?
Found a solution with help from a bit of deconstructing the Umbraco objects, so putting this here in case anyone else finds it useful. So the above OnActionExecuting code is as follows (to ensure this only runs from the page request):
Just for reference GetCustomPropertyValue
is working on a reply...