<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><language>en</language><title>Blog posts by Ollie Philpott</title> <link>https://world.optimizely.com/blogs/ollie-philpott/</link><description></description><ttl>60</ttl><generator>Optimizely World</generator><item> <title>A property viewer plugin for multilingual sites</title>            <link>https://world.optimizely.com/blogs/ollie-philpott/dates/2019/4/a-property-viewer-plugin-for-multilingual-sites/</link>            <description>&lt;p&gt;A challenge I have found when working on large multilingual Episerver builds is that there are often times where you want to review the value of a property across all languages - for example when debugging an issue on the site or comparing how a togglable feature is configured for different languages.&lt;/p&gt;
&lt;p&gt;Doing this using the Epi CMS UI can be a slightly laborious task &amp;ndash; load the page in the CMS, select a language, navigate to correct tab, find the property, rinse and repeat for each language. This approach works fine when reviewing a few languages but becomes unworkable when managing as many as 35 languages, as we do for some clients at &lt;a href=&quot;https://www.zonedigital.com&quot;&gt;Zone&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To provide a speedier approach, I created a custom admin plugin that allows you to compare the values of a property across on languages on a single screen.&lt;/p&gt;
&lt;p&gt;It works by navigating to a page using the content tree, and then selecting the property you want to view:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/7ygWvQt.gif&quot; width=&quot;1099&quot; alt=&quot;&quot; height=&quot;824&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin is built using the Episerver &lt;strong&gt;GuiPlugin &lt;/strong&gt;attribute with an &lt;strong&gt;Authorize &lt;/strong&gt;attribute to ensure that it is only accessible to admins&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[GuiPlugIn(
    DisplayName = &quot;Property Viewer&quot;,
    Area = PlugInArea.AdminMenu,
    Url = &quot;~/plugins/propertyviewer&quot;)]
[Authorize(Roles = &quot;Administrators,WebAdmins&quot;)]
public class PropertyViewerController : Controller
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and a custom route to allow MVC actions to be called in the standard way.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[InitializableModule]
public class CustomRouteInitialization : IInitializableModule
{
    public void Initialize(InitializationEngine context)
    {
        RouteTable.Routes.MapRoute(
            null,
            &quot;plugins/propertyviewer/{action}&quot;,
            new { controller = &quot;PropertyViewer&quot;, action = &quot;Index&quot; });
    }

