Thursday, October 30, 2014

Desktop application to find all 404 links on a web site

When developing a new web site or even re-creating an existing one, it is almost guaranteed that there will be a number of broken links (both internal and external) across the web site. There are a number of on line tools (including Google Webmaster Tools) that can be of help on production web sites. However when it comes to web sites still in production, those which aren't available externally or perhaps web sites that utilize the hosts file, a desktop application would be of help.

Xenu's Link Sleuth is a great desktop tool for finding broken links, and has been around for a number of years. The basic functionality is that it checks a web site for any broken links (across all media types, pages and even scripts/resources). It then gives a report that sorts the broken links by broken link or by page (that has broken links). Another great feature is the ability to disable the checking of external links.

Xenu's Link Sleuth Running
I have found this tool particularity helpful when migrating existing web site, as there are often links in the content to previous URL structures. It's also handy for checking links on internal intranets.

Sitecore MVC disable web edit of fields output on page

When you output a field to a page, in the case of a title field going into the head as the page title for instance. When in page editor more, that filed will appear as editable - and in the case of meta tags mess up the look of the page editor and put code as the page title.

You can disable web editing on a case by case basis for fields with the following code:
@Html.Sitecore().Field("Field Name", new { DisableWebEdit = true })

Sitecore get the URL of an image stored in the media library

When a template uses the image field, any images the user references (and uploads) go into the Sitecore media library. This can of course be rendered using the sitecore control, however for more custom implementations and MVC projects, the image URL itself is enough. The following method takes in an object of type ImageField and outputs a string with the URL to this image.
/// <summary>
/// get image url from sitecore imagefield
/// </summary>
/// <param name="field">imagefield</param>
/// <returns>image url</returns>
public static string GetImageURL(ImageField field)
    string imageURL = string.Empty;
    if (field != null && field.MediaItem != null)
        Sitecore.Data.Items.MediaItem image = new Sitecore.Data.Items.MediaItem(field.MediaItem);
        imageURL = Sitecore.Resources.Media.MediaManager.GetMediaUrl(image);
    return imageURL;
If the image is not rendering and your site is set-up to replace any spaces in URLs with dashes, then please see Sitecore media (images) not rendering.

Sitecore get URL for LinkField

A Sitecore template field of General Link type, can link to various items of various types (internal, external, media items and so on). Because each type would be rendered differently, when accessing these links in code, the different types need to be taken into account. The following method (found online) would take in a LinkField and output the URL as a string.

A LinkField comes from accesing a Sitecore item's template field liek follows: LinkField link = item.Fields["Field Name"]; This object can then be passed into the following method to get the correct URL:
/// <summary>
/// Get the URL for a given sitecore linkfield
/// </summary>
/// <param name="lf">sitecore linkfield</param>
/// <returns>web URL</returns>
public static string GetLinkFieldURL(LinkField lf)
    switch (lf.LinkType.ToLower())
        case "internal":
            // Use LinkMananger for internal links, if link is not empty
            return lf.TargetItem != null ? Sitecore.Links.LinkManager.GetItemUrl(lf.TargetItem) : string.Empty;
        case "media":
            // Use MediaManager for media links, if link is not empty
            return lf.TargetItem != null ? Sitecore.Resources.Media.MediaManager.GetMediaUrl(lf.TargetItem) : string.Empty;
        case "external":
            // Just return external links
            return lf.Url;
        case "anchor":
            // Prefix anchor link with # if link if not empty
            return !string.IsNullOrEmpty(lf.Anchor) ? "#" + lf.Anchor : string.Empty;
        case "mailto":
            // Just return mailto link
            return lf.Url;
        case "javascript":
            // Just return javascript
            return lf.Url;
            // Just please the compiler, this
            // condition will never be met
            return lf.Url;

Basic Search Index and Search Code in Sitecore 7.5

Setting up search in Sitecore can be a learning curve, especially when the configurations change from version to version (such as 6.xx - 7.5). The following is a basic implementation which I used to set-up lucene search on a Sitecore implementation with two main content (page) types: content pages and blog posts.

Setting up the index

The first step is to create a custom search index, this is created in root/Website/App_Config/Include -  an example configuration file is available in there called Sitecore.ContentSearch.Lucene.Indexes.Sharded.Core.config.example. Using this example I modified it to the following (and saved it in the same location as search.config):

