Category Archives: Sitecore 7.5

Untangling the Sitecore Search LINQ to SolR queries

Problem

It can be very difficult to identify why you do not get the search results you expected from Sitecore Search, but there is a simple way to help untangle what is going on.

Solution

It is possible to see the query that Sitecore generates and sends to SolR and then use the query on the SolR instance to see what data is returned to Sitecore.

This is such a huge help when trying to understand why your queries do not work!

Step 1 – Find the Query that was sent to SolR from Sitecore

Sitecore logs all the queries it sends to SolR in the standard sitecore log folder, look for files named Search.log.xxx.yyy.txt .

Step 2 – Execute the query in your SolR instance

Go to your Solr instance, and use the core selector drop down to select the index your Sitecore Search query is being executed against.

Select Query, from the menu

Then paste the query from the sitecore log, and you can see the result that is returned to Sitecore.

This has helped me a lot, so I hope this helps others untangling their search results using Sitecore Search 🙂

 

 

 

How to suspend sitecore schedule publishing – aborting the publish pipeline is not enough, it requires an exception!

The customer wanted the ability to suspend scheduled publishing, but could still make manual publishes (i.e. started from the Sitecore client).

Each time a publish is started it runs the publish pipeline. Therefore it is possible to insert a custom pipeline step at the beginning (see below) to do the following:

  1. Identify if it was a scheduled publish
  2. Check if a check-box in Sitecore is ticked
  3. If both conditions are met – abort the publish pipeline to stop the publish

publish pipeline

Unfortunately aborting the publish pipeline is not enough 😦

In the initial code I would abort the pipeline using AbortPipeline() (see below) as I assumed this was enough to stop the publish. The pipeline was aborted and no items were published, but the code that starts the pipeline still updated the properties table indicating that the publish had succeeded:-(

code

Side affect

This had the side effect that when the schedule publishing was enabled again, any items that were modified or created whist the publishing was disabled would not be published as when scheduled publishing was resumed Sitecore believed that they had already been published.

Solution

After checking the code using reflector I determined if I threw an exception, it would ensure that the properties table was not updated. So the publish was completely cancelled, and when scheduled incremental publishing was resumed it will publish all the items that have been modified since the last successful publish, and not since the last aborted publish.

How to identify a scheduled publish

Not the nicest solution but it works! I check the publish context user which can have the following values:

  1. The user logged into sitecore – If publish is started from the Sitecore client
  2. sitecore\Anonymous – if the publish is started by the scheduler

If the value is sitecore\Anonymous I know that it is a scheduled publish.

is schedules

 

 

 

How to filter AD roles or users using Sitecore’s LDAP module

Problem
Every time I have used AD for providing access to Sitecore, the active directory (AD) structure is crazy and recently I had a customer that had over 18000 roles, which made it difficult to assign roles and it killed the performance of the Sitecore client, as each user had at least 500 roles. Therefore Sitecore to evaluate the combination of a lot of roles to determine if they had read access or not.
18000I talked to the department responsible for the AD setup about changing and or creating a folder that only contained the Sitecore related roles, but this was not possible.

Initially I thought I would have to make own LDAP provider which derives from the standard provider, but I discovered this was not necessary as the LDAP module provides the functionality as standard.

Custom Filters
Custom Filter provide the ability to filter the roles and or users returned from the AD (see section 4.1 for full documentation).The custom filter uses the standard LDAP query syntax (see MSDN) to specify how the user or roles are filtered.

The following example ensures only roles, which contain Sitecore and or the special operations role; are imported into Sitecore. The Customcustom Filter

According to Sitecore documentation, both the User and Role provider must have the same CustomFilter, and that is why the (objectCategory=person) is added so all users are also imported regardless of their name.

I hope this blog post will help others using LDAP to control what roles or users are shown within sitecore.

Sitecore – property change events flooding the Event Queue in the Core database

I had an issue that the EventQueue table in the Core database which was being flooded with events, which in turn was responsible for causing bad performance.

This was caused by the fact that each time the Lucene indexes are updated Sitecore raises the database:propertychanged event.

event queue core datbase

 

The default implementation subscribes to the event and adds it to the EventQueue table in the core database. I set the “Days To Keep” events to 1 day – but it still inserts over 100000 events a day 😦

Sitecore have registered this as a bug, but as yet there is no fix for 7.5 or 8.

Solution

This is not very nice at all, but  it was the best we could do as a workaround for this issue. The credit for this solution must go to my colleague Peter Wind (@peterwind) who is created the hack!

Use reflector to get the code for the default Sitecore.Eventing.Remote.RemoteEventMap class (defined in Sitecore.Kernel.dll), and create your own class, see below.

own class

Modify the SetupGlobalEventSubscribers function, so you subscribe to the database:propertychanged event – but do not add the event to the EventQueue, see below.

code change

The last step is to update the configuration in the web.config to use your new and improved class.

config

note: I have the support case number in the namespace & DLL name – so when the bug is fixed, I can remove this code and in addition any other developer at Pentia can see the history related to this support issue and why I have done such a nasty fix.

Anyway I hope this helps somebody out there 🙂

 

Sitecore SPEAK Insert Link Dialog – missing icons & sitecore tree – Don’t panic, U didn’t break it!!!!

I was upgrading a solution from 6.2 to 7.2 and it had a number of custom fields that no longer worked,  so I started to fix the code.

One of the custom fields showed the SPEAK  Insert link dialog and after making a lot of changes, I noticed that I had broken the SPEAK dialog, see below

Speak dialog....

I reviewed the changes I had made, and could not see what could have caused this issue? But to be on the safe side, I undid all of my changes, did a full build, etc and still I had the issue 😦

So I tried to open the dialog from a sitecore standard field, and it was also broken 😦

Solution

Whist starting to panic, after 5 minutes I noticed that the dialog had fixed itself!!!!

It appears that after a restart of the website the first time you open the “Insert link” dialog you have to wait 5 minutes for it to start working, after that it works straight away.

 

 

 

Sitecore 7.5 SQL Provider (WFFM 2.5) – Download for specific data range

Version 1.4 is now released and is available either as a sitecore package at sitecore marketplace or you can get the source from Github (for more details see the original post for the module)

Firstly I have to say thanks to Paul Martin (@sitecorepm) as he implemented these new features.

It is now possible to specify a date range for exporting the SQL entries (see image).

date range

The following setting  defines the delimiter to be used to separate the columns in the CSV file.
      <setting name=”WFFM.SQLServer.SaveToDatabase.CsvDelimiter” value=”;” />

 

The following setting  defines the delimiter to be used to separate the columns in the CSV file.
      <setting name=”WFFM.SQLServer.SaveToDatabase.CsvDelimiter” value=”;” />

 

 

Sitecore 7 – Disable indexing – It is not enough to set Indexing.UpdateInterval to 00:00:00.

I was working on a setup for a customer where they have a dedicated publish server and therefore it was not necessary to update the indexes. There are many post stating that to disable sitecore indexing you have to set the Indexing.UpdateInterval setting to 00:00:00 i.e.

<setting name="Indexing.UpdateInterval" value="00:00:00"/>

The website has been recently upgraded from 6.6 to 7.5 and I noticed that the indexes were still being built?

So I used Brian’s jobs page (see his blog) which listed all the running jobs to see what was running and to my shock there were a lot of index update jobs? Which meant that instead of using all the machines power to publish it was busy indexing ALL the time?

running jobs

But since Sitecore 7.0 there is an extra setting which has to be changed in order to disable indexing.

Solution

To disable indexing the BucketConfiguration.ItemBucketsEnabled setting also must be set to false in the Sitecore.Buckets.config i.e.

<setting name="BucketConfiguration.ItemBucketsEnabled" value="false"/>

Hope this helps 🙂

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)

