Thursday, October 18, 2007

Things to remember before going to production


  1. Load testing with best in breed tools.
  2. Scan the Sitecore log files for latest 3 days and...
    • Any exceptions in the Sitecore Log files should be reported to tech support.
    • Any exceptions related to .NET Framework, ASP.NET worker process in the System Event Log should be investigated and reported to tech support.
  3. Special attention should be paid to the Item and Memory threshold warning in the log file.

The important thing to notice is the Page URL. If the front-end pages (not /sitecore/...  pages) are listed in these reports, there could be a potential problem in the code or ways to enhance to logic.

For example, the warning below shows that the timing exceeded the predefined limit:

5736 10:33:36 WARN  Timing threshold exceeded for web page. Milliseconds: 13072.38. Threshold: 7500. Page URL: /Default.aspx

while this message says that the logic of the page is trying to access more that the predefined limit of items:

6548 10:33:49 WARN  Item threshold exceeded for web page. Items accessed: 16715. Threshold: 7500. Page URL: /Default.aspx

So your actions:

  1. Identify the rendering logic producing such delay and heavy logic using Sitecore Debug mode.
  2. Refactor the code according to best practices (more about this below).
  3. Verify that this helped by scanning the log files and using Debug mode.

Best Practices and Techniques:

More about the predefined threshold parameters:

Wednesday, October 17, 2007

Publish related media items


Often users are curious why when they publish articles, the media associated with this article was not published.

There is one simple explanation - media items/assets in Sitecore are considered as separate content items and should be published separately.

Thanks to the powerful Sitecore Workflow engine that can be easily extended using workflow actions, it is possible to publish related media items by means of a special workflow action.

So by simply adding a workflow action before the Auto Publish action with the logic below, you will ensure that the relations will be published before the actual item:

workflow_actions

The code of the workflow action:

using System;

using Sitecore;
using Sitecore.Configuration;
using Sitecore.Data.Items;
using Sitecore.Links;
using Sitecore.Publishing;
using Sitecore.Workflows.Simple;

namespace WebApp.Customizations
{
    public class PublishRelationsAction
    {
        public void Process(WorkflowPipelineArgs args)
        {
            Item dataItem = args.DataItem;

            // Find all related items
            ItemLink[] itemLinks = dataItem.Links.GetValidLinks();

            foreach (ItemLink link in itemLinks)
            {
                Item itm = link.GetTargetItem();

                // publishing related media items - the ones that were referenced by the workflow item
                // this can be extended - you can publish related aliases also
                if (itm != null && itm.Paths.IsMediaItem)
                {
                    PublishItem(itm);
                }
            }
        }

        private void PublishItem(Item item)
        {
            PublishOptions options = new PublishOptions(PublishMode.SingleItem, item.Language, DateTime.Now);
            options.RootItem = item;
            options.Deep = false;
            options.SourceDatabase = item.Database;
            // publishing to the web database
            // production scenarios may have different publishing targets
            // this can be handled by some more advanced logic,
            // for example retrieving parameterized targets from the workflow action
            options.TargetDatabase = Factory.GetDatabase("web");
            new Publisher(options).Publish();
        }
    }
}

Related reading:

The caveats:

  1. If media items are associated with another workflow, they should be in the final state.
  2. Obviously this solution works when you are using workflow. Other solutions such as handing of publish:end events does not seem to be as easy as workflow action. In this case it could be better to introduce a one step workflow with one initial state "Editing" and final "Published" with such action attached.

Thanks to Alexander Tsvirchkov for investigation and code and Kim Hornung for ideas.

Tuesday, October 16, 2007

LDAP and Sitecore user/role mapping


Sometimes you may need certain users imported from Active Directory through the LDAP module to be associated with some Sitecore-native roles such as default Sitecore 5.3 Client Roles.

In order to accomplish this, you need to customize the LDAPDomain class that is associated with the domain definitions in web.config.

Just create your own class that will inherit from Sitecore.Modules.LDAP.LDAPDomain:

public class LDAPDomain : Sitecore.Modules.LDAP.LDAPDomain
  {
     public LDAPDomain(string domainName, string databaseName)
        : base(domainName, databaseName)
     {

     }

}

Then override the Login method that will call the base implementation of the Login method and post process the AD user:

public override Sitecore.SecurityModel.DomainAccessResult Login(string userName, string password)
       {
           DomainAccessResult loginResult = base.Login(userName, password);
           if (loginResult.Success)
           {
               UserItem user = this.GetUser(userName);
               if (user["Fromldap"] == "1")
               {
                   // Optional: Get the Role that is already imported from AD
                   RoleItem techSupportRole = Sitecore.Context.Domain.GetRole("Technical Support");

                   // Optional: if the role is found and the user is a member of this role
                   if (techSupportRole != null && user.Roles.Contains(techSupportRole.ID))
                   {
                       user.BeginEdit();

                       // getting Sitecore Client Authoring Role
                       RoleItem clientAuthRole = Sitecore.Context.Domain.GetRole(ID.Parse("{DE4E5C04-F820-4406-AEB9-C76144F7D808}"));
                       // Getting Sitecore Maintaining Role
                       RoleItem clientMaintRole = Sitecore.Context.Domain.GetRole(ID.Parse("{E2036D1D-2828-42B9-8D41-1AD2F247C256}"));

                       // assigne the Sitecore Client Authoring Role to the user
                       if (clientAuthRole != null)
                       {
                           user.Roles.AddRole(clientAuthRole.ID);
                       }

                       // assigne the Sitecore Maintaining Role to the user
                       if (clientMaintRole != null)
                       {
                           user.Roles.AddRole(clientMaintRole.ID);
                       }

                       user.EndEdit();
                   }
               }
           }
           return loginResult;
       }

The code is pretty easy and self-explanatory.

Instead of hard-coding the role IDs, you can of course create a Sitecore item that will contain the role mappings, so this logic can read it and apply the rules on the fly.

Thanks to Ivan Sharamok for the idea.

Tuesday, October 09, 2007

Windows Server 2008 RC0 and Visual Studio 2008 Beta2


It is happening, it is definitely happening! Just install the fresh copy of this new generation of the server OS and highly anticipated IDE. I had to enable Aero to experience vast UI enhancement along with the core enhancements :-) Impressions: - Was able to install all the drivers from Vista, even wireless :-) - On my dual core 2.0 Ghz/2Gb laptop performance is comparable to Windows Server 2003 that is still on partition C:\ which is impressive. - It took less to install VS 2008 Pro with SQL Express 2005 than it used to take to install SP1 for VS 2005 which is even more impressive. On top of this package I had to install SQL Management Studio Express, Office 2007. Everything was installed without a single issue! The only thing that I could not install is MSDN - I can live with that and also got unhandled exception when opening the SQL Management Studio, but I was able to login anyways. As a part of the configuration, I had to re-enable Mixed authentication in SQL 2005 to have the "sa" account working and reset the password for this user. What about Sitecore? No problem at all! Just follow the official instructions for installation on Vista and you are up and running! What is the most exciting is that the installation program worked flawlessly (big thanks to Yan) and I did not have to use manual install. Looking forward to explore new features of IIS7 and Visual Studio 2008!