Thursday 31 January 2008

Culture 'en' is a neutral culture. It cannot be used in formatting and parsing and therefore cannot be set as the thread's current culture.

The following exception may be thrown when trying to open a log file in the Sitecore Log Viewer:

“Culture ‘en’ is a neutral culture. It cannot be used in formatting and parsing and therefore cannot be set as the thread’s current culture.”

To overcome this, open the User Manager and add a value in the RegionalIsoCode field for the user affected. For GB English, enter en-GB.

Wednesday 30 January 2008

Failed to execute the request because the ASP.NET process identity does not have read permissions to the global assembly cache

If you get “Server Application Unavailable” when trying to browse to your development web site, check the Event Log on the host machine. If it contains the message “Failed to execute the request because the ASP.NET process identity does not have read permissions to the global assembly cache”, navigate to the .NET Framework directory containing the file aspnet_regiis.exe and run the command:
aspnet_regiis -ga machinename\ASPNET
(substituting machinename as appropriate).

Ensure also that the web site is an application (create an application in the IIS home directory).

If the message is simply “Service Unavailable” and you’re using IIS 6, check the application pool associated with your web site is running.

Tuesday 29 January 2008

Type conflicts with the imported type

Partial classes were introduced in .NET 2.0 enabling you to create classes spread over several source code files. What’s not immediately clear is that you only do this with source code files. You cannot add to a partial class that’s already built in a distinct assembly. If you try to do this, you’ll get something similar to the following error:

The type 'namespace.class' in 'C:\MyFolder\Class1.cs' conflicts with the imported type 'namespace.class' in 'assemblyfilename.dll'.

Generating Custom Configuration Sections in web.config (Part 2)

My earlier post about creating custom configuration sections in web.config, referred to a custom tool that can be used to do the leg work.

If you wish to implement custom sections yourself, here’s a simple example of how. This simple example uses standard key/value attributes and data that is not strongly typed. I shall later post a more advanced example, using strongly-typed data.

First, within the element of web.config, add the following element exactly as is, replacing MySectionName with the name you want to give your section:

<configSections>
<sectionGroup name="MySectionName">
<section name="Portal"
type="System.Configuration.NameValueSectionHandler,system,
Version=1.0.3300.0,Culture=neutral,
PublicKeyToken=b77a5c561934e089,Custom=null" />
</sectionGroup>
</configSections>

This uses the built-in handler. No further development is necessary.

You can then add keys to your custom section:

<MySectionName>
<MyStuff>
<add key="fruit1" value="apples" />
<add key="fruit2" value="oranges" />
</ MyStuff >
</MySectionName>

Finally, you extract the keys as follows:


NameValueCollection settings =
ConfigurationManager.GetSection(
"MySectionName/MyStuff")
as NameValueCollection;

Monday 28 January 2008

XHTML-compliant links: There is no attribute "target"

The traditional way to open links in a new window was to use target="_blank". This is non-valid XHTML. The error on the W3 validator is “there is no attribute "target".” The editor in Sitecore 5.2 generates target="_blank". I haven’t yet tried other versions.

There’s an interesting work-around on here:

http://www.sitepoint.com/article/standards-compliant-world


In short, they attach target="_blank" using JavaScript.

It seems like a fudge just to bypass the check, but the author argues it’s perfectly valid approach. The only downside is the reliance on JavaScript.

Friday 18 January 2008

Introducing MicroScrum!

Having attended various sessions at TechEd, DDD and DotNetDevNet on Scrum, I wanted to try implementing it. Trouble was, the size of the team for my current project is small (2 or 3 developers, including me) and Scrum’s intended for larger teams. So, I took the elements of Scrum that I felt still applied and, well, applied them!

Here’s what we are now doing:

We work in sprints—the tasks making up each sprint go into TFS as work items (or rather, they will be going into TFS: haven’t got around to that bit yet!). Every morning, we have a “Scrumlet”. We use it to run quickly through the tasks listed and attach estimated remaining times. It’s also a chance to re-focus efforts for the day. I keep a burn down chart up to date for my own and team’s reference. The chart is a great way to manage time and it keeps my project manager happy. Its visible nature means that the impact of moving someone onto another project is readily apparent.

I add to each sprint a couple of recurring tasks, namely the running of unit and functional tests, plus the updating of documentation. (I think of the latter as continuous integration for documentation.)

Early indications are that using “MicroScrum” is a great way to ensure project delivery remains on track, or at least that problems are seen earlier.

Tuesday 15 January 2008

