UPDATE [aspnet_Membership] SET Password='qOvF8m8F2IcWMvfOBjJYHmfLABc='
WHERE UserId IN (SELECT UserId FROM [aspnet_Users] WHERE UserName = 'sitecore\Admin')
Sitecore Blog
May 29, 2012
Reset the admin passord
To reset the 'admin' password to 'b' the easest way is to execute this SQL script on the core database:
April 16, 2012
How to create a custom Multilist field not related to the items
Sometimes you need to create any fields who list and store some values but you don’t have any sitecore items related to those values. For example, in one of our projects we have a list of categories who come from a webservice.
To do that easily, I have created a base class that you can download here
(the code of this file is also at the bottom of this post)
After that you need to impelemnt your field by creating a new class who will inherit from my base class. Here is the skeleton of this class.
where the key is the id stored into the sitecore field and the value is the display text. With this method you can really have the control of what is stored and display into the field.

But you can see that you can handle the raw value as I want:
If you want to be complete, you can also create the field who will be used into your code to retrieve the content of your field (as you use the fields from Sitecore.Data.Fields). The most important method here it the GetAvailableFields() method where you need to return the list of objects corresponding to the raw value.
Here is the source code of my base class:
To do that easily, I have created a base class that you can download here
(the code of this file is also at the bottom of this post)
After that you need to impelemnt your field by creating a new class who will inherit from my base class. Here is the skeleton of this class.
public class Test : MultilistExBase
{
protected override void InitRendering()
{
//You can Initialise some variables here.
}
protected override IEnumerable<KeyValuePair<string, string>> GetNonSelectedItems()
{
//Return here your unselected items. First value is the ID you will store into your field, the second one is the display text.
}
protected override IEnumerable<KeyValuePair<string, string>> GetSelectedItems()
{
//Return here your selected items. First value is the ID you will store into your field, the second one is the display text.
}
}
You need to implement only 3 methods :
- InitRendering: Allow you to initialize your variables, webservice, ...
- GetNonSelectedItems: You need to return the list of unselected items
- GetSelectedItems: You need to return the list of selected items
- To create your customfield into sitecore you need:
- Register your namespace in the
tag of your .config file
<controlSources> <source mode="on" namespace="MyNamespace" assembly="MyAssembly" prefix="myControls"/> </controlSources> - Create a new item based on the /sitecore/templates/System/Templates/Template field type in the core database below /sitecore/system/Field types/List Types

