Pages

11 December, 2013

Install Sitecore 6.6 in Windows 8

Sitecore 6.6 is officially not supported for Windows 8. As per SDN, Sitecore supports Windows 8 with Sitecore CMS 7.0 and forward.

Here is another way to install the Sitecore 6.6 in Windows 8 instance.

There are two options to install Sitecore in Windows machine. 
  • EXE installation checks the IIS version and if it is IIS8 (windows 8), it throws error saying IIS is not supported. 
  • ZIP with files and databases is another way to install Sitecore in Windows machine. The later one helps to install the Sitecore when IIS is not supported.

CMS Installation Guide explains the steps to do to complete the installation from ZIP file.

Simple steps:
  • Extract the .zip archive in a folder
  • Set permission for ‘/Website’ folder with Read access. User: IUSR
  • Set permission for ‘/Website’ and ‘/Data’ folder with Modify access. User: Network Service.
  • Create an Application pool with .net framework 4.0 (or 4.5), Identity: NetworkService.
  • Create a website with root folder to website.
  • Add a host (C:\Windows\System32\Drivers\etc\hosts) entry for the local access and browse the site.

Before that, asp.net should be registered in IIS. Unlike IIS7, asp.net should be registered in "Turn Windows Features On or Off" in Programs and Features of Control Panel. You can select the asp.net in the list and click Ok to register it in IIS8.



After the setup, you can work on Sitecore 6.6 in Windows 8. 

05 December, 2013

Sitecore 6.5 vs. Sitecore 6.6: StripLanguage Pipeline Changes

StripLanguage pipeline removes the language in the requested URL. 

This is based on the LinkManager property. LinkManager.LanguageEmbedding should not be "Never".

We had a requirement to configure a site with Virtual folder. Virtual folder was ‘fr’ which is the short form of Language French. 
So the URL of the website will be http://website/fr/.

In Sitecore 6.5, LanguageEmbedding was set to Never and site was browsed with virtual folder (/fr) without any issues.

In Sitecore 6.6, the same concept was not working. Somehow this language was removed even before ItemResolver. We checked the source code and the logic based on LinkManager has been removed. 


SDN Release notes: Logic has been removed as part of 6.6. upgrage.

We raised a ticket with Sitecore and waiting for any workaround to have the same functionality. #400317

Update: Sitecore has registered this as a bug for Sitecore 6.6 + version and they will inform us as soon as it is fixed. 

Update: Issue has been fixed in Sitecore CMS 6.6.0 rev. 131211 (6.6.0 Update-7).


05 November, 2013

Sitecore Analytics: DMS 2.0: Persistent Cookies

Sitecore Analytics provides most accurate data as it works on server side. It has lot of tracking variables which can used for analysis.
As part of Sitecore Analytics, certain cookies are set in the web client.

SC_ANALYTICS_GLOBAL_COOKIE
SC_ANALYTICS_SESSION_COOKIE

SC_ANALYTICS_GLOBAL_COOKIE: To identify repeat visits from a single user, Sitecore sends a persistent session cookie to the web client. The name of the persistent session cookie is SC_ANALYTICS_GLOBAL_COOKIE. The persistent session cookie expires 10 years after the last page requested from the solution by the web client.

SC_ANALYTICS_SESSION_COOKIE: To identify a sequence of HTTP requests from a single user, Sitecore sends an Engagement Analytics session cookie to the web client. The name of the session cookie is SC_ANALYTICS_SESSION_COOKIE. One of key feature of Sitecore Analytics Session Cookie is though ASP.NET expires (normally due the sessionState configuration) and creates a new session in the web page, Analytics session will not expire and will not create a new visit. 

AFAIK, this expiration time cannot be changed.

In Sitecore.Analytics.dll (DMS 2.0), the below code snippets add cookies to the client. Expiration time for Global session is for 10 years. 

HttpCookie result = (current == null) ? null : current.Response.Cookies["SC_ANALYTICS_GLOBAL_COOKIE"];
if (result == null)
{
       result = new HttpCookie("SC_ANALYTICS_GLOBAL_COOKIE");
this.AddCookie(result);
}
result.Value = this.VisitorId.ToString("N");
result.Path = "/";
result.Expires = this.IsInvalid ? DateTime.UtcNow.AddDays(-1.0) : DateTime.UtcNow.AddYears(10);

In the client, 

Set-Cookie: SC_ANALYTICS_GLOBAL_COOKIE=f80224a049a94a23a6a66c5c81639e13; expires=Mon, 01-Nov-2023 20:02:52 GMT; path=/; HttpOnly
Set-Cookie: SC_ANALYTICS_SESSION_COOKIE=BEAC5C6ADBE44D9E84056B4A8C019C46|1|3i11wfogrb2aqp1h2oj5cpwr; path=/; HttpOnly

04 November, 2013

Sitecore: Default Pages showing the home page

Default pages in Sitecore renders home page of the site.


Though there is no Sitecore item with name default, the above links still render the 
StartPath. Ideally this should redirect to 404 error page.

