« Archives in May, 2011

Design Structure Matrix (DSM) for your content tree

A design structure matrix (or dependency structure matrix) can help you to analyze the dependencies of your system and spot potential problems. This is especially useful when analyzing code, like you can do with the .NET Reflector Add-In you can find here.

Since certain aspects of your system structure can also be derived from the Sitecore content tree, I thought it might be useful to make a DSM for that. The aspx at the end of this post can be used to analyze the dependencies in your content tree!

An example of how this can be useful:

Let’s say you have a multisite Sitecore environment that currently has 3 websites (A, B and C). Some parts of the websites are quite similar and developers have copied different items between the websites. Website B is (functionally) essentially a subsite of site A. You could say that website B ‘depends’ on website A. And actually, since website A will have a link to site B, website A also depends on website B. Website C should be completely independent.

Now, I have opened the DSM aspx. After selecting the master database, expanding all the relevant nodes and selecting the websites, I am now ready to create a DSM. After clicking the “Update DSM data” button, I can see the following:

From this matrix, I can see the following (start reading by choosing a row and then choose the cell; the numbers in the top row reference the items in the column on the left):

- Website A (or one of its descendants) has 1 link to website B (or one of its descendants).
- Website B (or one of its descendants) has 3 link to website A (or one of its descendants).
- Website C (or one of its descendants) has 1 link to website B (or one of its descendants).

That last one could be a problem! Website C should have no links to the other websites. This probably happened because I copied something from website B to website C and I forgot to change the link.

To see where the problem is exactly, I click on the table cell (coordinate: 1.3 Website C, 1.2). The information in the next image is displayed:

The menu configuration for website C references a page in website B, instead of a page in website C. After I correct this error, I click “Update DSM data” again. Now the matrix looks like this:

That’s better; Only websites A and B now have references to each other.

If I need a more detailed look, I can select anything that I think is relevant in the tree. So the aspx page could look like this:

You have to get used to reading this type of matrix, but it can be a very useful tool. This example is obviously quite simple; more complex situations may be found in the “real world”.

The tool is not exclusively for solving problems. It can also be helpful for quickly understanding how a system is setup.

Just copy the following code to an aspx file and you’re ready to use the tool:

Manage Sitecore config across environments (DTAP)

Managing different Sitecore environments can be quite cumbersome. One of the things that I think is annoying is managing the configuration. In my Web.config alone, I currently have 2910 lines of Sitecore configuration, excluding the different configuration files in App_Config! I’m sure others have found this annoying as well. Here’s a way of making things a lot easier.

Disclaimer: by no means do I claim that this is the best way of doing this. If you know a better way, then please let me know!

The problem:

The problem is not that we have a lot of configuration; that is actually a good thing! But when you have separate environments, like in a DTAP (Development, Testing, Acceptance and Production) setup, small changes to the configuration for each environment may be required. Here are a few suggestions for possible differences:

  • Different connectionstrings
  • Different dataFolder, mediaFolder, tempFolder
  • Different cache sizes
  • Different Sitecore databases for websites (in development, it can be helpful to work on the master database directly)

If you copy all the config files when deploying to a different environment, you will have to go through all of the configuration to make the environment specific changes. And if you do not copy all the config files, you will have to make all the normal changes (that are not environment specific) by hand. Chances are, you may forget something in both cases.

A solution that we have used in the past:

We have made a folder structure containing the Web.config, ConnectionStrings.config and any other config file that contains environment specific settings for each environment. It looked similar to this:
> Web.config (development version can be in the original location)
> App_Config
>> ConnectionStrings.config
>> Web.config
>> App_Config
>>> ConnectionStrings.config

This appears to be better, because you know exactly what you need to include in your deployment. But with this approach, you rely on all the developers for keeping everything consistent; if someone makes a change to the DEV version of a config file and forgets to make the same changes for the other environments, the whole thing breaks.

Moreover, if you want to check the consistency between the different files, you will have to wade through these huge config files. A good diff tool like WinMerge can only go so far in helping you with this.

A better solution:

