Take the community feedback survey now.

KennyG
Sep 27, 2021
  7241
(1 votes)

Need to do some troubleshooting? Go go gadget!

We all know Version 12 of Optimizely is on the way with all its .Net Core goodness, but some of us will be maintaining the current version for a while. That being the case, it helps to have access to troubleshooting data.

Here are a few dashboard gadgets I use to make sure that things have gotten properly transformed in the web.configs or that my user has the proper group memberships.

Web.Config Viewer

This one is super simple. Just grab the web.config and output it to screen. Good for making sure that the proper Web.xxx.config entries were applied.

WebConfigViewerComponentController.cs

using EPiServer.Security;
using EPiServer.Shell.ViewComposition;
using System.Linq;
using System.Web.Mvc;

namespace Website.Features.Components
{
    [IFrameComponent(Url = "webconfigviewercomponent",
    Categories = "dashboard",
    Title = "Web Config Viewer", MinHeight = 400)]
    [Authorize(Roles = "Administrators, WebAdmins, CmsAdmins")]
    public class WebConfigViewerComponentController : Controller
    {
        public ActionResult Index()
        {
            string file = "~/web.config";
            string[] str = null;
            if (System.IO.File.Exists(Server.MapPath(file)))
            {
                str = System.IO.File.ReadAllLines(Server.MapPath(file));
            }

            return View("~/Features/Components/WebConfigViewerComponent.cshtml", str.ToList());
        }
    }
}

WebConfigViewerComponentController.cshtml

@using Century.Website.Data
@using EPiServer
@using EPiServer.Framework.Web.Resources
@using EPiServer.ServiceLocation
@using System.Security.Claims

@model List<string>

@{
    Layout = null;
}

<!DOCTYPE html>

<html lang="en-us">
<head>
    <title>Web Config</title>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
</head>
<body>
        @if (Model != null && Model.Any())
        {
            if (Model.Any() && Model != null)
            {
                <pre>
                    @foreach (var line in Model)
                    {
                        @($"{line}\n") 
                    }
                </pre>
            }
        }
</body>
</html>

App Settings Viewer

Since there is configuration set on the Web App itself in DXP/Azure it sometimes helps to see what is going on. Especially in PREP and PROD where you don't have portal access.

AppSettingsComponentController.cs

using EPiServer.Security;
using EPiServer.Shell.ViewComposition;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web.Mvc;

namespace Website.Features.Components
{
    [IFrameComponent(Url = "appsettingscomponent",
    Categories = "dashboard",
    Title = "App Settings", MinHeight = 400)]
    [Authorize(Roles = "Administrators, WebAdmins, CmsAdmins")]
    public class AppSettingsComponentController : Controller
    {
        public ActionResult Index()
        {
            var settings = new Dictionary<string, string>();
               
            foreach (var key in ConfigurationManager.AppSettings.AllKeys.ToList())
            {
                settings.Add(key, ConfigurationManager.AppSettings[key]);
            }
            return View("~/Features/Components/AppSettingsComponent.cshtml", settings);
        }
    }
}

AppSettingsComponent.cshtml

This one assumes you have some entry that states what environment you are in. In our case it is "env"

@using Century.Website.Data
@using EPiServer
@using EPiServer.Framework.Web.Resources
@using EPiServer.ServiceLocation
@using System.Security.Claims

@model Dictionary<string, string>

@{
    Layout = null;
    var env = !string.IsNullOrEmpty(Model["env"]) ? Model["env"] : string.Empty ;
}

<!DOCTYPE html>

<html lang="en-us">
<head>
    <title>Security Groups and Roles</title>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <!-- Shell -->
    @Html.Raw(ClientResources.RenderResources("ShellCore"))
    <!-- LightTheme -->
    @Html.Raw(ClientResources.RenderResources("ShellCoreLightTheme"))

    <link href="/EPiServer/CMS/App_Themes/Default/Styles/system.css" type="text/css" rel="stylesheet">
    <link href="/EPiServer/CMS/App_Themes/Default/Styles/ToolButton.css" type="text/css" rel="stylesheet">

