Force forms editing for specific blocks!?

Vote:
 

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
Vote:
 

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
Vote:
 

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

#72292
Jun 12, 2013 16:38
Vote:
 

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
Vote:
 

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
Vote:
 

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
Vote:
 

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
Vote:
 

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
Vote:
 

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

#72307
Jun 13, 2013 1:37
Vote:
 

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
Vote:
 

Great! Thanks!

#72312
Jun 13, 2013 9:11
Vote:
 

I just want to add that we have added the posibility to define the default view for a content type in the next release. More info about this when we get closer to the release...

#72317
Jun 13, 2013 9:50
Vote:
 
#81536
Feb 19, 2014 8:03
Vote:
 

Note that UIDescriptor<T> with the DefaultView is only available in EPiServer 7.5

#81539
Feb 19, 2014 8:30
This thread is locked and should be used for reference only. Please use the Episerver CMS 7 and earlier versions forum to open new discussions.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.