Implementing the MVP Pattern in Sitecore XSLT Extension Methods

Here’s a way of implementing the MVP pattern when creating Sitecore XSLT extension methods. Ideally, you should already have some experience of creating extension methods and be familiar with MVP.

In the example I use, a “for-each” loop is used to display a list of makes of car.

First, create the view interface, defining the property or properties you want to display in the XSLT. As we are returning an array of values, the XPathNodeIterator return type is used:

public interface ICarsView
{

    XPathNodeIterator Cars { get; set; }

}


Create an interface defining the method that will get the data or information from store:

public interface ICar
{

    XPathNodeIterator GetListOfCars();

}


In your data access layer (DAL), implement the method that gets the data:

public XPathNodeIterator GetListOfCars()

{

    var cars = from c in GetMyData()

               orderby c.Make

               select c;

 

    XDocument xdoc = new XDocument();

    XElement xmlTree = new XElement("Cars");


    foreach( var car in cars )

    {

        xmlTree.Add(new XElement("Car",

            new XAttribute("Make", car.Make)));

    }


    xdoc.Add(xmlTree);


    return xdoc.CreateNavigator().Select("/Cars/Car");

}


Create the presenter class, which will store references to the view and DAL method interfaces, and define the method(s) that will set the value of the property or properties on the view:

    public class CarsPresenter

    {

        private readonly ICarsView _view;

        private readonly ICar _icar;

 

        public CarsPresenter( ICarsView view, ICar car )

        {

            _view = view;

            _icar = car;

        }

 

        public void SetCarsProperty()

        {

            _view.Cars = _icar.GetListOfCars();

        }

    }



Create the extension method that implements the view:

public class CarsView: ICarsView
{
    public XPathNodeIterator GetListOfCars()
    {
        CarsPresenter cp = new CarsPresenter(this, new CarsDal());
        cp.SetCarsProperty ();
        return Cars;
    }
 
    #region IAgreementsView Members
 
    public XPathNodeIterator Cars
    {
        get; set;
    }
 
    #endregion
}


In the web.config file, add an extension element to the xslExtensions element that references the concrete view. Use one such element for each namespace:

<extension mode="on" type="XsltViews.CarsView, XsltViews"
           namespace=" http://example.com/xsltviews/cars " />


In your XSLT file, declare the namespace prefix by adding it to the stylesheet element and including the prefix in the exclude-result-prefixes attribute:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:sc="http://www.sitecore.net/sc"
  xmlns:dot="http://www.sitecore.net/dot"
  xmlns:view="http://example.com/xsltviews/cars"
  exclude-result-prefixes="dot sc view">


Finally, you can now call the method from your XSLT:

<xsl:for-each select="view:GetListOfCars()">
  <xsl:value-of select="@Make"/>
</xsl:for-each>

Monday 14 January 2008

Creating Simple Loops in XSLT

Here's a simple way to create a loop in XSLT. As you might expect, it uses recursion.

I have defined a template that will do the work of the loop. It checks the value of a variable called 'counter' before calling itself. This is the loop condition. Before this test, you can add whatever it is you need the loop to do. In the following example, I print the letters of the alphabet, followed by "... Hello!":

<xsl:template name="DoLoop">
<xsl:param name="counter" />
<xsl:variable name="letter"
select="substring($alphabet, $counter, 1)" />

<!--Body of loop goes here-->

<xsl:value-of select="$letter" />... Hello!
<br/>

<!--End of loop body-->

<xsl:if test="$counter &lt; 26">
<xsl:call-template name="DoLoop">
<xsl:with-param name="counter">
<xsl:value-of select="$counter+1" />
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>

The loop is then initiated by calling it with the desired starting value:

<xsl:call-template name="DoLoop">
<xsl:with-param name="counter">1</xsl:with-param>
</xsl:call-template>

For info, the alphabet variable is simply defined as:

<xsl:variable name="alphabet">
<xsl:text>ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:text>
</xsl:variable>

Thursday 3 January 2008

How to Change String Case in XSLT

Here's a simple way to convert a string to lower case in XSLT. The snippet takes an input variable inputtext and saves the lower case version to a new variable called lowercasetext.

<xsl:variable name="lowercasetext" select="translate($inputtext, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')" />

To upper case a string, simply swap the position of the two alphabet literals shown.

Wednesday 2 January 2008

A valid license cannot be granted for the type CuteEditor.Editor

If you get this error message in rich text fields of the Sitecore Content Editor, check that your bin folder includes the CuteEditor licence file (CuteEditor.Lic).