<configuration xmlns:patch="">
      <configuration type="Sitecore.ContentSearch.ContentSearchConfiguration, Sitecore.ContentSearch">
        <indexes hint="list:AddIndex">
          <!-- Change this to Sitecore.ContentSearch.LuceneProvider.SwitchOnRebuildLuceneIndex, Sitecore.ContentSearch.LuceneProvider if you would like indexes to be
               built in a temporary directory i.e. while rebuilding is happening, your old indexes work like normal until the rebuild is finished. -->
          <index id="content_index" type="Sitecore.ContentSearch.LuceneProvider.LuceneIndex, Sitecore.ContentSearch.LuceneProvider">
            <param desc="name">$(id)</param>
            <param desc="folder">$(id)</param>
            <!-- This initializes index property store. Id has to be set to the index id -->
            <param desc="propertyStore" ref="contentSearch/indexConfigurations/databasePropertyStore" param1="$(id)" />
            <configuration ref="contentSearch/indexConfigurations/defaultLuceneIndexConfiguration">
              <include hint="list:IncludeTemplate">
            <strategies hint="list:AddStrategy">
              <!-- NOTE: order of these is controls the execution order -->
              <strategy ref="contentSearch/indexConfigurations/indexUpdateStrategies/onPublishEndAsync" />
            <locations hint="list:AddCrawler">
              <crawler type="Sitecore.ContentSearch.SitecoreItemCrawler, Sitecore.ContentSearch">

In this example I have named the index content_index and set it to index the web database. It indexes items under the main content item ("/sitecore/content") and will only include the templates declared. All fields are also set to be indexed as well, however you could modify the file to meet any template/field indexing strategies you may have - multiple indexes could also be used for larger implementations with advanced information architecture. The index has also been set to update on publish and async.

Once saving the index xml, I went to the sitecore desktop and loaded the index manager (control panel > indexing > indexing manager). Here the index name was selected and the rebuild button clicked to build the index. If there are any errors in the index's XML, this page will show the stack trace. Once built the index is now accesible in code to complete actual searches.

Making a search

My templates all included fields called Heading and Content, these two fields would be what needed to be actually searched - as they would return the most relevant results. To allow linq to access these fields in the sitecore search I needed to Inherit the SearchResultItem object and add these fields in, this is achieved by using IndexField:
public class MyResultItem : SearchResultItem
    public string PageHeading { get; set; }

    public string PageContent { get; set; }
Then the actual search can be made with the following code:
var searchResults = new List<SearchResult>();
string searchTerm = Request.QueryString["term"];
var index = ContentSearchManager.GetIndex("content_index");

using (var context = index.CreateSearchContext())
    var results = context.GetQueryable<MyResultItem>().Where(resultItem => resultItem.PageHeading.Like(searchTerm) || resultItem.PageContent.Contains(searchTerm)).GetResults();

    foreach (var result in results)
        var searchResult = new SearchResult();
        var item = result.Document.GetItem();

        searchResult.Title = item.Fields["Heading"].ToString();
        string content = Utilities.Utility.HtmlRemoval.StripTags(item.Fields["Content"].ToString());
        searchResult.Summary = Utilities.Utility.TruncateString(content, 300);

        searchResult.Url = Sitecore.Links.LinkManager.GetItemUrl(item);

return View(searchResults);
Linq is returning any results from the index where the title is like the search term and the content contains the search term - remember this is very simple search and a search term of "cat" would match "concatenate". The results are then put into a custom object which can be rendered on the front end.

Monday, October 27, 2014

Sitecore media (images) not rendering

In Sitecore 7.5 I have come across an issue where some images in the media library are not rendering. This is occurring with the image URL given by Sitecore.Resources.Media.MediaManager.GetMediaUrl(MediaItem) and that URL will not load. After some investigation I found that in the sitecore web.config I had used the encodeNameReplacements section to rewrite all spaces as hyphens in URLs. That means that any media images with hyphens in the file name will not load because sitecore is then looking up that media with spaces instead of hyphens (and the image is then not found).

The solution is this case was to not use any hyphens in media file names.

Friday, October 24, 2014

Sitecore MVC output rich text field as HTML

