Category Archives: Uncategorized

Exception

Cannot change Sitecore item Presentation Details – InvalidOperationException placeholder id

Problem

I was working on a solution where I needed to change the renderings on the standard values. But when I clicked on the presentation details I got an InvalidOperationException exception, and the dialog showed the classic “Server Error in ‘/’ Application” page (see the image above).

Solution

I assume that the layouts field was corrupted. So I got the raw field value for the renderings field (using dbbrowser.aspx) and started to check if all the ID’s existed in the master database. I found that a number of ID’s did not exist so I removed those elements and then saved the raw value back in the field, and all was good again.

Sitecore History Table – how to control how long the entries are kept?

The following tables can contain a lot of data, especially if the website creates and or edits a lot of items, for the first 2 the tables it is very simple to define how many days to keep the data.

  • Publish Queue
  • Event Table
  • History Table

If there is to much data in any of the table it can causes the performance issues for Sitecore. By default Sitecore stores data for 30 days, which is too long.

Sitecore uses the following scheduled task to clean the database tables.

  1. Sitecore.Tasks.CleanupPublishQueue
  2. Sitecore.Tasks.CleanupEventQueue
  3. Sitecore.Tasks.CleanupHistory

Both CleanupPublishQueueCleanupEventQueue tasks provide the ability to specify the number of days to keep the entries (see below). Unfortunately in some cases 1 day is too long, but I will get back to that in another post.

days to keep

So why can’t you specify the number of days for the Sitecore.Tasks.CleanupHistory?

Just in case it was another undocumented feature, I opened up reflector and took a look at the Sitecore.Tasks.CleanupHistory implementation to see if it was possible or not to specify the period of time to keep entries in the history table – It wasn’t!

I continued my search and found that the SqlServerHistoryStorage.Cleanup() function (see image below) is responsible for cleaning the history table. The SQL statement uses the EntryLifeTime property to define the threshold (time-span) to keep the entries.

clean up function

 

Solution

With a bit more investigation I found that it was possible to define the EntryLifeTime value for each database in the web.config. It is possible to define the time-span using days, house, minutes s and even seconds 🙂

timespan

 

Hope this helps, Alan

Sitecore Upload Media Dialog Hangs (System.UnauthorizedAccessException)

I have a customer that was experiencing that for some users the SPEAK upload dialog would hang (well was not finished after 30 minutes). It would appear that the image had been uploaded (see below) but it never finished.

Media Upload dialog hangs

After some investigation I found that the users did not have access (create, write or delete) to the media root folder, but the strange thing is that the item was created, but the blob field was empty?

item created in the root

With a lot editors around the world soon the root folder was full of items without images, when I checked the log I could see that in fact a System.UnauthorizedAccessException was being cast (see complete exception below) but not because the item could not be created, but because it was not possible to write to the item?

The user did not have the create permission, so why was the item created? And why does the upload dialog not warn about the user they can not create and or write to an item? so I reported this to Sitecore and they have registered it as a bug and the following hot fix is available:

Sitecore CMS 7.5 rev. 141003 Hotfix 431794-1

If you don’t want to install a support DLL and JavaScript an alternative workaround is to  switch to the non-SPEAK version of the Select Media dialog by performing the following steps:

  1. Edit the /App_Config/Include/Sitecore.Speak.Applications.config file;
  2. Comment out the following lines:
   <overrideXmlControls>
      <override xmlControl="Sitecore.Shell.Applications.Media.MediaBrowser" with="/sitecore/client/applications/Dialogs/SelectMediaDialog" />
   </overrideXmlControls>

Complete Exception

