Standalone Sitecore ShowConfig


Sitecore's showconfig.aspx (https://{hostname}/sitecore/admin/showconfig.aspx) page is a simple web form page that compiles all of the Sitecore configuration files into a single XML result with all patches applied. This is then spit out onto a web page, where your browser can format and display that XML. We have all used the show config to take a look at the current Sitecore configuration, and validate that things are setup as intended. Most likely, this use case occurs when we are trying to solve a problem with our site (e.g. pipeline processor isn't executing). Unfortunately the page only functions on a successful startup of the Sitecore application. Recently, I was working on adding some patches to a Sitecore installation. The particular settings I was manipulating were triggered at application startup, and due to errors, Sitecore was throwing the infamous yellow screen of death; this meant I couldn't use the show config page to try and solve my problem. My solution: make my own show config page, and locate the issues with my startup. In this blog, I will go over my implementation for a standalone show config page, which can be used to debug and correct troublesome startup configurations.

The patching options for Sitecore configurations are pretty extensive. I wanted to stay as close to Sitecore's original implementation as possible, to ensure that I got the most accurate result. Therefore, step one was to open up the showconfig.aspx page that is delivered with Sitecore, and get an idea of what it was doing. The page itself doesn't have any actual content associated with it, but the code behind inherits from Sitecore.sitecore.admin.ShowConfig; a quick search through the assemblies pointed me to Sitecore.Client.dll for the implementation.

Most of the implementation for this page is pretty straight forward. If you have access to any decompile tool (e.g. DotPeek), then you can open the assembly up and take a look. For brevity purposes, I'm just going to touch on the specific things I had to adjust in order to get the implementation functioning outside of a Sitecore environment.

To start, I created an empty MVC project; Sitecore runs on a standard MVC project, and as mentioned earlier, I wanted to stay as close to the original implementation as possible. Once the project was up and running, I added the Sitecore's custom config reader to my web.config file.

1
2
3
4
5
6
7
8
<configuration>
    <configsections>
        <section name="section" type="Sitecore.Configuration.RuleBasedConfigReader, Sitecore.Kernel">section>
    configsections>
    <sitecore configsource="App_Config\Sitecore.config">sitecore>
 
    
configuration>

I didn't add any controllers or views to my project, as they weren't necessary. Instead, I created my own ShowConfig.aspx page and code behind file. For my Page_Load event, I took out some of the extra processing.

 

    protected void Page_Load(object sender, EventArgs e)
    {
    	var ruleCollection = new NameValueCollection();
    	var empty = string.Empty;
    
    	// Read the rule configurations
    	var configurationRules = Sitecore.Context.ConfigurationRules;
    	var strArray = configurationRules?.GetRuleDefinitionNames()?.Select(name =>
    		name?.ToUpperInvariant()
    	).ToArray() ?? new string[0];
    
    	// Process the rules from the query string (e.g. http://{host}/showconfig.aspx?search=solr)
    	foreach (var allKey in this.Request.QueryString.AllKeys)
    	{
    		if (allKey == "layer")
    			empty = this.Request.QueryString[allKey];
    		else if (strArray.Contains(allKey.ToUpperInvariant()))
    			ruleCollection.Add($"{allKey}:{RuleBasedConfigReader.RuleDefineSuffix}", this.Request.QueryString[allKey]);
    	}
    
    	var config = GetXmlDocument(ruleCollection, empty);
    
    	this.Response.ContentType = "text/xml";
    	this.Response.Write(config.OuterXml);
    }

The GetXmlDocument method is where most of the good stuff happens. I used this method to create an instance of Sitecore's RulesBasedConfigReader. The primary method needed for this class, DoGetConfiguration, is internal, but this was easy enough to get around using reflection. Once we had the reference to the necessary method, I executed it to process my App_Config folder.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
private XmlDocument GetXmlDocument(NameValueCollection ruleCollection, string layers)
{
    // Get an instance of a config reader
    var reader = new RulesBasedConfigReader(GetIncludeFiles(layers.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)), ruleCollection);
 
    // Grab the DoGetConfiguration method using reflection
    var doGetConfigurationMethod = reader.GetType().GetMethod("DoGetConfiguration", BindingFlags.NonPublic | BindingFlags.Instance);
 
    // Now we can execute the method
    var configuration = (XmlDocument)doGetConfigurationMethod?.Invoke(reader, new object[] {});
 
    return configuration;
}

Everything else was copied from the decompiled implementation of the page. Once I had this running, I grabbed the contents of my troublesome Sitecore instance's App_Config folder, and copied them into the running directory of my project. Starting the application, and navigating to the ShowConfig.aspx url produced the result of a typical ShowConfig page:

Standalone ShowConfig

Implementing my own version of the show config page helped me identify the specific part of my configuration that was causing issues. The fix for the issue was relatively simple, but it is a fix I would not have identified without first knowing the problem.

The example used in this blog post has been implemented on Sitecore 9 Initial Release, a MVC application running on .NET Framework 4.6.2.

Categories: Sitecore, Web Development
Tags: CMS, Sitecore, Sitecore;

SEARCH ARTICLES