Sitecore DefaultResolver Pipeline checks for this default document and if the request is with the default document, then it set the current context item as the Site StartPath item and we get the StartPath for all the above URLs.

Sitecore.Pipelines.HttpRequest.DefaultResolver

SiteContext site = Context.Site;
if ((((Context.Item == null) && (Context.Database != null)) && ((site != null) && (site.StartPath.Length != 0))) && ((args.LocalPath.Length == 0) || (args.LocalPath == "/default")))
{
    Item item = args.GetItem(site.StartPath);
    if (item != null)
    {
        Tracer.Info("Using default item \"" + site.StartPath + "\" from site definition.");
        Context.Item = item;
    }
    else if (!args.PermissionDenied)
    {
        Tracer.Error("Default item was not found: " + site.StartPath, "Database: \"" + Context.Database.Name + "\"");
    }
}

To avoid this, create a custom DefaultResolver pipeline and remove the condition for the default document.
if ((((Context.Item == null) && (Context.Database != null)) && ((site != null) && (site.StartPath.Length != 0))) && ((args.LocalPath.Length == 0)

This will throw 404 error for all the default URLs.

30 October, 2013

.Net: Sending email with AlternateView, LinkedResources: System.Net.Mail

Recently we faced an issue in receiving mails from same (sender) domain email account but using different SMTP server. Mail body has few resources like GIF, JPEG and they are loaded with AlternateView (System.Net.Mail.MailAddress.AlternateViews) parameter with linked resources. 

Ex: sender@example.com sends mail to recevier@example.com using a different SMTP server (ex: mailserver.com) i.e. not using example.com (SMTP) domain.
Result of this scenario: Receiver did not receive any email. 

In mail body, resources can be loaded with the below options.

The mail could be blocked due to Exchange Intelligent Message Filter as in Microsoft Exchange server. Also to note that emails to other providers like GMAIL, YAHOO were successful.

When we remove all the resources in the email body, email reached the destination mail boxes but without any resources. Initially, to get the resource image, the below line was used.

LinkedResource image = new LinkedResource(imageResource) { ContentId = contentId };
view.LinkedResources.Add(image);
message.AlternateViews.Add(view);

Solution:
We did a small tweak to add proper content type for the resource which apparently resolved the issue. 

LinkedResource image = new LinkedResource(imageResource, MediaTypeNames.Image.Gif) { ContentId = contentId };
view.LinkedResources.Add(image);
message.AlternateViews.Add(view);

By this way, we are explicitly defining the content type of the resource. Of-course, we can simply disable the filter in the exchange server to receive the email but amending the resources in the mail body with proper content type has been skipped by the exchange filters. 

13 October, 2013

Smart Tools-1: Add Version and Copy Content

Recently I published a Sitecore tool (idea was old but did not get time to work on itJ) to add a version and copy the field content from the source language to the selected destination language(s).

This tool does the following tasks. 
  • It adds a new version to the selected destination language(s) version.
  • It copies the content from the source language (context item) to all selected destination language(s).
  • It has the option of including the child items as well.

Installation:

There is a package which you can download from the Sitecore marketplace. You can use Sitecore inbuilt installation wizard to install the package. The package includes an assembly, XML control and a config file.

How to use:
  • Once installed, you will have a menu item in the content tree. 


  • On selecting this menu, a window will open with all the available options. Source language is from the context language. If the source language is different from the default language, please change it and select the menu. 


  • An alert window will show you the message on the completion of the process. 


That's it

Smart Tools-2 will be published soon. ;)

Update: (1/13/2015)

  • Version 2.0 has been released in Marketplace. 
  • It supports Sitecore 7.0+ and SXP 8.
  • In SXP 8 , you  may need to disable the analytics and install the package.

Update: (7/27/2016)


  • Version 3.0 has been released in Marketplace. You can download it here
  • It supports Sitecore 8.1 with shared layout. 


08 October, 2013

Tools: Recycle .NET Application Pool Remotely

Recently I created an application to recycle the .net Application pool without logging into the server. It is a .net website with a dropdown showing the list of servers. On selecting a server, user can populate the all the application pools available in that server and user can recycle the application pool.


Page with dropdown and buttons.


List of application pools and a button to recycle it. 



  • The server list can be added in the configuration file.
  • Status Check will provide you the status of the application pool.
  • This .Net application should run with an account which has admin access to all the servers.
  • SMTP can be configured in the web.config.
  • After each recycle, this application will send a mail to the list of configured email ids.
  • This application logs the activity in the logs folder.


You can download the application here.


06 October, 2013

Sitecore: Image Resizer Pipeline (ResizeProcessor) Pipeline

Sitecore has a feature in processing high resolution images while rendering in the website.

Let’s say, content authors wants to use an image as Icon, Thumbnail and full scale in the website. Normally, they will upload three images in icon sized, thumbnail sized and full scale images. They will have different name to differentiate the sizes. They can use (<img src="/url/image.png" height="100" width="100") image tag with height and width but it will render with high resolution image size even for thumbnail. But Sitecore has an option of resizing the image at runtime. 

There is a pipeline in the <getMediaStream>.

<processor type="Sitecore.Resources.Media.ResizeProcessor, Sitecore.Kernel" />

This pipeline has the following advantages.
  • Depending upon the width and the height in the media url, this will resize the image and render it.  /~/media/image.JPG?h=300&w=400
  • While resizing the image, it will reduce the size of the image as well.
  • Authors can use same name for Icon, Thumbnail and Full Scale. 

Example:

High Resolution Image Size: 4.70 MB (4,938,293 bytes)

Without processor (Size – 4.7 MB): http://sitecore1/~/media/flower.JPG?h=300&w=400


With processor (Size – 55 KB): http://sitecore1/~/media/flower.JPG?h=300&w=400


Of course, there will be a performance impact for resizing at runtime. To avoid the impact, the site can be configured for ARRCache which will reduce the load on the subsequent request.


04 October, 2013

Sitecore: Ideal way to execute a long running job

One of our requirement was to execute a long running job in Sitecore Content Tree. In many cases, we end up in Timed out error. Obviously we can increase request timed out configuration. But Sitecore has a very good way of executing such long running task in a ProgressBox.

ProgressBox.Execute(JobName, JobTitle, ProgressBoxMethod, Params);

//Sitecore.Shell.Applications.Dialogs.ProgressBoxes
ProgressBox.Execute("Job Name", "Job Title ", new ProgressBoxMethod(ExecuteOperation), item);

This line of code will start progress box and the functionality will be executed in the
ProgressBoxMethod.

        protected void ExecuteOperation(params object[] parameters)
        {
            //Do the operations
           
            //Logging for the job
            Sitecore.Context.Job.Status.Messages.Add("Logs for the job: JobName");
           
            //Is the job done?
            if (Sitecore.Context.Job.IsDone)
            {
                //On completing the job
            }           
        }

By using the progress box, the long running tasks are executed successfully without getting any timed out errors. This has other methods to handle the queuing asynchronously.




18 August, 2013

Sitecore: Scheduler Job in Production server with SwitchMasterToWeb.config

One of our requirement is to schedule Sitecore job in Production environment. Most of the production environments will have SwitchMasterToWeb.config configuration to remove any master database traces in the configuration.

      <agent type="Sitecore.Tasks.DatabaseAgent" method="Run" interval="00:10:00">
        <param desc="database">master</param>
        <param desc="schedule root">/sitecore/system/tasks/schedules</param>
        <LogActivity>true</LogActivity>
      </agent>

We changed this database configuration to “web” but still the job was not executed on the scheduled time.

To investigate further we used the Sitecore admin configuration page /Sitecore/admin/showconfig.aspx. Surprisingly these agent were missing in the output. We analyzed SwitchMasterToWeb configuration and commented the patch configuration to delete these agents. Agent is there in the admin configuration page and job is running on scheduled time.

In SwitchMasterToWeb.config:

      <!--<agent type="Sitecore.Tasks.DatabaseAgent">
         <patch:delete />
      </agent>
      <agent type="Sitecore.Tasks.DatabaseAgent">
         <patch:delete />
      </agent>-->

07 August, 2013

Sitecore: RunAs Different User for Admins

If you are working as a supporting partner for a Sitecore website, you may need to provide access to various content authors. In most of cases, content authors used to say “This item is not accessible”, “my account is having issues with accessing WFFM” etc… To support them and resolve the issue, you may need to request the user whether you can reset their account to check the issue. Once the issue is fixed, you need to ask them change their password.

RunAs module will help the admins to run the Sitecore Backend as like other user i.e. Run the content tree as a different user without their password. Seems to be a security violation!!! There is an option of sending alerts to the configured mail address and also to the defective account user email.

You can download the module here. Download the zip file as it is and install it using Installation Wizard.

Once the module is installed in the Sitecore, you can browse the RunAs page as below.


Following validations/alerts are in place:
  • Requestor should be a Sitecore admin user or should be part of “Sitecore RunAs” role.
  • Requestor account will be validated with their password.
  • Once logged in, a mail will be sent to the configured mail addresses and it can be sent to the impersonated user as well.

Login screen for the Run as different user. I used the same Sitecore login UI.



Requestor      : Admin or a user in “Sitecore RunAs” Role
Password       : Requestor Password
Run As           : User to be impersonated (use domain as well ex: Sitecore\user1)

Configurations: /App_Config/Include/Sitecore.SharedSource.RunAs.config
RunAsFromAddress                – From address used for sending mails
RunAsAdminEmailAddresses   – To addresses for sending mails

Sample Mail:
Run As - Audit Log

8/7/2013 8:01:07 PM

Run As
richard
Requested By
nehemiah
Requested Url
IP Address
1.1.1.1
Machine Name

blockquote { margin: 0; } blockquote p { padding: 15px; background: #eee; border-radius: 5px; } blockquote p::before { content: '\201C'; } blockquote p::after { content: '\201D'; }