    public void Uninitialize(InitializationEngine context)
    {
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Displaying a content tree&lt;/h2&gt;
&lt;p&gt;Although Episerver has a Web Forms component available (&lt;strong&gt;PageTree&lt;/strong&gt;) to render the site content tree, there is no out-of-the-box solution for displaying the tree in an MVC plugin. I used &lt;a href=&quot;https://www.jstree.com/&quot;&gt;jsTree&lt;/a&gt;, a third-party jQuery plugin, to render the content which was quick to setup and easy to configure.&lt;/p&gt;
&lt;p&gt;To display the tree, I provide a url for an AJAX endpoint of the plugin which will return the first two levels of content, and is called again when subsequent children in the tree are expanded.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;script src=&quot;https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;hellip;
&amp;lt;div id=&quot;jstree&quot; class=&quot;epi-paddingVertical-small episerver-pagetree-selfcontained&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;script&amp;gt;
    $(function() {
        $(&quot;#jstree&quot;).jstree({
            &quot;core&quot;: {
                &quot;data&quot;: {
                    &#39;url&#39;: &quot;/plugins/propertyviewer/getcontenttree/&quot;,
                    &quot;dataType&quot;: &quot;json&quot;,
                    &quot;data&quot;: function(node) {
                        // jstree requests # for root of tree
                        return { &quot;id&quot;: node.id === &quot;#&quot; ? &quot;1&quot; : node.id };
                    }
                }
            },
            &quot;root&quot;: &quot;1&quot;
        });
    });
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The GetContentTree&amp;nbsp;endpoint in the plugin takes a page id as a parameter and returns details about the page and its children, using &lt;strong&gt;IContentLoader &lt;/strong&gt;to fetch content from Episerver. &lt;strong&gt;jsTree &lt;/strong&gt;expects a JSON object with a node&amp;rsquo;s id, name and an array of children with the same information.&lt;/p&gt;
&lt;p&gt;Setting the &lt;strong&gt;children &lt;/strong&gt;property to &lt;em&gt;true&lt;/em&gt;&amp;nbsp;indicates that the node has children and means that it will be closed initially. When it is expanded, another request is sent to the endpoint to fetch the next levels of the tree.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public JsonResult GetContentTree(int id = 1)
{
    var page = _contentLoader.Get&amp;lt;PageData&amp;gt;(new ContentReference(id));

    return Json(new
    {
        id,
        text = page.Name,
        children = _contentLoader.GetChildren&amp;lt;PageData&amp;gt;(page.ContentLink)?.Select(s =&amp;gt; new
        {
            text = s.Name,
            id = s.ContentLink.ToReferenceWithoutVersion().ID,
            children = _contentLoader.GetChildren&amp;lt;PageData&amp;gt;(s.ContentLink)?.Any()
        })
    }, JsonRequestBehavior.AllowGet);
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Displaying page properties&lt;/h2&gt;
&lt;p&gt;To display a dropdown list of page properties, I bind to the &lt;strong&gt;select_node &lt;/strong&gt;event (triggered when a node in the tree is selected) and call the&amp;nbsp;&lt;strong&gt;GetProperties &lt;/strong&gt;endpoint. The selected node id is passed as a parameter, and the returned html for the dropdown list is rendered below the content tree. The selected node id is also stored in a hidden input for use with other js events.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;$(&quot;#jstree&quot;).on(&quot;select_node.jstree&quot;,
    function (e, data) {
        $(&quot;#PageId&quot;).val(data.node.id);
        $.ajax(&quot;/plugins/propertyviewer/getproperties/?pageId=&quot; + data.node.id).done(
            function (data) {
                $(&quot;#blockPropertyList&quot;).html(&quot;&quot;);
                $(&quot;#results&quot;).html(&quot;&quot;);
                $(&quot;#propertyList&quot;).html(data);
        });
});&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;strong&gt;GetProperties &lt;/strong&gt;action of the controller fetches the list of standard page properties for the specified ID, and returns a partial view containing the dropdown list of properties.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public PartialViewResult GetProperties(int pageId)
{
    var page = _contentLoader.Get&amp;lt;PageData&amp;gt;(new ContentReference(pageId));
    var model = new PropertyListModel
    {
        PageProperties = page.Property
                            .Where(x =&amp;gt; x.IsPropertyData)
                            .Select(x =&amp;gt; x.Name)
                            .OrderBy(x =&amp;gt; x)
    };

    return PartialView(PropertyListView, model);
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Displaying property values&lt;/h2&gt;
&lt;p&gt;Once a page has been selected and a property chosen, we need to display a table containing the values of the property for each language.&lt;/p&gt;
&lt;p&gt;The plugin can handle properties in two ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;in the case of most properties, it simply displays the string representation for the property&lt;/li&gt;
&lt;li&gt;for local blocks (i.e. a fixed block added as a property), it provides an additional dropdown to choose the block property to view&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When a property is selected from the dropdown, we call the &lt;strong&gt;GetPropertyValues &lt;/strong&gt;endpoint with the page id and property name, and either display the values for the property, or display the block property list.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;$(&quot;#propertyList&quot;).on(&quot;change&quot;, &quot;select&quot;, function () {
    $.ajax(&quot;/plugins/propertyviewer/getpropertyvalues/?pageId=&quot;
        + $(&quot;#PageId&quot;).val() + &quot;&amp;amp;propertyname=&quot; + this.value).done(
        function (data) {
            if (data.indexOf(&quot;BlockPropertyName&quot;) &amp;gt; -1) {
                $(&quot;#blockPropertyList&quot;).html(data);
                $(&quot;#results&quot;).html(&quot;&quot;);
            } else {
                $(&quot;#blockPropertyList&quot;).html(&quot;&quot;);
                $(&quot;#results&quot;).html(data);
            }
    });
});&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;strong&gt;GetPropertyValues &lt;/strong&gt;action checks whether the specified property is a block type using &lt;strong&gt;propertyData.Type&lt;/strong&gt; and returns the list of block properties if it is block. For other property types, the property values are returned.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public PartialViewResult GetPropertyValues(PropertyReference reference)
{
    if (IsBlock(reference))
    {
        var blockModel = BuildBlockPropertyListModel(reference);
        return PartialView(BlockPropertyListView, blockModel);
    }

    var model = BuildPropertyValuesModel(reference);

    return PartialView(PropertyValuesView, model);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To fetch the values of a property for each language, we need to use &lt;strong&gt;IContentRepository.GetLanguageBranches&lt;/strong&gt; to get the language-specific instances of the page, and then fetch the value of the property for each instance.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;private PropertyValuesModel BuildPropertyValuesModel(PropertyReference reference)
{
    var languageVersions = _contentRepository.GetLanguageBranches&amp;lt;PageData&amp;gt;(new ContentReference(reference.PageId));
    var propertyValues = languageVersions.Select(x =&amp;gt; new PropertyValueModel
    {
        Language = x.Language.Name,
        Value = x.GetPropertyValue(reference.PropertyName)
    });

    return new PropertyValuesModel
    {
        PropertyValues = propertyValues
    };
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the situation where the property is a local block, we return a partial view containing a dropdown of the block properties, constructed in a similar way to the page property dropdown.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;private BlockPropertyListModel BuildBlockPropertyListModel(PropertyReference reference)
{
    var page = _contentLoader.Get&amp;lt;PageData&amp;gt;(new ContentReference(reference.PageId));
    var property = page.Property.Get(reference.PropertyName);

    return new BlockPropertyListModel
    {
        BlockProperties = ((BlockData) property.Value).Property
            .Where(x =&amp;gt; x.IsPropertyData)
            .Select(x =&amp;gt; x.Name)
            .OrderBy(x =&amp;gt; x)
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, we bind to the change event of the block property dropdown and call a &lt;strong&gt;GetBlockPropertyValues &lt;/strong&gt;endpoint that builds a table of the block property values in the same way as the page property values, but fetching the value from the property on the block.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;var propertyValues = languageVersions.Select(x =&amp;gt; new PropertyValueModel
{
    Language = x.Language.Name,
    Value = x.Property
            .GetPropertyValue&amp;lt;BlockData&amp;gt;(propertyName)
            .GetPropertyValue(blockPropertyName)
});&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The results are rendered in a simple HTML table using the default Epi table styling with a special case to display a tick for &lt;em&gt;true&lt;/em&gt; Boolean properties.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;@model AlloyTemplates.Plugins.PropertyViewer.Models.PropertyValuesModel

&amp;lt;table class=&quot;epi-default&quot;&amp;gt;
    &amp;lt;colgroup&amp;gt;
        &amp;lt;col style=&quot;width:10%&quot;&amp;gt;
        &amp;lt;col style=&quot;width:90%&quot;&amp;gt;
    &amp;lt;/colgroup&amp;gt;
    &amp;lt;thead&amp;gt;
        &amp;lt;tr&amp;gt;
            &amp;lt;th&amp;gt;Language&amp;lt;/th&amp;gt;
            &amp;lt;th&amp;gt;Value&amp;lt;/th&amp;gt;
        &amp;lt;/tr&amp;gt;
    &amp;lt;/thead&amp;gt;
    @foreach (var item in Model.PropertyValues)
    {
        &amp;lt;tr&amp;gt;
            &amp;lt;td&amp;gt;
                @item.Language
            &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt;
                @RenderValue(item.Value)
            &amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;
    }
&amp;lt;/table&amp;gt;

@helper RenderValue(string propertyValue)
{
    if (propertyValue == &quot;True&quot;)
    {
        &amp;lt;img src=&quot;/App_Themes/Default/Images/Tools/png/Check.png&quot; alt=&quot;True&quot; align=&quot;center&quot; /&amp;gt;
    }
    else
    {
        @propertyValue
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Improvements&lt;/h2&gt;
&lt;p&gt;This version of the plugin works well for simple properties &amp;ndash; text, numbers, Booleans and any property that provides a comprehensive &lt;strong&gt;ToString &lt;/strong&gt;method. It is also useful for Content References where it will show the content ID, and values stored as JSON where it will display the JSON object. It doesn&amp;rsquo;t currently work for complex property types or Content Areas since it uses the string representation of the property.&lt;/p&gt;
&lt;p&gt;Future improvements I would like to make are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;display a thumbnail for images&lt;/li&gt;
&lt;li&gt;allow the user to select a block in a content area and a property from that block&lt;/li&gt;
&lt;li&gt;handle blocks nested to more than 1 level&lt;/li&gt;
&lt;li&gt;create as an add-on so it can be easily shared and added to projects&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, in its current form it is still an extremely useful tool to have available as a first port of call for quickly auditing a property on a large multilingual site.&lt;/p&gt;</description>            <guid>https://world.optimizely.com/blogs/ollie-philpott/dates/2019/4/a-property-viewer-plugin-for-multilingual-sites/</guid>            <pubDate>Thu, 18 Apr 2019 11:34:31 GMT</pubDate>           <category>Blog post</category></item><item> <title>Common errors when developing an Episerver site</title>            <link>https://world.optimizely.com/blogs/ollie-philpott/dates/2019/2/common-errors-when-developing/</link>            <description>&lt;p&gt;At &lt;a href=&quot;https://www.zonedigital.com&quot;&gt;Zone&lt;/a&gt;, we spend a lot of time developing and maintaining large-scale Episerver builds with a team split across the UK, Romania and India. With a large codebase and lots of developers working at the same time, there are some errors we encounter occasionally that can take time a lot of time to identify, but are quick to fix when you know the solution.&lt;/p&gt;
&lt;h3&gt;Changes to content types are not reflected in the CMS&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you are using a code-first approach to create and modify pages and blocks, and you notice that changes are not being reflected when you view the content in the CMS, you may have a problem with assembly versions.&lt;/p&gt;
&lt;p&gt;You can confirm that you are experiencing this issue by navigating to the &lt;em&gt;Content Type &lt;/em&gt;tab in the &lt;em&gt;Admin&lt;/em&gt; section of the Episerver CMS. If you select a content type from the left-hand menu, you will see a yellow warning message like this:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Changes in the model for this page type were ignored because its version (1.0.0.0) is lower than version in the database(2.0.0.0)&lt;/em&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;img src=&quot;/link/9011304fc4ec458d953f9d08e878c07d.aspx&quot; width=&quot;603&quot; height=&quot;206&quot; /&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This can occur after restoring a backup of the CMS database from an environment where semantic versioning (eg GitVersion) is being used, to an environment not using any versioning &amp;ndash; such as a local development environment.&lt;/p&gt;
&lt;p&gt;Episerver stores the current version of an assembly in the database when syncing changes to the model. If the site is loaded with a version of the assembly lower than the one stored in the database, it will not update the model to avoid overwriting the most recent update with older changes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can fix this by running a short SQL script in the database to reset the version of the assemblies to correct version.&lt;/p&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;UPDATE [dbo].[tblContentType]
SET [ModelType] = REPLACE(ModelType, &#39;, Version=2.0.0.0,&#39;, &#39;, Version=1.0.0.0,&#39;)
WHERE ModelType like &#39;%, Version=2.0.0.0,%&#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should replace &lt;em&gt;2.0.0.0&lt;/em&gt; with the version that is incorrectly set in the database, and &lt;em&gt;1.0.0.0&lt;/em&gt; with the version in the assembly info.&lt;/p&gt;
&lt;h3&gt;Website pages are loading slower than usual in a development environment&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When loading a website that uses Episerver Find, pages suddenly take a lot longer to load. When checking the Episerver logs, you may find errors like this:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;EPiServer.Find.ServiceException: The remote server returned an error: (401) Unauthorized.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We have experienced this when developing locally - where we may be using an Episerver Find demo licence. Since the demo licence only lasts for 30 days, you will see this error when the licence expires if you are calling Find during page load. It is a bit more obvious if your website crashes and you see a Yellow Screen of Death (YSOD), but if you are handling errors in a more graceful way, it may be harder to identify the cause.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Generate a new demo licence at &lt;span&gt;&lt;a href=&quot;https://find.episerver.com/&quot;&gt;https://find.episerver.com/&lt;/a&gt;&lt;/span&gt; and update the search index in your Web.config.&lt;/p&gt;
&lt;h3&gt;YSOD for all pages&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Loading the site or CMS shows the .NET YSOD with an error message like the following:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;ERROR EPiServer.Framework.Initialization.InitializationEngine: Initialize action failed for &#39;Initialize on class EPiServer.Initialization.Internal.ModelSyncInitialization, EPiServer, Version=11.10.1.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7&#39;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The DELETE statement conflicted with the REFERENCE constraint &quot;FK_tblContent_tblContentType&quot;. The conflict occurred in database &quot;myCmsDatabase&quot;, table &quot;dbo.tblContent&quot;, column &#39;fkContentTypeID&#39;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This error, or similar sounding errors, can occur for a number of reasons. Lots of causes and solutions are discussed in the Episerver forums: &lt;span&gt;&lt;a href=&quot;/link/cbaa80f6c2d6481c89c48fbbbfdfc280.aspx?searchQuery=statement+conflicted&amp;amp;from=151704&quot;&gt;https://world.episerver.com/Search?searchQuery=statement+conflicted&amp;amp;from=151704&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The error is triggered from SQL Server when a command to delete a row of data conflicts with a constraint on one of the columns in the database table.&lt;/p&gt;
&lt;p&gt;In this case, it seems to occur during the model sync as Episerver initialises after a page or block type has been deleted from code. I have not been able to identify the exact conditions that lead to this error in Episerver but I have seen it happen several times after deleting a page type and deploying the code to another environment. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you check the &lt;em&gt;tblContent&lt;/em&gt; table in the Episerver database, you may find you have orphaned rows that are flagged as &lt;em&gt;Deleted&lt;/em&gt; but are not present in the &lt;em&gt;Recycle Bin&lt;/em&gt; of the CMS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Empty the Recycle Bin in the CMS&lt;/li&gt;
&lt;li&gt;&lt;em&gt; &lt;/em&gt;Run a SQL query to check if there are still any rows remaining in the database that are set as &lt;em&gt;&lt;em&gt;Deleted:&lt;br /&gt;&lt;/em&gt;&lt;/em&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;SELECT * 
FROM [tblContent]
WHERE Deleted = 1&lt;/code&gt;&lt;/pre&gt;
&lt;em&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;If there are rows returned by the query after emptying the recycle bin, delete the rows from the table:&lt;br /&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;DELETE 
FROM [tblContent]
WHERE Deleted = 1​&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The site should now load as normal.&lt;/p&gt;
&lt;h3&gt;Front-end assets redirect to the login page&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We have experienced this error when a developer is setting up a new machine or a new project. The issue happens when loading the website &amp;ndash; front assets such as CSS or JavaScript fail to load and if you attempt to load the assets directly you are taken to the Episerver login page.&lt;/p&gt;
&lt;p&gt;Logging into the CMS will allow the assets to be loaded, but this issue is caused by misconfigured Windows security permissions for assets folders for &lt;em&gt;IUSR&lt;/em&gt; or &lt;em&gt;IIS_IUSRS.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;img src=&quot;/link/1bf538b2078e45daa6f66f128e05f78d.aspx&quot; /&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Right-click on the root folder of the website, select &lt;em&gt;Properties&lt;/em&gt; and the &lt;em&gt;Security&lt;/em&gt; tab.&lt;/p&gt;
&lt;p&gt;Ensure that &lt;em&gt;IUSR&lt;/em&gt; and &lt;em&gt;IIS_IUSRS&lt;/em&gt; have at least read access to the root folder and subfolders (&lt;em&gt;IIS_IUSRS&lt;/em&gt; requires write access to the blobs folder).&lt;/p&gt;
&lt;p&gt;The assets should load correctly once these permissions are configured.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/a225014519bd485e87d671d40f9eac12.aspx&quot; /&gt;&lt;/p&gt;</description>            <guid>https://world.optimizely.com/blogs/ollie-philpott/dates/2019/2/common-errors-when-developing/</guid>            <pubDate>Tue, 19 Feb 2019 11:59:05 GMT</pubDate>           <category>Blog post</category></item></channel>
</rss>