</head>
<body>
    @Html.Raw(Html.ShellInitializationScript())

    <div class="epi-contentContainer epi-padding">

        <script src="/Util/javascript/episerverscriptmanager.js" type="text/javascript"></script>
        <script src="/EPiServer/CMS/javascript/system.js" type="text/javascript"></script>
        <script src="/EPiServer/CMS/javascript/dialog.js" type="text/javascript"></script>
        <script src="/EPiServer/CMS/javascript/system.aspx" type="text/javascript"></script>

        <input type="hidden" id="doExport" name="doExport" value="False">
        <div class="epi-formArea">

        </div>


        @if (Model != null && Model.Any())
        {

            <div class="epi-contentArea epi-clear">
                <div>
                    @if (Model.Any() && Model != null)
                    {
                        <table class="epi-default epi-default-legacy"
                               cellspacing="0"
                               id="FullRegion_MainRegion_ReportView"
                               style="border-style: None; width: 100%; border-collapse: collapse;">
                            <tr>
                                <th scope="col" colspan="2">@env App Settings</th>
                            </tr>
                            @foreach (var setting in Model)
                            {
                                <tr>
                                    <td>@setting.Key</td>
                                    <td>@setting.Value</td>
                                </tr>
                            }
                        </table>
                    }
                </div>
            </div>

        }
        else
        {
            <div class="epi-floatLeft epi-marginVertical-small">No Information Found</div>
        }
    </div>
</body>
</html>

Connection Strings Component

View which connection strings are set in DXP.

ConnectionStringsComponentController.cs

using EPiServer.Shell.ViewComposition;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web.Mvc;

namespace Website.Features.Components
{
    [IFrameComponent(Url = "connectionstringscomponent",
    Categories = "dashboard",
    Title = "Connection Strings", MinHeight = 400)]
    [Authorize(Roles = "Administrators, WebAdmins, CmsAdmins")]
    public class ConnectionStringsComponentController : Controller
    {
        public ActionResult Index()
        {
            var settings = new Dictionary<string, string>();
            var conStrings = ConfigurationManager.ConnectionStrings;


            foreach (var conn in ConfigurationManager.ConnectionStrings.Cast<ConnectionStringSettings>())
            {
                settings.Add(conn.Name, conn.ConnectionString);
            }
            return View("~/Features/Components/ConnectionStringsComponent.cshtml", settings);
        }
    }
}

ConnectionStringsComponent.cshtml

@using Century.Website.Data
@using EPiServer
@using EPiServer.Framework.Web.Resources
@using EPiServer.ServiceLocation
@using System.Security.Claims

@model Dictionary<string, string>

@{
    Layout = null;
}

<!DOCTYPE html>

<html lang="en-us">
<head>
    <title>Security Groups and Roles</title>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <!-- Shell -->
    @Html.Raw(ClientResources.RenderResources("ShellCore"))
    <!-- LightTheme -->
    @Html.Raw(ClientResources.RenderResources("ShellCoreLightTheme"))

    <link href="/EPiServer/CMS/App_Themes/Default/Styles/system.css" type="text/css" rel="stylesheet">
    <link href="/EPiServer/CMS/App_Themes/Default/Styles/ToolButton.css" type="text/css" rel="stylesheet">