One problem I came across when outputting Sitecore template fields (of rich text aka HTML) was that the HTML tags would be encoded and displayed on the page. To fix this, placing Html.Raw around the field value, would then output it correctly in HTML.
@Html.Raw(RenderingContext.Current.Rendering.Item.Fields["HTML Content"])
The example above outputs the 'HTML Content' Rich Text field directly as HTML. This field is a member of the content template which was set as the associated content (data source) for the rendering.

Thursday, October 23, 2014

Sorting a list of custom object in C#

Sorting a list of custom tyupe is not as simple as sorting a list of integers and strings for example. The type needs to be made IComparable and a CompareTo method needs to be added to allow the default .Sort method to work correctly.
var menuItems = new List<MenuItem>();

// add items

public class MenuItem : IComparable<MenuItem>
    public int MenuID { get; set; }
    public int ParentID { get; set; }
    public string Title { get; set; }
    public string URL { get; set; }
    public int SortOrder { get; set; }

    public int CompareTo(MenuItem other)
        return this.SortOrder.CompareTo(other.SortOrder);
The example above shows the MenuType class being made IComparable with itself and the CompareTo method is comparing based on the sort order. In this example the list of MenuItems will be sorted by that SortOrder field.

Wednesday, October 22, 2014

Using perfmon to troubleshoot performance in IIS

When an ASP.NET web site starts having performance issues, in general or when significant load is on the web site (in terms on concurrent users) it can be difficult to narrow down the root cause(s). It often takes several tools to get to the bottom of the issue, and one of the first I tend to use is the Performance Monitor built into Windows aka perfmon.exe

This utility allows you to monitor a very wide variety of system resources: at the basic level such as CPU, memory, network, disk and so on, along with application specific such as IIS, ASP, .NET and even .NET CLR Thread Pool. There are many other variables that can be monitored, too many to list here.

Perfmon Main screen showing live data (processor and memory)
By right clicking on the graph, new counters to monitor can be added by clicking "add counters". In terms of looking at performance problems in IIS, I find the following counters helpful.

  • .NET CLR LocksAndThreads - Useful to see how busy the threads are that are actually processing the code. 

  • Memory, PhysicalDisk, Processor and Network - all provide useful counters for general debugging. For instance, if processor is experiencing high usage and there is memory free, caching may be of use.
  • ASP.NET v 4.0.xxxxx - is helpful to view counters on the requests, session state and worker processes.

Friday, October 17, 2014

Adding MaxPoolSize to a connection string

Max Pool Size is the maximum number of allowed connections for a given connection string. It appears as MaxPoolSize programatically however when setting it in a connection string it needs to have spacing between the words:
string srConnectionString = "server=localhost;database=MyDB;uid=sa;pwd=pass;Max Pool Size=200;";

Monday, October 13, 2014

Increasing IIS performance using a Web Garden

A web farm is where you have multiple servers serving the web site and these servers usually sit behind a load balancer. A Web Garden (introduced in IIS 6), is the concept of a single application pool having multiple worker processes.

In general web gardens are not recommended because they require overhead to operate (each worker process will consume a base level of RAM/CPU) and do not share resources. For example caching and session states are not shared between worker processes in web farms, so there is some duplication of work from that aspect.

However in cases where you have long running processes, that lead to queuing, there may be some performance benefits to using a web garden. As more threads are made available to process these requests, which leads to quicker processing overall.

You can setup web garden at the application pool level in IIS Manager. However before enabling in a production environment I recommend extensive testing to ensure there are no negative impacts to end users (application state/session) and that you don't overload the server (too many worker processes when little CPU/RAM is available).

Web Gardens are not a popular solution due to their overhead, and some people look at them as a band aid to poorly written code. Perhaps that is the case for the vast majority of web applications, yet there are always cases where the positives outweigh the negatives and a Web Garden leads to increased IIS performance.

Friday, October 3, 2014

Sitecore replace spaces in URLs with dashes

Out of the box, Sitecore will display spaces in URLs which can look messy and potentially have negative SEO consequences. However it is possible to replace all of a given character or string in a URL for another. This can be used in this case to replace any occurrence of a space with a dash.

Simply open the web.config file for your Sitecore website and locate the "encodeNameReplacements" section. Here you will see all existing string replacements, and can add the following line:
<replace mode="on" find=" " replaceWith="-"/>
 In this section you could also replace underscores with dashes or potentially entire words with others.