Exception: System.Web.HttpUnhandledException
Message: An unhandled exception occurred.
Source: Sitecore.Mvc
   at Sitecore.Mvc.Pipelines.MvcEvents.Exception.ShowAspNetErrorMessage.ShowErrorMessage(ExceptionContext exceptionContext, ExceptionArgs args)
   at Sitecore.Mvc.Pipelines.MvcEvents.Exception.ShowAspNetErrorMessage.Process(ExceptionArgs args)
   at (Object , Object[] )
   at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
   at Sitecore.Mvc.Pipelines.PipelineService.RunPipeline[TArgs](String pipelineName, TArgs args)
   at Sitecore.Mvc.Filters.PipelineBasedRequestFilter.OnException(ExceptionContext exceptionContext)
   at System.Web.Mvc.ControllerActionInvoker.InvokeExceptionFilters(ControllerContext controllerContext, IList`1 filters, Exception exception)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
   at Sitecore.Mvc.Controllers.SitecoreActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
   at System.Web.Mvc.Controller.<>c__DisplayClass22.<BeginExecuteCore>b__1e()
   at System.Web.Mvc.Async.AsyncResultWrapper.<.cctor>b__0(IAsyncResult asyncResult, Action action)
   at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)
   at System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult)
   at System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)
   at Sitecore.Mvc.Routing.RouteHttpHandler.EndProcessRequest(IAsyncResult result)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Nested Exception
Exception: System.UnauthorizedAccessException
Message: The current user does not have write access to this item. User: XXX\yyy, Item: Desert ({B1793B35-A61D-40AC-869F-4AD66A752234})
Source: Sitecore.Kernel
   at Sitecore.Data.Items.ItemEditing.BeginEdit()
   at Sitecore.Resources.Media.MediaData.SetBlobStream(MediaStream mediaStream)
   at Sitecore.Resources.Media.Media.SetStream(MediaStream mediaStream)
   at Sitecore.Resources.Media.MediaCreator.AttachStreamToMediaItem(Stream stream, String itemPath, String fileName, MediaCreatorOptions options)
   at Sitecore.Resources.Media.MediaCreator.CreateFromStream(Stream stream, String filePath, MediaCreatorOptions options)
   at Sitecore.Controllers.MediaController.Upload(String database, String destinationUrl)
   at lambda_method(Closure , ControllerBase , Object[] )
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)

Sitecore SPEAK Control view life cycle

Scenario

We implemented a custom data source control that retrieves messages from a web service. The data source has a number of properties, some of which are bound to other SPEAK controls for example:

  1. Sorting – Bound to List Control
  2. Search Text – Bound to Text box
  3. Message Type – Drop down

Therefore we need to wait until all the bound properties are set before we call the web service to avoid unnecessary web service calls.

Solution 1

In the model we detect when the last property is bound (i.e. its value changes from empty to some value). In this case we used the MessageType when it contained a value it was assumed it was OK to call the web service.

Problem

This worked until the server side control code was re-factored and the following code was called first in the constructor and not last:

  parametersResolver.GetString("MessageType", "messageType");

The “Get String” function is responsible for generating the data-sc-bindings attribute of the control, which defines the bindings and the order they are bound (probably requires another post to explain all the magic that SPEAK does here).

Therefore as this was now called first, not last, each time the search text, sorting was bound another web service call was made. We could not detect if search text or sorting parameters had been bound or not as either of these properties can contain an empty string. It is not a great strategy to check all the properties and try to determine if they are bound or not and or rely on the order they are bound.

Therefore I investigated the life cycle to determine if there is an event, trigger, etc. I could use to determine when binding for a control is completed.

Control View life cycle

The life cycle for a control’s view is implemented as a pipeline (see my previous post about pipelines). The pipeline defines 5 steps:

  1. Initialization – call the view’s initialize function
  2. Applying Cross Binding – Bind all the properties for the control, and child controls that have bindings.
  3. Before Render – If the view declares a beforeRender function it is called.
  4. Render – If the view declares a render function it is called.
  5. After Render – If the view declares a afterRender function it is called.

Solution 2

A very simple solution was to add a beforeRender function to the view (see image below) and set the isReady to true and call Refresh on the Model.

As beforeRender  is called after all the bindings are bound, the refresh function only needs to check if isReady is true before calling the web service. The Refresh function has to check isReady as it is called each time a property changes and or the first time it is bound.

before Render

Sitecore SPEAK – Dialog Rendering

The standard way to add/create dialog’s in SPEAK is to add the Dialog Window control, and then add the controls required by the dialog to the Dialog Window’s placeholders.
This has a number of disadvantages

  • Each new page that requires the dialog has to add all the renderings/settings that the dialog requires.
  • The code related for the dialog is added to the code page.
  • If you need to add/remove controls from the dialog you have to update all the pages that use the dialog
  • If you have a page with a lot of dialog’s the page will have a LOT of controls and all the code

In order to address the afore mentioned issues and enable reuse of dialog’s across a number of pages, we introduced the concept of a Dialog Rendering item; which contains all the renderings required by the Dialog, and defines its own sub-page code which contains the code required by the dialog.
In this blog we will create a attachment dialog, as the uploader control that comes with SPEAK is very cool (look out for an upcoming blog post)..

attachment dialog

Adding/showing a dialog

There are a 4 steps in order to add and then show a dialog:

  1. Create the Dialog Rendering Template. (Whilst this is not required, as you could add the layouts to any item, I would strongly recommend defining a template).
  2. Create the Dialog Rendering item
    1. Add the Dialog Window Control and add the required controls to the Dialog Window placeholder.
    2. Add a SubPageCode control and create the JavaScript which provides the functionality required by the dialog.rendering item
  3. Add the dialog to the page using Client side insert renderings.
    1. The guid is the rendering item id (i.e. the attachment item defined in step 2).
    2. Then save the dialog in the subpage controls list with a unique name.
contextApp.insertRendering("{26D93861-13E8-4416-8319-0D03094A19CB}", { $el: $("body") }, function (subApp) {
        contextApp["showAddAttachmentDialog"] = subApp;

      });

  1. To show the dialog the show function on the DialogWindow control has to be called. There are a number of ways this could be achieved, but I decided to implement it as follows
    1. In the initialize function for the dialog (SubPageCode JavaScript), set up an event handler to listen for a show event i.e. add:attachment:dialog:show.
    2. Define a showDialog function which calls the DialogWindow.Show().code
    3. To show the dialog, trigger the event and pass the in the required parameters.events & paramter

Context Issue

The dialog does not have access to the page’s context and controls; therefore you pass the required context via the event parameters.
This in fact reduces dependencies as the only dependency is the event parameters; therefore the dialog is not aware of where it is called from.