Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Chris 10 posts 100 karma points
    1 week ago
    Chris
    0

    Hi,

    I would like to be able to add some caching to DTGE components, ideally using Donut Caching on the DocTypeGridEditorSurfaceController.

    The issue I have is I can't find anything in the model or route that I could use to construct a cache key. I can get the page node, but as there can be multiple versions of the component on the page i need an extra id.

    I thought about setting a guid on item creation, but as it's not real content there isn't an event to hook into. Is there an angular way to do that (my angular skills are pretty much zero).

    Does anyone know of a solution to this?

  • Dave Woestenborghs 2691 posts 8074 karma points MVP 2x admin c-trib
    1 week ago
    Dave Woestenborghs
    100

    Hi Chris,

    I got this working but not on id. More on controller level.

    I will explain our use case so you understand what we were doing. We have DTGE grid block that displays x latest news items. So when a news detail page is updated we wanted to update all these blocks, but leave the rest of the page in cache.

    I first created a new abstract controller that inherits from DocTypeGridEditorSurfaceController so we can pass in some extra parameters from the view. You need to inherits your controller from this one.

    namespace Website.Controllers
    {
        using Our.Umbraco.DocTypeGridEditor.Helpers;
    
        using Umbraco.Core.Models;
    
        public abstract class CachedDocTypeGridEditorSurfaceController : DocTypeGridEditorSurfaceController
        {
            public new IPublishedContent Model
            {
                get
                {
                    return DocTypeGridEditorHelper.ConvertValueToContent(this.Id, this.ContentTypeAlias, this.Value);
                }
            }
    
            public string Id
            {
                get { return this.ControllerContext.RouteData.Values["dtgeId"] as string ?? string.Empty; }
            }
    
    
            public string ContentTypeAlias
            {
                get { return this.ControllerContext.RouteData.Values["dtgeContentTypeAlias"] as string ?? string.Empty; }
            }
    
            public string Value
            {
                get { return this.ControllerContext.RouteData.Values["dtgeValue"] as string ?? string.Empty; }
            }
        }
    }
    

    Next step is to create a new "renderrer" for your cached grid blocks. I called CachedDoctypeGridEditor.cshtml and placed in the /Views/Grid folder of my website.

    This is the contents of the view.

    @using Microsoft.CSharp.RuntimeBinder
    @using Our.Umbraco.DocTypeGridEditor.Helpers
    @inherits Umbraco.Web.Mvc.UmbracoViewPage<dynamic>
    @if (Model.value != null)
    {
        string id = Model.value.id.ToString();  
        string contentTypeAlias = "";
        string value = Model.value.value.ToString();
        string viewPath = Model.editor.config.viewPath.ToString();
    
        try
        {
            contentTypeAlias = Model.value.dtgeContentTypeAlias.ToString();
        }
        catch (RuntimeBinderException)
        {
            contentTypeAlias = Model.value.docType.ToString();
        }
    
        if (contentTypeAlias != "")
        {
            var content = DocTypeGridEditorHelper.ConvertValueToContent(id, contentTypeAlias, value);       
    
            @Html.Action(content.DocumentTypeAlias, content.DocumentTypeAlias + "Surface", new
                                                                  {
                                                                      dtgeValue = value,
                                                                      dtgeId = id,
                                                                      dtgeContentTypeAlias = contentTypeAlias,
                                                                      dtgeViewPath = viewPath,
                                                                      dtgePreviewViewPath = ""
                                                                  }, true);
        }
    }
    

    It calls your controller action and excludes it from the parent cache. You can ofcourse annotate your controller action with the DonutOutputCache attribute.

    Next step is tell your grid editor config to use the new renderrer.

    {
            "name": "News list",
            "alias": "newslist",
            "view": "/App_Plugins/DocTypeGridEditor/Views/doctypegrideditor.html",
            "render": "/Views/Grid/CachedDoctypeGridEditor.cshtml",
            "icon": "icon-grid",
            "config": {
                "allowedDocTypes": ['gridNews'],
                "nameTemplate": "",
                "enablePreview": true,
                "viewPath": "/Views/Partials/Grid/Editors/DocTypeGridEditor/",
                "previewViewPath": "/Views/Partials/Grid/Editors/DocTypeGridEditor/Previews/",
                "previewCssFilePath": "",
                "previewJsFilePath": ""
            }
        }
    

    Last thing what you need to do is build some logic that decides if the grid block cache should be emptied.

    You can empty the cache for all the grid blocks using a specific controller like this :

    var cachemanager = new OutputCacheManager();
    cachemanager.RemoveItems("ControllerNameSurface");
    

    If you have anymore questions. Just shoot.

    Dave

  • Chris 10 posts 100 karma points
    7 days ago
    Chris
    0

    I've had the time to implement this now and it's working like a dream :)

    I had one or two issues, maybe with the specific versions of Donut Caching and Umbraco we are using.

    The first issue was Model builder was crashing as it's content was null.

    This was fixed by passing the dtgeModel in the renderer:

            @Html.Action(content.DocumentTypeAlias, content.DocumentTypeAlias + "Surface", new
        {
            dtgeValue = value,
            dtgeId = id,
            dtgeContentTypeAlias = contentTypeAlias,
            dtgeViewPath = viewPath,
            dtgePreviewViewPath = "",
            dtgeModel = content
        });
    

    I was also unable to use the Donut Caching Html.Action extension as it threw an error that DetachedPublishedContent is not serializable. However I'm not caching the full page anyway so I don't need the exclude from parent cache flag and the default Action works fine.

Please Sign in or register to post replies

Write your reply to:

Draft