January 27, 2011

Use the sitecore jobs

When you need to do some long running operations in the Sitecore backend (like an import form example) most of the time we do that as we do for the small tasks.

But this is not a very good practice because the task is synchronous in the main thread and the admin is freeze until the task is finished.

In sitecore they are a very simple way to execute these tasks in another thread: the jobs.

Here is a small code snippet to create a job :
//Create the options and pass some attributes
JobOptions options2 = new JobOptions("The job name", "The job category", "MyWebsiteName", MyObjectInstanceThanContainTheMethodToExecute, "The Method Name To Exectute", new object[] { parameter1ForTheMethod, parameter2ForTheMethod });
options2.ContextUser = Context.User;
//This line allow to keep the job alive at least the time needed to check the lastest infos for the status.
options2.AfterLife = TimeSpan.FromMilliseconds((double)(POOLING_INTERVAL * 2));
//The thread priority
options2.Priority = System.Threading.ThreadPriority.Normal;
//Start the job himself
Job job = JobManager.Start(options2);
job.Options.CustomData = status; //Status is a object shared between my job and this class (to check the status of the import)
//Keep an instance of the if you need to check his status
this.JobHandle = job.Handle.ToString();

You may also launch a timer to check the status (how many items are already imported for example) but I will create another subject about “How to create a admin wizard”

January 14, 2011

Implement a Custom MultiListField using lucene search

I have recently experiment the Lucene search feature for sitecore. 
During my investigation I have create a custom multilist field but in place of using the classical datasource I use Lucene search to return the results. Here is the procedure to create it.

For this project I have use the shared source "Advanced Database Crawler" http://trac.sitecore.net/AdvancedDatabaseCrawler

Syntax
The syntax I have used for the datasource is:

 IndexName=advanced&Language=en&TemplateFilter=&LocationFilter=&FullTextQuery=&FieldsFilter=Title:Sample,_templatename:Lucene Demo


Those parameters are the same as in the Demo 3 of the "Advanced Search Crawler". I have used the separator ',' as separator for the Fields filter and ':' for the second member. In my example, the field 'Title' need contain the word 'Sample' and the field '_templatename' need contain 'Lucene Demo'.



Add Advanced Database Crawler
Download http://trac.sitecore.net/AdvancedDatabaseCrawler and it to your solution.

Configure Sitecore
 In the core database, duplicate the item: /sitecore/system/Field types/List Types/Multilist rename it 'LuceneMultilist'. In the field 'Control' set the value to: MyPrefix:LuceneMultilist. You may choose your prefix, it only need to be the seem as in the next step.

Add a .config file
Add /App_Config/Include/LuceneMultilist.cs.config with this content:
<configuration xmlns:x="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <controlSources>
      <source mode="on" namespace="Your Namespace" assembly="Your Assembly Name" prefix="Your Prefix as in the field control" />
    </controlSources>
  </sitecore>
</configuration>

Implement your field
Add a new project to your solution and create a new class LuceneMultilist.cs.
The only think you need to implement is inheriting for the existing MultilistEx and override the method GetItems.

Here is the code
protected override Item[] GetItems(Item current)
{
    Assert.ArgumentNotNull(current, "current");

    //Split the source from the DataSource field
    NameValueCollection splitted = Sitecore.StringUtil.GetNameValues(Source, '=', '&');
    //Split the field FieldsFilter
    NameValueCollection splittedFields = Sitecore.StringUtil.GetNameValues(splitted["FieldsFilter"], ':', ',');

    //Create the refinements to filter on the Fields values
    var refinements = new SafeDictionary<string>();
    foreach (string key in splittedFields.Keys)
    {
        refinements.Add(key, splittedFields[key]);                
    }

    //Create the parameters as in the Demo 3 of Advanced Search Crawler
    var searchParam = new FieldValueSearchParam
    {
        Refinements = refinements,
        LocationIds = splitted["LocationFilter"],
        TemplateIds = splitted["TemplateFilter"],
        FullTextQuery = splitted["FullTextQuery"],
        Occurance = QueryOccurance.Must,
        ShowAllVersions = false,
        Language = splitted["Language"]
    };

    //Execute the search
    using (var searcher = new Searcher(splitted["IndexName"]))
    {
        var items = searcher.GetItems(searchParam);
        return SearchHelper.GetItemListFromInformationCollection(items).ToArray();
    }
} 

Of course you need to add your own Lucene index or use an existing one. The tool : http://trac.sitecore.net/IndexViewer is usefull to see the content of the indexes.


It is done, Enjoy!

January 4, 2011

Interact with the user in the admin forms

In the XAML forms, you may interact with the user with these kind of method

Display a popup:
Sitecore.Context.ClientPage.ClientResponse.Alert("My message");

Download a file
Sitecore.Context.ClientPage.ClientResponse.Download(@"c:\MyPath\Myfile.xxx");

Display an input
Input(string text, string defaultValue, string validation, string validationText, int maxLength)

Change the HTML in ajax:
SheerResponse.SetInnerHtml("MyBorderName", "My String");

Launch a timer (to refresh the page every XX seconds for example)
SheerResponse.Timer("CheckStatus", 100);

If you inherit from WizardFrom these methods work perfectly, but if you inherit from Sitecore.Web.UI.Sheer.BaseForm it seem that it doesn't work.
Here is a simple workaround to bypass this limitation:
  • Add this in you xaml:

    <script type='text/javascript'>window.setTimeout('scForm.invoke("local:show")', 0)</script>
    
  • And now you can invoke these methods without problems

    [HandleMessage("local:show")]
    protected void Show(Message message)
    {
        //This method work to launch a timer
        SheerResponse.Timer("CheckStatus", 100);            
    }
    

January 3, 2011

Sitecore Visual Studio Templates

I have just found some templates for visual studio with all the think you can create for sitecore in the project http://trac.sitecore.net/SitecoreStuff

To install them you may:
Either
  • download the project: http://trac.sitecore.net/SitecoreStuff 
  • unzip it 
  • Open the folder "Visual Studio Templates"
  • Modify the install2008.cmd file if you have visual studio 2010 (if you use VS2008 it is already ok)
  • Execute it
  • Restart Visual Studio
 Or
Or
    • Install Sitecore Rocks (Thank you Lars Nielsen for this tips)
    Now you should have something like this when you add a item in visual studio:

    Thank you the creators of those templates!