But you can see that you can handle the raw value as I want:
If you want to be complete, you can also create the field who will be used into your code to retrieve the content of your field (as you use the fields from Sitecore.Data.Fields). The most important method here it the GetAvailableFields() method where you need to return the list of objects corresponding to the raw value.
public class TestField : DelimitedField
{
// Methods
public TestField(Field innerField)
: base(innerField, '|')
{
}
public List<MyObject> GetAvailableFields()
{
//Return the list of object corresponding to the raw value
List<MyObject> lst = new List<MyObject>();
foreach (var item in this.Items)
{
lst.Add(new MyObject(item));
}
return lst;
}
public static implicit operator TestField(Field field)
{
if (field != null)
{
return new TestField(field);
}
return null;
}
}
Here is the source code of my base class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sitecore.Shell.Applications.ContentEditor;
using Sitecore.Diagnostics;
using Sitecore.Data.Items;
using System.Collections;
using Sitecore;
using Sitecore.Globalization;
using Sitecore.Resources;
using System.Web.UI;
using Sitecore.Text;
using Sitecore.Data;
namespace BaseFields
{
public abstract class MultilistExBase : Sitecore.Shell.Applications.ContentEditor.MultilistEx
{
/// <summary>
/// Return here your unselected items. First value is the ID you will store into your field, the second one is the display text.
/// </summary>
/// <returns>The unselected items</returns>
protected abstract IEnumerable<KeyValuePair<string, string>> GetNonSelectedItems();
/// <summary>
/// Return here your selected items. First value is the ID you will store into your field, the second one is the display text.
/// </summary>
/// <returns>The selected items</returns>
protected abstract IEnumerable<KeyValuePair<string, string>> GetSelectedItems();
/// <summary>
/// By overideing this method, you can initialise some variables here.
/// </summary>
protected virtual void InitRendering()
{
}
protected override void DoRender(System.Web.UI.HtmlTextWriter output)
{
Assert.ArgumentNotNull(output, "output");
base.ServerProperties["ID"] = this.ID;
InitRendering();
string text = string.Empty;
if (this.ReadOnly)
{
text = " disabled=\"disabled\"";
}
output.Write(string.Concat(new string[]
{
"<input id=\"",
this.ID,
"_Value\" type=\"hidden\" value=\"",
StringUtil.EscapeQuote(this.Value),
"\" />"
}));
output.Write("<table" + this.GetControlAttributes() + ">");
output.Write("<tr>");
output.Write("<td class=\"scContentControlMultilistCaption\" width=\"50%\">" + Translate.Text("All") + "</td>");
output.Write("<td width=\"20\">" + Images.GetSpacer(20, 1) + "</td>");
output.Write("<td class=\"scContentControlMultilistCaption\" width=\"50%\">" + Translate.Text("Selected") + "</td>");
output.Write("<td width=\"20\">" + Images.GetSpacer(20, 1) + "</td>");
output.Write("</tr>");
output.Write("<tr>");
output.Write("<td valign=\"top\" height=\"100%\">");
output.Write(string.Concat(new string[]
{
"<select id=\"",
this.ID,
"_unselected\" class=\"scContentControlMultilistBox\" multiple=\"multiple\" size=\"10\"",
text,
" ondblclick=\"javascript:scContent.multilistMoveRight('",
this.ID,
"')\" onchange=\"javascript:document.getElementById('",
this.ID,
"_all_help').innerHTML=this.selectedIndex>=0?this.options[this.selectedIndex].innerHTML:''\" >"
}));
//Bind the selected values?
foreach (KeyValuePair<string, string> field in GetNonSelectedItems())
{
//Item item2 = dictionaryEntry.Value as Item;
//if (item2 != null)
//{
output.Write(string.Concat(new string[]
{
"<option value=\"",
field.Key,
"\">",
field.Value,
"</option>"
}));
//}
}
output.Write("</select>");
output.Write("</td>");
output.Write("<td valign=\"top\">");
this.RenderButton(output, "Core/16x16/arrow_blue_right.png", "javascript:scContent.multilistMoveRight('" + this.ID + "')");
output.Write("<br />");
this.RenderButton(output, "Core/16x16/arrow_blue_left.png", "javascript:scContent.multilistMoveLeft('" + this.ID + "')");
output.Write("</td>");
output.Write("<td valign=\"top\" height=\"100%\">");
output.Write(string.Concat(new string[]
{
"<select id=\"",
this.ID,
"_selected\" class=\"scContentControlMultilistBox\" multiple=\"multiple\" size=\"10\"",
text,
" ondblclick=\"javascript:scContent.multilistMoveLeft('",
this.ID,
"')\" onchange=\"javascript:document.getElementById('",
this.ID,
"_selected_help').innerHTML=this.selectedIndex>=0?this.options[this.selectedIndex].innerHTML:''\">"
}));
//Bind the available items list
foreach (KeyValuePair<string, string> field in GetSelectedItems())
{
output.Write(string.Concat(new string[]
{
"<option value=\"",
field.Key,
"\">",
field.Value,
"</option>"
}));
}
output.Write("</select>");
output.Write("</td>");
output.Write("<td valign=\"top\">");
this.RenderButton(output, "Core/16x16/arrow_blue_up.png", "javascript:scContent.multilistMoveUp('" + this.ID + "')");
output.Write("<br />");
this.RenderButton(output, "Core/16x16/arrow_blue_down.png", "javascript:scContent.multilistMoveDown('" + this.ID + "')");
output.Write("</td>");
output.Write("</tr>");
output.Write("<tr>");
output.Write("<td valign=\"top\">");
output.Write("<div style=\"border:1px solid #999999;font:8pt tahoma;padding:2px;margin:4px 0px 4px 0px;height:14px\" id=\"" + this.ID + "_all_help\"></div>");
output.Write("</td>");
output.Write("<td></td>");
output.Write("<td valign=\"top\">");
output.Write("<div style=\"border:1px solid #999999;font:8pt tahoma;padding:2px;margin:4px 0px 4px 0px;height:14px\" id=\"" + this.ID + "_selected_help\"></div>");
output.Write("</td>");
output.Write("<td></td>");
output.Write("</tr>");
output.Write("</table>");
}
private void RenderButton(HtmlTextWriter output, string icon, string click)
{
Assert.ArgumentNotNull(output, "output");
Assert.ArgumentNotNull(icon, "icon");
Assert.ArgumentNotNull(click, "click");
ImageBuilder imageBuilder = new ImageBuilder();
imageBuilder.Src = icon;
imageBuilder.Width = 16;
imageBuilder.Height = 16;
imageBuilder.Margin = "2px";
if (!this.ReadOnly)
{
imageBuilder.OnClick = click;
}
output.Write(imageBuilder.ToString());
}
}
}quot;_selected_help').innerHTML=this.selectedIndex
March 14, 2012
Add a custom section in the config
Here is the method if you need to a custom section into you config file.
Here is my example of config that I need to include into my \App_Config\Include folder:
And here is a way to read it:
Don’t forget to use a property “Name” to avoid the conflicts in the include folder (see this post: http://sitecoreblog.blogspot.com/2012/02/config-patching-system-for-external.html)
Here is my example of config that I need to include into my \App_Config\Include folder:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <MyCustomSection> <MyCustomElement Name="XXX" MyProperty="YYY" /> <MyCustomElement Name="AAA" MyProperty="BBB" /> </MyCustomSection> </sitecore> </configuration>
And here is a way to read it:
using System.Collections.Generic;
using Sitecore.Configuration;
using System.Xml;
using Sitecore.Xml;
/// <summary>
/// TODO: Update summary.
/// </summary>
public class MyConfigElement
{
//The two properties corresponding to the properties into the config
public string Name { get; set; }
public string MyProperty { get; set; }
//The method who return the list of my custom elements
public static List<MyConfigElement> GetListMyCustomElements()
{
List<MyConfigElement> lst = new List<MyConfigElement>();
//Read the configuration nodes
foreach (XmlNode node in Factory.GetConfigNodes("MyCustomSection/MyCustomElement"))
{
//Create a element of this type
MyConfigElement elem = new MyConfigElement();
elem.Name = XmlUtil.GetAttribute("Name", node);
elem.MyProperty = XmlUtil.GetAttribute("MyProperty", node);
lst.Add(elem);
}
return lst;
}
}
Don’t forget to use a property “Name” to avoid the conflicts in the include folder (see this post: http://sitecoreblog.blogspot.com/2012/02/config-patching-system-for-external.html)
March 2, 2012
Include the sc namespace
When you have multiple projects in a single solution you will maybe have this error message when you try to use some sitecore controls like the sc:Text:
You have to simple solutions to fix this problem:
You may add this line on the top of each files:
Or you may add a web.config into your project with the minimal information to include this namespace.
But don’t deploy this web.config in your solution because it will override the correct sitecore web.config
You may add this line on the top of each files:
<%@ Register Assembly="Sitecore.Kernel" Namespace="Sitecore.Web.UI.WebControls" TagPrefix="sc" %>
Or you may add a web.config into your project with the minimal information to include this namespace.
But don’t deploy this web.config in your solution because it will override the correct sitecore web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<pages validateRequest="false">
<controls>
<add tagPrefix="sc" namespace="Sitecore.Web.UI.WebControls" assembly="Sitecore.Kernel" />
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add tagPrefix="sc" namespace="Sitecore.Web.UI.WebControls" assembly="Sitecore.Analytics" />
</controls>
</pages>
</system.web>
</configuration>
February 17, 2012
Team development for sitecore (TDS) - Double build required
With Team development for sitecore (TDS) some developers of my company complain that they need to build the solution twice to have they change in the deploy folder.
After some investigations, I have found that sometime TDS doesn't create the dependencies correctly. And, with those dependencies not correctly set the TDS project is build before the project to deploy.
The bug fix is pretty easy:
After some investigations, I have found that sometime TDS doesn't create the dependencies correctly. And, with those dependencies not correctly set the TDS project is build before the project to deploy.
The bug fix is pretty easy:
- Right click on your solution and then on "properties"
- In the "project" dropdown select your TDS project to deploy and check the corresponding project to deploy
February 15, 2012
Config patching system for the external config files
This very good post http://www.thescrewballdivision.com/playing-with-sitecore-include-files explain the available commands for the patching very well so I will not copy it but I will add an important information.
When you need to add some informations in a tag the key used for the merge is the property name.
Example:
By default in the web.config you have this:
And if you add this in a separated config file:
The merged web.config will be:
To avoid this and combine the two tags without removing the existing one you only have to add a name property in the site tag:
Like this you will have the expected result:
When you need to add some informations in a tag the key used for the merge is the property name.
Example:
By default in the web.config you have this:
<event name="publish:end">
<handler type="Sitecore.Publishing.HtmlCacheClearer, Sitecore.Kernel" method="ClearCache">
<sites hint="list">
<site>website</site>
</sites>
</handler>
</event>
And if you add this in a separated config file:
<event name="publish:end">
<handler type="Sitecore.Publishing.HtmlCacheClearer, Sitecore.Kernel" method="ClearCache">
<sites hint="list">
<site>mysite</site>
</sites>
</handler>
</event>
The merged web.config will be:
<event name="publish:end">
<handler type="Sitecore.Publishing.HtmlCacheClearer, Sitecore.Kernel" method="ClearCache">
<sites hint="list">
<site>mysite</site>
</sites>
</handler>
</event>
To avoid this and combine the two tags without removing the existing one you only have to add a name property in the site tag:
<event name="publish:end">
<handler type="Sitecore.Publishing.HtmlCacheClearer, Sitecore.Kernel" method="ClearCache">
<sites hint="list">
<site name="mysite">mysite</site>
</sites>
</handler>
</event> Like this you will have the expected result:
<event name="publish:end">
<handler type="Sitecore.Publishing.HtmlCacheClearer, Sitecore.Kernel" method="ClearCache">
<sites hint="list">
<site>website</site>
<site name="mysite">mysite</site>
</sites>
</handler>
</event>
February 9, 2012
Error message - The operation could not be completed
I post here an error message I had yesterday on the sitecore of one of our customer because I don't have found this answer on the sdn site of in the forums.
We had randomly some error messages:
"The operation could not be completed.
Your session may have been lost due to a time-out or a server failure.
Try again."
After investigation, I don't have found any error messages in the logs or in the windows event viewer. But, we had multiple log files with the same datetime.
In fact the resolution was pretty simple the number of worker process of the application pool was set to 5 but it must be set to 1.
To change it:
We had randomly some error messages:
"The operation could not be completed.
Your session may have been lost due to a time-out or a server failure.
Try again."
After investigation, I don't have found any error messages in the logs or in the windows event viewer. But, we had multiple log files with the same datetime.
In fact the resolution was pretty simple the number of worker process of the application pool was set to 5 but it must be set to 1.
To change it:
- In iis select your application pool and click on the "Advanced settings" button
- In the "Process Model" section, set the "Maximum Worker Process" to 1.
February 7, 2012
Share the config file : how to handle the path like the dataFolder
When we use SVN or TFS normally we commit some .config file an especially the web.config. The problem happened when all the computers doesn’t have the same path structure. For example I will not use the same data folder as my colleague.
You have multiple solutions to handle including having different build configuration but I think that the easiest way to handle it is by simply using the virtual directories.
To create a virtual directory:- In IIS right click on your website and select “Add Virtual Directory”
- The alias is the folder name (in your config file) and the physical path is the real folder
- In the config, the datafolder will look like
<sc.variable name="dataFolder" value="/Data" />
February 6, 2012
Remote events how to investigate
I had some issues with the sitecore remote events not triggered on the content delivery. I will explain how you can investigate why it could happened and how to fix it.
First of all, how sitecore handle the remote events when you use the scalability?
When you publish an item in sitecore, sitecore will write a line in the EventQueue table of the corresponding database with all the necessary data including the InstanceName of the server who have triggered the event.
After that sitecore have an timer who check in this table if they are any event to trigger. First remark, sitecore look at the InstanceName field to know if this instance need to trigger this record or not so this instance need to be unique (be carefull with the copy paste) ;-).
Here is what sitecore add in the web database in the EventQueue when you publish an item:
The most important columns are :
This is the first method to see if your events are trigered.
For the second method, you need to set in the web.config of each server the <events timingLevel="high"> setting (this setting is set to custom by default).
With this modification you should have any line like this for each event handled by sitecore in your log on both content delivery and content management instances.
If even with all those informations your events are not triggered or triggered but not received in by the other server you can try to cleanup the temporary event tables.
On each database execute those scripts:
I don't know exactly what is the EQStamp% setting but it was the solution provided by the support and it has solved my problem :) If anybody know what is is exactly you can post a comment.
Be also careful to the exception in your events because if one event of the pipeline throw an exception the other one will be not executed.
First of all, how sitecore handle the remote events when you use the scalability?
When you publish an item in sitecore, sitecore will write a line in the EventQueue table of the corresponding database with all the necessary data including the InstanceName of the server who have triggered the event.
After that sitecore have an timer who check in this table if they are any event to trigger. First remark, sitecore look at the InstanceName field to know if this instance need to trigger this record or not so this instance need to be unique (be carefull with the copy paste) ;-).
Here is what sitecore add in the web database in the EventQueue when you publish an item:
| Id | 82480059-8CF4-4D2E-82B1-9C00323F12F2 |
| EventType | Sitecore.Eventing.Remote.PublishEndRemoteEvent, Sitecore.Kernel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=null |
| InstanceType | Sitecore.Eventing.Remote.PublishEndRemoteEvent, Sitecore.Kernel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=null |
| InstanceData | {"CompareRevisions":true,"Deep":false,"FromDate":"\/Date(-5339901827822+0200)\/","LanguageName":"en","Mode":3,"PublishDate":"\/Date(1328532964271+0100)\/","PublishingTargets":["{8E080626-DDC3-4EF4-A1D1-F0BE4A200254}","{8E080626-DDC3-4EF4-A1D1-F0BE4A200254}"],"RepublishAll":false,"RootItemId":"ebff6e2a-9149-4660-9d55-dec34282f856","SourceDatabaseName":"master","TargetDatabaseName":"web"} |
| InstanceName | GRNQ6R1-sitecore650up3 |
| RaiseLocally | 0 |
| RaiseGlobally | 1 |
| UserName | sitecore\admin |
| Stamp | 0x0000000000079C0F |
| Created | 2012-02-06 12:56:07.033 |
The most important columns are :
- "InstanceName": it is the server who have triggered the event. (setting "InstanceName" from ScalabilitySettings.config)
- "EventType": The type of event: item:saved:remote, publish:end:remote, ...
- "InstanceData": The data required to perform this operation
This is the first method to see if your events are trigered.
For the second method, you need to set in the web.config of each server the <events timingLevel="high"> setting (this setting is set to custom by default).
With this modification you should have any line like this for each event handled by sitecore in your log on both content delivery and content management instances.
Heartbeat 14:22:05 INFO Event started: publish:statusUpdated Heartbeat 14:22:05 INFO Executed: Sitecore.Publishing.RemotePublishingEventHandler.OnStatusUpdated(). Elapsed: 4,23265309264199 Heartbeat 14:22:05 INFO Event ended: publish:statusUpdated. Elapsed: 4,33442834380877
If even with all those informations your events are not triggered or triggered but not received in by the other server you can try to cleanup the temporary event tables.
On each database execute those scripts:
DELETE FROM EventQueue; DELETE FROM [Properties] WHERE [Key] LIKE 'EQStamp%';
I don't know exactly what is the EQStamp% setting but it was the solution provided by the support and it has solved my problem :) If anybody know what is is exactly you can post a comment.
Be also careful to the exception in your events because if one event of the pipeline throw an exception the other one will be not executed.
November 15, 2011
Add a publish button in the contextual menu
To add a publish button in the contextal menu as in the screenshot below it is very simple:
- Open the core database
- Go to the item /sitecore/content/Applications/Content Editor/Context Menues/Default and duplicate the item Insert for example
- Set the fields values to:
- Display Name: Publish Item
- Message: item:publish(id=$Target)
October 18, 2011
Retreive the content editor language and item version
Here is a small tip to retreive the language and the version of the item selected in the sitecore content editor when you create a custom field for example.
Thank you to Mister Tony Locatelli from LBi Belgium for this tip :)
public class MyCustomField : CustomDropListField
{
public string ItemLanguage { get; set; }
public string ItemVersion { get; set; }
}
Thank you to Mister Tony Locatelli from LBi Belgium for this tip :)
October 13, 2011
Crash IIS event 5011 and how to add your unhandled exceptions in the event viewer
Recently I had a bug in one of my website because of a recursive infinite loop. The effect was some random restart of IIS but noting in the sitecore logs and not way to know why.
In the windows event viewer I saw in the IIS section that the I had some IIS crashes with the event code 5011.
After googling a little bit I found this website: http://martinnormark.com/how-to-handle-iis-event-id-1009-event-id-5011-on-iis-7
So, if you create a dll with this class
Add add this
You will have more details about the cause of this error a StackOverflowException in my case.
It takes me a lot of time to find why because I didn't find how to know witch line or class cause the exception but it already help a lot :)
This class also adds all the unhandled error in the event viewer so it is also great to have it.
In the windows event viewer I saw in the IIS section that the I had some IIS crashes with the event code 5011.
After googling a little bit I found this website: http://martinnormark.com/how-to-handle-iis-event-id-1009-event-id-5011-on-iis-7
So, if you create a dll with this class
#region Using
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Web;
#endregion
/// <summary>
/// Handles all unhandled exceptions from in the current AppDomain.
///
/// Works great to catch unhandled exceptions thrown by IIS's child threads, /// which will make the application pool terminate unexpectedly
/// without logging. This makes sure your Exception /// is logged to the Application event log.
/// </summary>
public class UnhandledExceptionModule : IHttpModule
{
#region Fields
private static int _UnhandledExceptionCount = 0;
private static string _SourceName = null;
private static object _InitLock = new object();
private static bool _Initialized = false;
#endregion
#region IHttpModule members
public void Init(HttpApplication app)
{
// Do this one time for each AppDomain.
if (!_Initialized)
{
lock (_InitLock)
{
if (!_Initialized)
{
string webenginePath = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "webengine.dll");
if (!File.Exists(webenginePath))
{
throw new Exception(String.Format(CultureInfo.InvariantCulture, "Failed to locate webengine.dll at '{0}'. This module requires .NET Framework 2.0.", webenginePath));
}
FileVersionInfo ver = FileVersionInfo.GetVersionInfo(webenginePath);
_SourceName = string.Format(CultureInfo.InvariantCulture, "ASP.NET {0}.{1}.{2}.0", ver.FileMajorPart, ver.FileMinorPart, ver.FileBuildPart);
if (!EventLog.SourceExists(_SourceName))
{
throw new Exception(String.Format(CultureInfo.InvariantCulture, "There is no EventLog source named '{0}'. This module requires .NET Framework 2.0.", _SourceName));
}
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);
_Initialized = true;
}
}
}
}
public void Dispose()
{
}
#endregion
#region UnhandledException event handler
public void OnUnhandledException(object o, UnhandledExceptionEventArgs e)
{
// Let this occur one time for each AppDomain.
if (Interlocked.Exchange(ref _UnhandledExceptionCount, 1) != 0)
return;
StringBuilder message = new StringBuilder("\r\n\r\nUnhandledException logged by UnhandledExceptionModule:\r\n\r\nappId=");
string appId = (string)AppDomain.CurrentDomain.GetData(".appId");
if (appId != null)
{
message.Append(appId);
}
Exception currentException = null;
for (currentException = (Exception)e.ExceptionObject; currentException != null; currentException = currentException.InnerException)
{
message.AppendFormat("\r\n\r\ntype={0}\r\n\r\nmessage={1}\r\n\r\nstack=\r\n{2}\r\n\r\n",
currentException.GetType().FullName,
currentException.Message,
currentException.StackTrace);
}
EventLog Log = new EventLog();
Log.Source = _SourceName;
Log.WriteEntry(message.ToString(), EventLogEntryType.Error);
}
#endregion
}
Add add this
<httpmodules>
<add name="UnhandledExceptionModule" type="UnhandledExceptionModule"/>
.....
</httpmodules>
You will have more details about the cause of this error a StackOverflowException in my case.
It takes me a lot of time to find why because I didn't find how to know witch line or class cause the exception but it already help a lot :)
This class also adds all the unhandled error in the event viewer so it is also great to have it.
October 12, 2011
Open the content editor on a specific item
First technique
useful if you need to generate a link to send to one of your editors.The format of this link will be :
http://Youthostname/sitecore/shell/Applications/Content Editor?id=%7b9822ABDF-F2B7-41BA-B56D-63E73BEB7E88%7d&vs=1&la=en&sc_content=master&fo=%7b9822ABDF-F2B7-41BA-B56D-63E73BEB7E88%7d&ic=People%2f16x16%2fcubes_blue.png&he=Content+Editor&cl=0
Where the parameters are:
- Id & fo: the ID of the target item
- vs: the version of the target item.
- la: the language of the target item
- sc_content: the database
The second technique
useful of you need to open it from one of your xaml application :UrlString str = new UrlString();
.Add("id", id);
str.Add("fo", id);
Windows.RunApplication("Content editor", str.ToString());
The third technique
In javascript: (a contribution of Mark Ursino. Thank you!)http://firebreaksice.com/link-directly-to-a-sitecore-item-in-a-custom-editor/
September 20, 2011
Sitecore installation tips and tricks
Recently I have done one of the most difficult installation of sitecore I have never done. Not because of sitecore himself but because of IIS, the firewall, the sql server, …
Here is some tips you can use if you have some trouble to install sitecore :
IIS Errors
If you have this error : « This configuration section cannot be used at this path. This happens when the section is locked at a parent level. Locking is either by default (overrideModeDefault='Deny'), or set explicitly by a location tag with overrideMode='Deny' or the legacy allowOverride='false'. »
If the website return a blank page or an error:
SQL Errors
If you have an sql error :
If the website return a blank page :
If the license is missing :
Here is some tips you can use if you have some trouble to install sitecore :
IIS Errors
If you have this error : « This configuration section cannot be used at this path. This happens when the section is locked at a parent level. Locking is either by default (overrideModeDefault='Deny'), or set explicitly by a location tag with overrideMode='Deny' or the legacy allowOverride='false'. »
- Execute this command : %windir%\system32\inetsrv\appcmd.exe unlock config -section:system.webServer/security/requestFiltering
If the website return a blank page or an error:
- Check if all the required windows component are installed (IIS, Dotnet, …)
- Check if the server doesn’t need a reboot to install some components or updates
- Execute an aspnet_regiis –i
- Check if you don’t have some strange Query strings or http verbs blocked in the IIS request filtering
SQL Errors
If you have an sql error :
- Check your connectionstring in connectionstrings.config
- Check if the local firewall doesn’t block your query (cf windows eventviewer)
- Check if the global firewall doesn’t block the request
- from the web server to the sql server
- from the sql server to the web server
- Check the network route is correct (especially if you have more than one network card on this server) (use the command « route PRINT » to see it) and use the command « route –p add » if needed
- Put the server name in the hostfile
- If you use the active directory
- you will maybe need to use the impersonate (cf. web.config)
- The user need to have the access write to the web server and the sql server
If the website return a blank page :
- Try to add a page test.htm at the root of your website folder and call it to see if iis work.
If the license is missing :
- Check in the web.config if the datafolder and the licensefolder is set correctly
- Check if the App Pool user have the read access to the license.xml file
- Check if the license file is correct
- Unzip and execute this package (as administrator) : http://sdn.sitecore.net/upload/sdn5/faq/administration/sitecorecounters.zip
- Check if the user of the App Pool is in the windows user group : « Performance Monitor Users »
- If you want to use the Framework 4.0 http://sdn.sitecore.net/upload/sitecore6/64/integrating%20an%20asp.net%20mvc%20web%20application%20in%20sitecore%20cms-a4.pdf
- If possible set the App Pool in « Integrated » mode
July 15, 2011
New module on trac
Here is my first contribution in association with the LBi to the Shared Source library.
http://trac.sitecore.net/ScheduledTaskUtils
This module allows you to run manually a sitecore scheduler. This is very useful especially when you try to debug a scheduler.
Here is a small screenshot
http://trac.sitecore.net/ScheduledTaskUtils
This module allows you to run manually a sitecore scheduler. This is very useful especially when you try to debug a scheduler.
Here is a small screenshot
If you have some bug of improvement request, you can post a reply to this post.
Categories : Sitecore,
Admin and Security,
Shared Source
June 23, 2011
Create a custom remote event in sitecore
Recently, I had to clear some cache on the frontend server from my backend.
To do that I have implemented a custom remote event. I did not find some documentation on sdn so here is the procedure (thank you to the Sergey Kravchenko from the sitecore support).
How does it work?
To do that I have implemented a custom remote event. I did not find some documentation on sdn so here is the procedure (thank you to the Sergey Kravchenko from the sitecore support).
- Create your custom remote event class. Remote event class is a usual class inherited from System.Object and marked with a [DataContract] attribute.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.Serialization; namespace XXX { [DataContract] public class ClearCacheEvent { public ClearCacheEvent() { } } } - Create a custom event arguments class, to store the arguments of the event. It also, can be empty. Both Remote event class and event arguments class will be used to add event to the EventQueue.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Sitecore.Events; namespace XXX { public class ClearCacheEventArgs : EventArgs, IPassNativeEventArgs { public ClearCacheEventArgs(ClearCacheEvent @event) { } } } - Create your custom event handler
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Sitecore.Diagnostics; using Sitecore.Events; namespace XXX { public class ClearCacheEventHandler { /// <summary> /// The methos is the method that you need to implement as you do normally /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public virtual void OnClearCacheRemote(object sender, EventArgs e) { Log.Info("Tadaa", this); } /// <summary> /// This methos is used to raise the local event /// </summary> /// <param name="event"></param> public static void Run(ClearCacheEvent @event) { Log.Info("ClearCacheEventHandler - Run", typeof(ClearCacheEventHandler)); ClearCacheEventArgs args = new ClearCacheEventArgs(@event); Event.RaiseEvent("clearcache:remote", new object[] { args }); } } } - Create a custom Hook to bind event from the EventQueue and the "local event" in the CD server web config. This hook will call the method you have added in the event handler ("Run" method of the ClearCacheEventHandler class in our case)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Sitecore.Events.Hooks; namespace XXX { public class ClearCacheHook : IHook { public void Initialize() { Sitecore.Eventing.EventManager.Subscribe(new Action (ClearCacheEventHandler.Run)); } } } - Trigger the event in your code
ClearCacheEvent inst = new ClearCacheEvent(); Sitecore.Eventing.EventManager.QueueEvent<ClearCacheEvent>(inst);
- Configure the web.config (or add it in a separated file in the /include folder it is cleaner)
The hook:
<hooks> <hook type="XXX.ClearCacheHook, XXX"/> </hooks>The event:
<events> <event name="clearcache:remote"> <handler type="XXX.ClearCacheEventHandler, XXX" method="OnClearCacheRemote"/> </event> </events>
How does it work?
- Your code add an event in the EventQueue.
- The EventQueue is checked by the special task:
<eventQueue> <processingInterval>00:00:02</processingInterval> </eventQueue> - The Hook call a method who raise the corresponding local event.
- Your local is triggered.
June 7, 2011
The page editor is not yet available
I have recently experiment a bug with the webedit mode in sitecore 6.4.1. When I try to add some components on some pages I have this message: "The page editor is not yet available".
In fact, it append if a layout or a sublayout contains an ASP.NET LinkButton with a PostBackUrl attribute
As a workaround, you can wrap your line with PostBackUrl attribute in the “if” clause like this:
Thank you to the sitecore support. I will maybe see some of you at the London dreamcore :)
In fact, it append if a layout or a sublayout contains an ASP.NET LinkButton with a PostBackUrl attribute
As a workaround, you can wrap your line with PostBackUrl attribute in the “if” clause like this:
if ((!Sitecore.Context.PageMode.IsPageEditor) && (!Sitecore.Context.PageMode.IsPreview))
{
lbLink.PostBackUrl = Utils.GetUrlFromGeneralLink(tmpItem, "Link");
}
Thank you to the sitecore support. I will maybe see some of you at the London dreamcore :)
May 26, 2011
Add a custom property to the site node
Here is an easy way to add and retrieve a custom property to you site in the .config file.
Here is an example with my custom property SiteUID
- Add this property to your site tag:
<site patch:after="*[contains(@name, 'login')]" hostName="uk.xxx" targetHostName="uk.xxx" name="UK" siteUID="MyUniqueID" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content/United Kingdom/Website" startItem="/Homepage" contentStartItem="/sitecore/content/United Kingdom/Website/Homepage" database="web" domain="extranet" allowDebug="true" cacheHtml="true" htmlCacheSize="10MB" registryCacheSize="0" viewStateCacheSize="0" xslCacheSize="5MB" filteredItemsCacheSize="2MB" enablePreview="true" enableWebEdit="true" enableDebugger="true" disableClientData="false" language="en"/> - Create an extension method:
/// <summary> /// Retrun the site unique ID /// </summary> /// <returns></returns> public static string SiteUID(this SiteContext site) { Assert.IsNotNull(site, "Site cannot be null"); try { string uid = site.Properties["siteUID"]; if (!String.IsNullOrEmpty(uid)) return uid; else return site.Name; } catch (Exception) { return site.Name; } } - Use this property in your code: (don't forget to add you using to the class with your extention method)
Sitecore.Context.Site.SiteUID()
Write you messages in a separated file
It is not always easy with a sitecore "out of the box" to know witch messages come from your custom code and witch messages come from sitecore himself.
Here is a small tip to write you custom messages in a separated file:
First of all, we will prefix all our messages with a custom prefix "SH - " in my case:
And then to write it in a custom log file change in the web.config in the log4net section:
And second point after the logFileAppender of sitecore add you custom one:
You have a lot of example of what you can do with log4net here: http://logging.apache.org/log4net/release/config-examples.html
Here is a small tip to write you custom messages in a separated file:
First of all, we will prefix all our messages with a custom prefix "SH - " in my case:
Log.Info("SH - My message", typeof(MyObject));
Log.Error("SH - My message", typeof(MyObject));
...
And then to write it in a custom log file change in the web.config in the log4net section:
<appender name="MyFileAppender" type="log4net.Appender.SitecoreLogFileAppender, Sitecore.Logging">
<file value="$(dataFolder)/logs/mylog.{date}.txt" />
<filter type="log4net.Filter.StringMatchFilter">
<regexToMatch value="^SH .*" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%4t %d{ABSOLUTE} %-5p %m%n" />
</layout>
</appender>
You will need to adapt the regex with your custom prefix of course.And second point after the logFileAppender of sitecore add you custom one:
<root>
<priority value="DEBUG"/>
<appender-ref ref="LogFileAppender"/>
<appender-ref ref="MyFileAppender" />
</root>You have a lot of example of what you can do with log4net here: http://logging.apache.org/log4net/release/config-examples.html
April 28, 2011
Infinite loop when using sitecore and the iis url rewriting
Recently I have install the ULRewrite module for IIS7 : http://www.iis.net/download/URLRewrite
Everything was good but during my tests with IE7 I had a strange comportment: I have an infinite loop on the error page.
In fact, it was a mistake during the configuration of this module. Effectively, this module add this section in the web.config.
Everything was good but during my tests with IE7 I had a strange comportment: I have an infinite loop on the error page.
In fact, it was a mistake during the configuration of this module. Effectively, this module add this section in the web.config.
<httpErrors> <remove statusCode="404" subStatusCode="-1" /> <error statusCode="404" prefixLanguageFilePath="" path="/notfound" responseMode="ExecuteURL" /> </httpErrors> </system.webServer>But the error page I have configured as the ItemNotFoundUrl is error-page-not-found.aspx:
<setting name="ItemNotFoundUrl" value="/sitecore/service/error-page-not-found.aspx" />So we only need to put this url of our custom error page in path="XXX” or simply remove the section <httpErrors>
Subscribe to:
Posts (Atom)









