Showing posts with label Sitecore. Show all posts
Showing posts with label Sitecore. Show all posts

Wednesday, June 25, 2014

Reading Complex Field Values in Sitecore WFFM

Sitecore Web Forms for Marketers is a Sitecore CMS module used for creating forms in a website. It has various set of fields like simple, list, complex, pre-filled etc.

Usually to access field value in code, Value property of AdaptedControlResult class is used.
For any list or complex types of fields, the Value property normally contains extra information.

For e.g., A WFFM form has a check-box list and the values for its items are 1,2,3,4,5. User selects 1,2,3 and submits the form.
Then in the server-side code the value of this field is:

<item>1</item><item>2</item><item>3</item>

To get a simple value with out item tags then GetSitecoreStyleValue method of FieldReflectionUtil class can be used.
Example code snippet:

AdaptedResultList fields;

// Get the form field by specifying the field name
AdaptedControlResult formField = fields.GetEntryByName("fieldName"); 

// complex value with item tags
string fieldValue = formField.Value;

// simple value without item tags
fieldValue = Sitecore.Form.Core.Utility.FieldReflectionUtil.GetSitecoreStyleValue(formField.FieldID, fieldValue);


BottomLine: Use FieldReflectionUtil class to get simplified version of form field values.

Tuesday, June 24, 2014

Extension Randomly Added in Sitecore Media Item URLs

In Sitecore 6.6, MediaManager randomly adds extension while generating URL for any Sitecore Media Item. This is a bug in Sitecore. A workaround is available to fix this issue.
MediaUrlOptions mediaUrlOpts = new MediaUrlOptions();
mediaUrlOpts.IncludeExtension = false;
Response.Write(MediaManager.GetMediaUrl(item, mediaUrlOpts));

In case extension is always needed in the URL then set IncludeExtension property to true.

Tuesday, April 22, 2014

Sitecore Admin User Password Reset

Some times the admin password for Sitecore instance is lost or the user admin account is locked.
One way to reset the admin password is by executing SQL scripts.

Another easy way is by placing below C# code in an aspx page and browsing it using the sitecore instance domain:

string resetPassword = String.Empty;
string userName = string.Empty;
string newPassword = "newPassword";
bool status = false;
bool isLocked = false;

using (new Sitecore.SecurityModel.SecurityDisabler())
{
 userName = @"sitecore\admin";
 MembershipUser user = Membership.GetUser(userName, true);
 if (user != null)
 {
  resetPassword = user.ResetPassword();
                status = user.ChangePassword(resetPassword, newPassword);
                isLocked = user.IsLockedOut;
                if (isLocked)
                {
                    user.UnlockUser();
                }
 }
}

Response.Write(String.Format("Password updated {0} for user - {1}", (status ? "successfully" : "failed"), userName));

This code can be placed in an aspx file kept inside \Website\sitecore\admin\ location.
Once the aspx page is created with the above snippet, browsing that aspx page will reset the admin password to the desired password given in variable newPassword.

Sample aspx page can be found in GitHub.

Sunday, April 20, 2014

Reasons for Sitecore IIS App Pool Crash

In past few months, there were two separate instance where IIS application pool of Sitecore website was crashing intermittently. In both of these cases, stack overflow resulted in IIS application pool crash. This article lists some of the reasons for stack overflow scenarios in Sitecore:

1. Infinite control load using Presentation Inversion of Control:

The websites which were built on Sitecore instance uses Presentation Inversion of Control. In simple terms, there were some custom Sitecore sublayouts built which renders the controls added to its DataSource item.

In one of the website's home page (startItem), the content author added one such control. The data source item for that control also had the same control, mistakenly, added as part of it presentation details. Whenever a request was made for the home page, the controls were loaded infinitely which led to application pool crash.

2. Sitecore Custom Security Providers:

Whenever an item is requested, sitecore checks if the user has access rights to the item or not. To get the user details for access rights, Sitecore checks with the security providers which are configured in web.config file. In one such custom security provider, to get user details, a sitecore item was being accessed. Since this custom security provider was trying to access sitecore item, Sitecore again checks for user access and invokes GetUser() for security providers. This resulted in an infinite recursive loop and led to application pool crash. So, if you are creating any custom security providers in Sitecore, ensure that those security providers in turn do not access any sitecore item.

Saturday, June 1, 2013

Sitecore CSS/JS Media Items Minfier

As suggested by Google, minification of CSS and JS resources improves the performance of websites. Minification can save many bytes of data and speed up downloading, parsing, and execution time.

In Sitecore CMS, for JS and CSS resources present in media library, it is a good idea to keep minified versions in live environment and original uncompressed versions in development/authoring environment.

Media Items Minifier Module

I have created a media items minifier module for Sitecore which will minify any CSS/JS media item when published. Media items will be minified only in target environment, items in source environment will not be impacted. It makes use of YUICompressor for minifying CSS/JS resources.