I really would like to have only the differences between the environments in separate files. So the file structure as mentioned before is useful only if:

  • Only the Web.config file is used. No other config files please!
  • The Web.config needs to be as small as possible, containing only the environment specific Sitecore settings.

Luckily, putting all the Sitecore config in a separate file is quite easy. I made a new config file under App_Config called Sitecore.config and I copied the entire <sitecore /> section into it. Then I made the Web.config point to it, like this:

That cleans up the Web.config nicely! Why not externalize everything in the Web.config? Well, because the other configuration can be implemented differently (it is not specific to Sitecore) and may rely on the configuration being specified in the Web.config. Furthermore, the Web.config may be changed by IIS Manager. Be aware of this!

Environment specific settings:

But this still does not solve our problem, because now we would need different versions of Sitecore.config for each environment. This would give us the same problems.

Again, Sitecore has a nice built in solution for this problem. The differences between the environments will mostly be references to file paths, urls or arbitrary strings. So all we really need in most cases is a simple text replace. Sitecore uses the <sc.variable />  element for this.

So let’s move some variables that were copied to the Sitecore.config back to the Web.config first.

Now we have a nice base to work from.

The ConnectionStrings.config:

The connection strings are not in the <sitecore /> section. So we need a way to include them in the Web.config. Turns out, this is pretty easy. However, I must warn you here: I did see something that worried me with .NET Reflector in ConfigModifier.dll, so I’m not sure that this solution will never break. It appears to read the connection strings directly from the App_Config/ConnectionStrings.config path. I may be mistaken, and I’ve had no problems with it so far. But if you want to be sure, then skip this step for now.

Change the connectionStrings section in your Web.config file, like this:

Don’t forget to remove the original ConnectionStrings.config file to avoid confusion.

Specifying differences:

From now on, if you want to make something environment specific, you do the following:

  1. Replace the string in Sitecore.Config with a meaningful variable, for example
  2. Then add a <sc.variable /> element to the Web.config for each environment (or only do it for DEV and use a diff tool before the deployment to see what you need to change)

Here is a simple example of what your <sitecore /> section may look like for one environment in particular:

Checking configuration:

So there you have it. An easier way of managing configuration across multiple environments. This way, you can always just Copy the App_Config folder and quickly identify differences between environments by comparing the cleaned up Web.config files.

Finally, I’d like to point out an easy way to check the current configuration of a Sitecore website. This allows you to see if your configuration changes worked out correctly. Go to this location on your site: /sitecore/admin/ShowConfig.aspx.

Better FieldRenderer usage with CDM

We’ve been using CompiledDomainModel for several projects now. And we keep inventing new ways to make things even better.

Yesterday I was brainstorming with some colleagues about a better way of using the Sitecore FieldRenderer in combination with CDM. I found a very neat new way of doing this. But I’d like to share some of the different options, so that you can choose the best one for you.

Traditional FieldRenderer without CDM:

  • Simple implementation
  • Spelling errors result in not displaying anything instead of an error
  • Not wrapped, so no custom functionality can be placed on the item

Use CDM without FieldRenderer:

  • Easy implementation
  • Typed access
  • The rendering pipeline is not used, so the page editor will not make this output editable

Traditional FieldRenderer with CDM (currently the most used with CDM):

  • A bit of a pain to unwrap the Sitecore item every time
  • Spelling errors result in compilation errors, which is great!
  • The FieldName can refer to a field from an entirely different type (though this is not a very common mistake)

Custom FieldRenderer with CDM:

  • The same as the previous one, but without the need to unwrap the Sitecore item every time
  • You need to use a non-standard control

Custom FieldRenderer with CDM and lambda expression:

  • The best possible type-safety
  • Only usable in .NET 4
  • You need to use a non-standard control

The last one is the nicest one in my opinion. You can use it as if you are not using a field renderer at all, and still get all the benefits of a fieldrenderer (use of the rendering pipeline and editable in the page editor).

It works by using the expression tree of the passed-in lambda expression and reflection to determine the name of the field. It shouldn’t be too hard to create similar controls for sc:Link and sc:Image. Here’s the code:

Good luck!