Force forms editing for specific blocks!?

Member since: 2007

Some blocks doesn't make sense to edit on page. Maybe they have a lot of "hidden" properties that is not visible to the user and sometimes the design of the block makes it to hard for the edtior. Sometimes the block has different apperance depending on where it is rendered.

 

My scenario


I have a general previewing template...

[TemplateDescriptor(
    AvailableWithoutTag = false,
    Inherited = true,
    Tags = new string[] { RenderingTags.Preview })]
public partial class BlockPreview : PreviewPage, IRenderTemplate<BlockData>

...and then I add a content renderer to this page for the block.


But is there a way to force the user to the forms view straight away? I have tried with all attributes on the blocks, but they always gets rendered on my preview template with the message "Block A dosen't have a renderer for the tag Preview", which is true, because I don't want to render them there.

#72287 Jun 12, 2013 14:46
  • Member since: 2004

    One way that comes up to my mind is to have a baseclass called e.g. OnPageEditableBlock that inherits BlockData and then all blocks that should be on page editable would inherit that class. While your other blocks that should have forms editing would inherit directly from BlockData. Then in your BlockPreview you should set the generic argument to IRenderTemplate to OnPageEditableBlock.

    #72290 Jun 12, 2013 15:12
  • Member since: 2007

    Of course... that should work. Don't know why I didn't come up with that.

    #72292 Jun 12, 2013 16:38
  • Member since: 2007

    Hmmm I'm getting an error though in PreviewContainerPage.aspx. The error just flashes and then the form view slides in.

    The error

    Content with id '24_363' is of type 'Castle.Proxies.SlideBlockProxy' which does not inherit required type 'EPiServer.Core.PageData'
    
    [TypeMismatchException: Content with id '24_363' is of type 'Castle.Proxies.SlideBlockProxy' which does not inherit required type 'EPiServer.Core.PageData']
       EPiServer.DataFactory.ThrowTypeMismatchException(ContentReference link, Type actual, Type required) +179
       EPiServer.DataFactory.Get(ContentReference contentLink, ILanguageSelector languageSelector) +482
       EPiServer.PageBase.GetPage(PageReference pageLink, ILanguageSelector selector) +233
       EPiServer.Web.PageExtensions.LoadCurrentPage.get_CurrentPage() +133
       EPiServer.PageBase.SetCachePolicy() +195
       EPiServer.PageBase.OnInit(EventArgs e) +39
       System.Web.UI.Control.InitRecursive(Control namingContainer) +186
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2098

    And this is what I find in the log

    2013-06-12 19:04:05,660 ERROR [user] EPiServer.Global System.Web.HttpUnhandledException (0x80004005): Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> EPiServer.Core.TypeMismatchException: Content with id '85_584' is of type 'Castle.Proxies.SlideBlockProxy' which does not inherit required type 'EPiServer.Core.PageData'
       at EPiServer.DataFactory.ThrowTypeMismatchException(ContentReference link, Type actual, Type required)
       at EPiServer.DataFactory.Get[T](ContentReference contentLink, ILanguageSelector languageSelector)
       at EPiServer.PageBase.GetPage(PageReference pageLink, ILanguageSelector selector)
       at EPiServer.Web.PageExtensions.LoadCurrentPage.get_CurrentPage()
       at EPiServer.PageBase.SetCachePolicy()
       at EPiServer.PageBase.OnInit(EventArgs e)
       at System.Web.UI.Control.InitRecursive(Control namingContainer)
       at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
       at System.Web.UI.Page.HandleError(Exception e)
       at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
       at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
       at System.Web.UI.Page.ProcessRequest()
       at System.Web.UI.Page.ProcessRequest(HttpContext context)
       at ASP.episerver_cms_edit_previewcontainerpage_aspx.ProcessRequest(HttpContext context) in c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\78f76313\91ca32c3\App_Web_vru0ko5h.19.cs:line 0
       at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
       at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
     - 1.2.5 Unhandled exception in ASP.NET

    The SlideBlock inherits from SiteFormsViewBlockDataBase which inherits from BlockData.

    #72298 Jun 12, 2013 19:13
  • Member since: 2008

    Make sure that you describe the templatedescriptor so your blockdata is not included.

    You can look your block type settings and make sure the fields for Web Form Template and MVC Template are empty. Sometimes you need to Revert to default. Especially if you are a couple of developers sharing database since they will update the selected template on restart according to their "old" TemplateDescriptor

    #72303 Edited, Jun 12, 2013 23:40
  • Member since: 2008

    Sorry I misread your callstack.

    This is what seems to be ordinary when editing a Block that does not have a Preview-Template. I also had this after my first couple of Blocks.

    #72304 Jun 13, 2013 0:19
  • Member since: 2007

    Yeah, and the thing is that we don't want a template. We just want the Forms Editing view.

    This works great for pages though, so I guess there is some attribute we can render on the template to load up the Forms Editing view.

    #72305 Jun 13, 2013 0:23
  • Member since: 2008

    When I'm looking in the XML Http Requests for a Block (/EPiServer/shell/Stores/context/?uri=epi.cms.contentdata:///8664&dojo.preventCache=1371078678651) that have no Template I can see the following:

    hasTemplate: false
    previewUrl: "/secure/CMS/edit/PreviewContainerPage.aspx"

    I can see the same in the XHR when I edit a Container Page (ordinary page that have no template)

    Though when I'm editing a Block that have a template i can see the following:

    hasTemplate: true
    previewUrl: "/secure/CMS/Content/Ny-katalog/Ny-katalog1/,,8664_35819/?epieditmode=true"

    My guess is that "hasTemplate" is what's triggering whether to automatically show the form editing and the call stack you see flash by must be the PreviewContainerPage.aspx throwing an exception since it tries to get a PageData object where CurrentContent in fact is a Block.

    A spontanious search for "hasTemplate" brought me to C:\Program Files (x86)\EPiServer\CMS\7.0.586.1\Application\UI\EPiServer\CMS\ClientResources\EPi\Cms\contentediting\PageDataController.js which seems to confirm this:

            _getDefaultView: function (viewModel) {
                // summary:
                //    Get the default view based on user's access rights.
                //
                // tags:
                //    private
    
                return viewModel.contentData.hasTemplate ?
                        (viewModel.canChangeContent() ? this._defaultEditViewName : "readonly") :
                        "formedit";
            }

    So the question is how you can return false on hasTemplate while also returning another previewUrl than PreviewContainerPage.aspx

    I think this seems kinda tricky since EPiServer.Cms.Shell.UI.dll seems to be the assembly deciding what previewUrl should be sent in the XHR.

    Here you can find IContentExtensions with a method PreviewUrl:

    public static string PreviewUrl(this IContent content)
    {
        if (!content.HasTemplate())
        {
            return UriSupport.ResolveUrlFromUIBySettings("edit/PreviewContainerPage.aspx");
        }
        VirtualPathData virtualPathData = RouteTable.Routes.GetVirtualPath(content.ContentLink, content.LanguageBranch(), true, true);
        if (virtualPathData == null)
        {
            return string.Empty;
        }
        UrlBuilder builder = new UrlBuilder(virtualPathData.GetUrl());
        if (!(content is PageData))
        {
            builder.QueryCollection.Remove("id");
        }
        return builder.ToString();
    }
    

    content.HasTemplate() is an extension method in IContentExtensions:

    internal static bool HasTemplate(this IContent content)
    {
        PageData data = content as PageData;
        if ((data != null) && (data.LinkType == PageShortcutType.Inactive))
        {
            return false;
        }
        return ServiceLocator.Current.GetInstance<TemplateResolver>().HasTemplate(content, TemplateTypeCategories.Page, "Preview");
    }

    I would call this a bug or a request to let PreviewContainerPage not be dependent on having a PageData.

    Either way, at the moment I think you'll have to live with the call stack flashing by, or create a plugin that does some Dojo magic displaying the forms edit.

    #72306 Edited, Jun 13, 2013 1:30
  • Member since: 2007

    I would also call this a bug. Thanks for digging in Alf :)

    #72307 Jun 13, 2013 1:37
  • Member since: 2004

    Looking at sourcecode I see that this has changed (PreviewContainerPage handles other content than PageData) in development branch meaning it will be fixed in 7.5 release.

    I have however also reported a bug on that it should be fixed in Maint branch meaning that it then (given that the bug will be fixed) will be available in next maintenanace drop.

    #72311 Jun 13, 2013 9:10
  • Member since: 2008

    Great! Thanks!

    #72312 Jun 13, 2013 9:11
First   1 2   Last