This module is basically an event handler for Sitecore's publish:itemProcessed event which is triggered after an item is published. 

After installing this module a MediaItemsMinifier.config file is created in /Website/App_Config/Include folder. It contains below configuration:

 <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">  
  <sitecore>  
   <events timingLevel="custom">  
    <event name="publish:itemProcessed">  
     <handler type="MediaItemsMinifier.ItemProcessedEventHandler, MediaItemsMinifier" method="OnItemProcessed">  
      <databases>web</databases>  
     </handler>  
    </event>  
   </events>  
  </sitecore>  
 </configuration>  

In <databases> node list of comma separated target database names can be given in which media items should be minified.

Whenever an item is published, this module first check whether target database name is part of <databases> node or not. Then it verifies if item is published and it is CSS/JS media item.
When the published item is a CSS/JS media item, it performs following actions:
  1. Get original contents using GetMediaStream method of MediaItem.
  2. Compress the contents using YUICompressor.
  3. Edit the target media item to upload minified version.
This way media items are minified only in target environments when they are published from source environment.

To view the source code and download the Sitecore package visit Media Items Minifier at github.

Update: Media Items Minifier module is now available at Sitecore Marketplace.

Sunday, April 28, 2013

Custom Link Provider for Items outside startItem in Sitecore

In a recent website development using Sitecore, we had to keep pages outside startItem to implement the required the information architecture of the site. Below is an image depicting the page hierarchy.


Sitecore page item outside contentStartItem

The user friendly URL generated for page "Our-Range" was /sitecore/Content/site_name/Website/our-range instead of /our-range.

On troubleshooting it was found that as "Our-Range" item is out side contentStartItem (in this case, "home" item), Sitecore's default linkProvider returned full path for the item. Displaying full item path as URL is not a good practice from SEO and security point of views.

To fix this, Sitecore's out of box LinkProvider (Sitecore.Links.LinkProvider) was extended and the GetItemUrl method was overridden.


namespace Sitecore.Custom.Providers
{
/// <summary>
/// Class to generate URL for Sitecore items.
/// </summary>
public class LinkProvider : Sitecore.Links.LinkProvider
{
/// <summary>
/// Returns user friendly URL for given Sitecore item.
/// </summary>
/// <param name="item">The Sitecore item for which URL is needed.</param>
/// <param name="options">The options to be considered when generating URL</param>
/// <returns>User friendly URL for Sitecore item.</returns>
public override string GetItemUrl(Sitecore.Data.Items.Item item, Sitecore.Links.UrlOptions options)
{
// Get URL from Sitecore out of box link provider.
string originalURL = base.GetItemUrl(item, options);


// Get contentStartItem path for context site.
string contentStartItem = Sitecore.Context.Site.RootPath.ToLower();

// Replace contentStartItem path in originalURL with empty string and return the resultant string.
return originalURL.ToLower().Replace(contentStartItem, String.Empty);
}
}
}

In above code, GetItemUrl method is overridden to adjust the friendly URL for Sitecore items. First, friendly URL for required item is retrieved using default link provider. Then the contentStartItem path is replaced with empty string. Finally the resultant URL is returned.

After the code is build and deployed, below configuration changes have to be make in web.config file of Sitecore instance:

<add patch:instead="*[@name='sitecore' and @type='Sitecore.Links.LinkProvider, Sitecore.Kernel']" name="sitecore" type="Sitecore.Custom.Providers.LinkProvider, Sitecore.Custom" addAspxExtension="false" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="asNeeded" languageLocation="filePath" shortenUrls="true" useDisplayName="true"></add>

After deploying these changes, URLs for items outside startItem did not have full item path.

Full source code for above custom link provider can be found at GitHub.

Friday, April 5, 2013

Improve Sitecore Media Library Performance with IIS ARR

Recently one of our Sitecore production environment was having performance issues. On troubleshooting we found that one of the causes was media library. It was performing poorly when there was heavy load on the server. Even after configuring various media library related settings in web.config, performance was not getting improved. We were still observing CPU spikes in production environment.

Due to budget constraints, CDN option was ruled out for media library. Then we came up with a solution to have a proxy before the CD server. We found that reverse proxy can be setup with help of IIS Application Request Routing and URL Rewrite.

After setting up reverse proxy, all media library requests were forwarded to CD server for the first time and its response was cached on disk. After creation of cache, media library request were not forwarded to CD server and instead were being served from cache.

When we performed load testing on our Staging environment, there was vast improvement in performance with ARR cache. CPU Utilization reduced by almost 10x times, Requests/Sec increased by 1.5x times and Response Time reduced to half.

Till now we haven't seen any functionality issues in Sitecore websites with ARR caches. All sites were working fine as expected.

One important setting to be configured in web.config file is to set HTTP Cache-Control Header to Public for media library files. This will enable media library items to get cached at proxy sites.
<setting name="MediaResponse.Cacheability" value="public" />

There are other ways as well to improve media library performance but more on that in later posts.