Missing dialog’s after upgrading to Sitecore 7.5

After upgrading to Sitecore 7.5 there where a number of SPEAK dialog’s (select media dialog, insert item link, etc) that would open and show the front page of the website?

I eventually tracked it down to they fact that their where a number of duplicated SPEAK items in the core database see the image below and the fact that the solution had some custom code which showed the front page if an item has no renderings defined (not a good idea).

items

 

I believe that whist upgrading a update package failed and or did not remove the unused items.

Solution

Delete all the items that have the folder icon, and then all the dialog should work again, of course take a backup of the items before deleting them.

How to add a button to the sitecore content editor to download data as a CSV file

In this blog I will explain how to add a button to the content editor and download data as an CSV file. For this example I will assume that we want to download the data for a given web form for marketers form as a CSV file.

Adding the button
the button

Contextual Ribbons

You may not have noticed but this is a contextual ribbon that is it is only shown when the item is based on the forms template, as it gives no meaning to have the download data as CSV added to all items.

First you need to swap to the core database, and navigate to the Contextual Ribbons item for the content editor i.e. /sitecore/content/Applications/Content Editor/Ribbons/Contextual Ribbons.

This is where all the ribbons that are only shown for specific item types are placed; within this folder there is a forms toolbar, which contains a form strip, which contains a forms chunk, which in turn contains the “Export Data as CSV” button item.

button item
The most important part of the button item is the click field, which defines the command name that will be raised when the button is clicked (I will explain how to hook this up in more detail later).

But how is a contextual ribbon associated with a given template – well that part is easy on the template item under the appearance section there is a ribbon field which can define a contextual ribbon or toolbar to be shown.

co0ntextual form

How to hook the button click up to the code that is to executed? 

We have to add a command item to the /app_config/commands.config file to bind the command name to the class that is going to provide the functionality.

<command name="forms:exportformdata" type="WFFM.SQLServer.SaveToDatabase.Infrastructure.Commands.ExportFormDataCommand, WFFM.SQLServer.SaveToDatabase" />

The class must inherit from the Sitecore Command class, and override the Execute function.

    internal class ExportFormDataCommand : Command
    {
        public override void Execute(CommandContext context)
        {
            Assert.ArgumentNotNull(context, "context");
            Assert.IsNotNull(context.Items, "context items are null");
            Assert.IsTrue(context.Items.Length > 0, "context items length is 0");

            Item contextItem = context.Items[0];
            Assert.IsNotNull(contextItem, "First context item is null");
            OpenNewWindow(contextItem.ID, contextItem.Name);
        }

        private void OpenNewWindow(ID id, string name)
        {
            Assert.ArgumentNotNull(id, "id");
            UrlString url = new UrlString(Constants.Url.ExportFromDataPage);
            url.Append(Constants.QueryString.Name.ItemId, HttpContext.Current.Server.UrlEncode(id.ToString()));
            url.Append(Constants.QueryString.Name.ItemName, HttpContext.Current.Server.UrlEncode(name));
            SheerResponse.Eval(string.Format("window.open('{0}');", url));
        }
    }

Its not very elegant, but the code generates a URL which points to a aspx page that will stream the data. The Eval method of the sheer response, allows me to execute JavaScript on the client which in this case opens a tab/window.

The aspx page doesn’t do that much it just sets the ContentType to “text/csv” and streams the data. If you want to see the complete implementation, you can download it from github

Hope this was helpful, Alan