</head>
<body>
    @Html.Raw(Html.ShellInitializationScript())

    <div class="epi-contentContainer epi-padding">

        <script src="/Util/javascript/episerverscriptmanager.js" type="text/javascript"></script>
        <script src="/EPiServer/CMS/javascript/system.js" type="text/javascript"></script>
        <script src="/EPiServer/CMS/javascript/dialog.js" type="text/javascript"></script>
        <script src="/EPiServer/CMS/javascript/system.aspx" type="text/javascript"></script>

        <input type="hidden" id="doExport" name="doExport" value="False">
        <div class="epi-formArea">

        </div>


        @if (Model != null && Model.Any())
        {

            <div class="epi-contentArea epi-clear">
                <div>
                    @if (Model.Any() && Model != null)
                    {
                        <table class="epi-default epi-default-legacy"
                               cellspacing="0"
                               id="FullRegion_MainRegion_ReportView"
                               style="border-style: None; width: 100%; border-collapse: collapse;">
                            <tr>
                                <th scope="col" colspan="2">Connection Strings</th>
                            </tr>
                            @foreach (var setting in Model)
                            {
                                <tr>
                                    <td>@setting.Key</td>
                                    <td>@setting.Value</td>
                                </tr>
                            }
                        </table>
                    }
                </div>
            </div>

        }
        else
        {
            <div class="epi-floatLeft epi-marginVertical-small">No Information Found</div>
        }
    </div>
</body>
</html>

Security Groups Component

We use Azure Active Directory for Single Sign On.  This component shows which groups and roles are being passed in for the logged in user. In this example we are looking for groups that start with "SecGrp-Episerver"

SecurityGroupsComponentController.cs

using EPiServer.Security;
using EPiServer.Shell.ViewComposition;
using System.Linq;
using System.Security.Claims;
using System.Web.Mvc;

namespace Website.Features.Components
{
    [IFrameComponent(Url = "securitygroupscomponent",
        Categories = "dashboard",
        Title = "Security Groups and Roles", MinHeight = 400)]
    public class SecurityGroupsComponentController : Controller
    {
        public ActionResult Index()
        {
            var claims = ClaimsPrincipal.Current.Identities.First().Claims.ToList();

            return View("~/Features/Components/SecurityGroupComponent.cshtml", claims); 
        }
    }
}

SecurityGroupComponent.cshtml

@using Century.Website.Data
@using EPiServer
@using EPiServer.Framework.Web.Resources
@using EPiServer.ServiceLocation
@using System.Security.Claims

@model List<Claim>

@{
    Layout = null;

    var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();
}

<!DOCTYPE html>

<html lang="en-us">
<head>
    <title>Security Groups and Roles</title>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <!-- Shell -->
    @Html.Raw(ClientResources.RenderResources("ShellCore"))
    <!-- LightTheme -->
    @Html.Raw(ClientResources.RenderResources("ShellCoreLightTheme"))

    <link href="/EPiServer/CMS/App_Themes/Default/Styles/system.css" type="text/css" rel="stylesheet">
    <link href="/EPiServer/CMS/App_Themes/Default/Styles/ToolButton.css" type="text/css" rel="stylesheet">

</head>
<body>
    @Html.Raw(Html.ShellInitializationScript())

    <div class="epi-contentContainer epi-padding">

        <script src="/Util/javascript/episerverscriptmanager.js" type="text/javascript"></script>
        <script src="/EPiServer/CMS/javascript/system.js" type="text/javascript"></script>
        <script src="/EPiServer/CMS/javascript/dialog.js" type="text/javascript"></script>
        <script src="/EPiServer/CMS/javascript/system.aspx" type="text/javascript"></script>

        <input type="hidden" id="doExport" name="doExport" value="False">
        <div class="epi-formArea">

        </div>


        @if (Model != null && Model.Any())
        {

            var roleClaims = Model.Where(x => x.Type.Contains("role") && !x.Value.StartsWith("SecGrp-Episerver"));
            var groupClaims = Model.Where(x => x.Type.Contains("role") && x.Value.StartsWith("SecGrp-Episerver"));

            <div class="epi-contentArea epi-clear">
                <div>
                    @if (roleClaims.Any() && roleClaims != null)
                    {
                        <table class="epi-default epi-default-legacy"
                               cellspacing="0"
                               id="FullRegion_MainRegion_ReportView"
                               style="border-style: None; width: 100%; border-collapse: collapse;">
                            <tr>
                                <th scope="col">Roles</th>
                            </tr>
                            @foreach (var claim in roleClaims)
                            {
                                <tr>
                                    <td>@claim.Value</td>
                                </tr>
                            }
                        </table>
                    }
                    <br /><br />
                    @if (groupClaims.Any() && groupClaims != null)
                    {
                        <table class="epi-default epi-default-legacy"
                               cellspacing="0"
                               id="FullRegion_MainRegion_ReportView"
                               style="border-style: None; width: 100%; border-collapse: collapse;">
                            <tr>
                                <th scope="col">Groups</th>
                            </tr>
                            @foreach (var claim in groupClaims)
                            {
                                <tr>
                                    <td>@claim.Value</td>
                                </tr>
                            }
                        </table>
                    }
                    <br /><br />
                    @if (Model.Any() && Model != null)
                    {
                        <table class="epi-default epi-default-legacy"
                               cellspacing="0"
                               id="FullRegion_MainRegion_ReportView"
                               style="border-style: None; width: 100%; border-collapse: collapse;">
                            <tr>
                                <th scope="col" colspan="2">Troubleshooting Info</th>
                            </tr>
                            @foreach (var claim in Model)
                            {
                                <tr>
                                    <td>@claim.Type</td>
                                    <td>@claim.Value</td>
                                </tr>
                            }
                        </table>
                    }
                </div>
            </div>

        }
        else
        {
            <div class="epi-floatLeft epi-marginVertical-small">No Information Found</div>
        }
    </div>
</body>
</html>

I'm not sure how these will transfer to the new version but I'm sure something similar will be an option.

I hope you found some of these useful and maybe it has given you some ideas for your own. Do you do anything similar? If so let me know in the comments.

Sep 27, 2021

Comments

valdis
valdis Sep 28, 2021 02:36 PM

some security concerns just raised in my head :) but anyways - great stuff and will help definitely. might be even pulled into DeveloperTools, what do you think?

KennyG
KennyG Sep 28, 2021 02:55 PM

Valdis, that would be awesome. Yeah, I tried to keep the more dangerous viewers locked down to admin roles. 

Please login to comment.
Latest blogs
New Certification Alert: Become a Certified Optimizely CMS PaaS Administrator

If you’ve ever managed an Optimizely CMS environment, you already know it’s not just about deployments and settings. It’s about keeping everything...

Satata Satez | Nov 10, 2025

Algolia Search with Optimizely SAAS

Algolia + Optimizely SAAS (Remko Next.js) Integration Guide This guide explains how to integrate Algolia Search with your Optimizely SaaS CMS proje...

PuneetGarg | Nov 10, 2025

Optimizely CMS platform bug in ErrorsController (EPiServer.CMS.Core 12.22.9 fix)

While checking  Application Insights earlier this year, I stumbled upon a strange exception in my Optimizely site. At first, I thought it might be ...

David Drouin-Prince | Nov 9, 2025 |

Avoid Using OnStatusChanged in Optimizely CMS – It Can Impact Database Performance

Beware of Overusing OnStatusChanged in Optimizely CMS Scheduled Jobs Optimizely CMS allows you to create scheduled jobs — a powerful feature often...

David Drouin-Prince | Nov 9, 2025 |

Optimizely CMS - Learning by Doing: EP06 - Create Header, Footer, Menu & Component/View for Blocks

  Episode 6  is Live!! The latest installment of my  Learning by Doing: Build Series  on  Optimizely CMS 12  is now available on YouTube! This vide...

Ratish | Nov 4, 2025 |

Going Headless: 3 Ways to Store Custom Data in Optimizely Graph

Welcome to another installment of my  Going Headless  series. Previously, we covered: Going Headless: Making the Right Architectural Choices Going...

Michał Mitas | Nov 3, 2025