Category Archives: .Net

Azure Functions – Json: Self referencing loop detected for property

Problem

Whilst developing a Rest API using Azure functions I got the error below.

 Newtonsoft.Json: Self referencing loop detected for property 'task' with type 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[System.Collections.Generic.IEnumerable`1[Feature.Order.Domain.TravelCard.OrderedTravelCard],Feature.Order.Domain.TravelCard.OrderedTravelCardRepository+<Get>d__4]'. Path 'stateMachine.<>t__builder'

As we had created a lot of new models and called a number of external API’s, which had a bad habit of changing their models without notification. I assumed incorrectly that one of the swagger files for the API’s was not correct.

But after much investigation I could not detect any issue with the data returned from the external API’s and the models match correctly their definitions.

Eventually I found out what the issue was, can you see what is wrong with the following code?

Solution

See the image above that a Task<…> is returned from the OrderedTravelCardRepository.Get() function.

I had forgotten to await the asynchronous call of the function, see the fixed code below.

Simple when you know how, simply awful when you don’t!

I hope this blog post helps others avoid the time I wasted on this issue.

How SQL Index Fragmentation will kill Sitecore’s Performance

Thought I wrote a blog post about this years ago, but apparently I didn’t.

Problem

Poor index maintenance is a major cause of decreased SQL Server performance, which in turn will impact your Sitecore’s performance. The Sitecore databases contains tables with numerous entries, that get updated frequently, therefore high index fragmentation will occur.

Detecting SQL Server index fragmentation

The following script displays the average fragmentation, and as a help generates the SQL query to fix it.

SELECT OBJECT_NAME(ind.OBJECT_ID) AS TableName,
ind.name AS IndexName, indexstats.index_type_desc AS IndexType,
indexstats.avg_fragmentation_in_percent,
'ALTER INDEX ' + QUOTENAME(ind.name) + ' ON ' +QUOTENAME(object_name(ind.object_id)) +
CASE WHEN indexstats.avg_fragmentation_in_percent>30 THEN ' REBUILD '
WHEN indexstats.avg_fragmentation_in_percent>=5 THEN 'REORGANIZE'
ELSE NULL END as [SQLQuery] -- if <5 not required, so no query needed
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) indexstats
INNER JOIN sys.indexes ind ON ind.object_id = indexstats.object_id
AND ind.index_id = indexstats.index_id
WHERE
--indexstats.avg_fragmentation_in_percent , e.g. >10, you can specify any number in percent
ind.Name is not null
ORDER BY indexstats.avg_fragmentation_in_percent DESC

Below you can see the typical result of running the script above. I was shocked as the majority of indexes on my local SQL server where over 99%.

Solution

The script above generates the SQL statements needed to defragment the affected indexes, so you can automate the defragmentation process, using SQL Server Maintenance Plans.

Anyway I hope this helps keeping you sitecore solution running at its best, Alan

Swagger – An item with the same key has already been added. Key: 400

We had a solution that used azure functions provide a rest API, to help reduce the load on the sitecore content delivery servers.

We used AzureExtensions.Swashbuckle  which makes it so easy to add swagger documentation to Azure functions.

Problem

Suddenly the swagger UI no longer worked and we got the An item with the same key has already been added. Key: 400 ” exception.

After going through all the commits, one by one I could not see how the code changes could introduce this error?

Solution

Until I noticed that there where 2 ProducesResponseType attributes with the same status code (i.e. 400).

It was soo obvious when I noticed it, but when I look at C# code for changes I guess I ignore comments and attributes.

Therefore I hope by drawing attention to my stupid mistake I can help others that experience this issue, Alan

hack attibute

Hack Attribute to the Rescue

The challenge

At some point in a web project a underlying system, rest API, etc. will not be available and you must make some hacks and or fake code to enable development to continue.

But how do you ensure that the hacks and or fake code never make it into production? Typically  TODO’s, comments, PBI’s etc. are used, but to be honest I have never liked doing that.

Especially in this case as the OAuth Authorization flow was not available, so I had to fake the authentication.

Solution

Introducing the [Hack] custom attribute. It adds the ability to add the hack attribute to classes, properties, and methods.

  • When the code is compiled to Debug–  it generates a warning,
    • So the code compiles and can be deployed
  • When the code is compiled to Release – it generates an errorSo the code cannot compile, and can’t be deployed to production.

In out setup for local development, continues integration and our internal development & test server we build for debug. For pre-production & production we build for release.

Therefore I could relax knowing that the hacks could not make it into production.

The Code

namespace Foundation.Diagnostics.Infrastructure
{
#if !DEBUG
[Obsolete("Hack code is still present", true)]
#endif
#if DEBUG
[Obsolete("Hack code is still present")]
#endif

[AttributeUsage(AttributeTargets.All)]
public class HackAttribute : Attribute
{
public HackAttribute(string message)
{
Message = message;
}

public string Message { get; }
}
}

It was actually quite simple to achieve by using the Obsolete attribute and the using preprocessor directives, to control if the Obsolete attribute should couase a warning or error, depending if the build was debug or release.

Hope this helps, Alan

How IQueryable and Take can kill your Sitecore Solution

We had a solution that had serve performance issue when it got a lot of visitors. Sitecore was casting the following exception and SolR had a similar errors in its logs:

Unable to read data from the transport connection: The connection was closed

We identified that the problem was caused by hitting the network bandwidth in Azure!
Yes, there were a lot of visitors, but enough to hit the bandwidth limit, the customer upgraded the plan to get more network bandwidth, but still the issues continued.

But what could cause this issue?

I started to review the SolR implementation and found the issue quite quickly.

return IQueryable<Result>
            .Where(result => result.Date < DateTime.UtcNow)
            .OrderByDescending(result => result.Date)
            .GetResults()
	    .Take(count)
            .ToList();

The Take() was made after GetResults() was called, so the entire data set is returned to Sitecore from SolR, then the take was applied to get the top 5 results.

This simple mistake was what caused all the network and performance issues.

Solution

return IQueryable<Result>
            .Where(result => result.Date < DateTime.UtcNow)
            .OrderByDescending(result => result.Date)
	    .Take(count)
            .GetResults()
            .ToList();

It was a simple fix (in 150+ places) to move the Take before GetResults!

This is why I believe that you should always Introduce a (SolR) Sitecore Search Abstraction, please read my post on this very subject, instead of returning the IQueryable interface.

Hope this helps, Alan

 

Sitecore Helix – Supporting Integrations

This blog will outline how it is possible to identify, separate and isolate dependencies on external systems, by introducing an Integrations module group. See here for more information about module groups in Helix.

But why do we need a Integrations module group?

Any feature that requires integration to achieve its purpose, will introduce additional challenges relating to stability and additional system knowledge, than a standard feature layer module.

Stability

Helix is built on a number of principles that help deal with stability, the Stable-dependencies principle and Stable-abstractions principle for more details see my blog post.

Features that rely on 3rd party systems are by nature more unstable than any other feature/foundation modules. As it is not usually possible to control when external systems change, upgrade or fail. Therefore, quality assurance, test, and automated deployment for the website cannot protect against this type of change or failure.

System knowledge

Working with a 3rd party system, such as CRM, ERP, Marketing Automation, DAM, SolR, Custom API, etc. requires additionally system specific knowledge. So it is a good idea to use abstractions to hide the system specific complexities for several reasons:

  1. The web team might not have the specific system knowledge.
  2. The web team should not be distracted by the additional complexities of all the integrations.
  3. The team responsible for implementing the integration may have limited Sitecore knowledge and should not be distracted by the rest of the web solution.
  4. It is good practice to separate modules by their responsibilities by splitting the presentation and the retrieval of data from the external system.

Integrations Module Group

The intention/purpose of the Integrations module group is to clearly define which modules have a dependency on an external system and ensure they are only responsible for that integration to the external system.

Example

This solution is responsible for selling a wide variety of courses. The customer has its own custom course catalog API and a complex legacy enrollment system.

The following diagram shows the module architecture for the solution.

In the foundation layer the following modules were introduced to provide abstractions. If you are not familiar with IoC and Abstractions see my earlier post.

  • Course Catalog
    • Defines the abstraction/system agnostic logical data module for the course catalog.
    • Acts as an abstraction between the website and Custom Catalog API.
    • It helps to focus on the ideal model that supports the business objectives.
  • Enrollment
    • Defines the abstractions to support the process of initiating attendance on a course at a specific school and shopping cart.
    • Acts as an abstraction between the website and the enrollment legacy system.
    • It helps to focus on the ideal model that supports the business objectives.

In the Integrations Group in Features layer the following modules where introduced

  • EXT Course API
    • Responsible for getting data provided by the EXT Course API.
    • Provide the implementation of the Course Catalog (foundation layer) abstractions.
    • Responsible for caching the course catalog, as the API only supports periodical batch retrieval.
  • EPOC Enrollment Management
    • Responsible for integration of the functionality provided by the EPOC Enrollment Management SDK.
    • Provide the implementation of the Enrollment (foundation layer) abstractions.

In the Features layer the following modules where introduced

  • Course
    • Responsible for the presentation of the course catalog, retrieved via the course catalog abstractions defined in the foundation layer.
  • Enrollment
    • Responsible for presentation and controlling the process of initiating attendance on a course and displaying the shopping cart, using the abstraction  defined in the foundation layer.

Additional Bonus

Once the integration code is isolated in a single module and only responsible for the integration, it is easier using dependency injection to achieve the following:

  1. Update external system, as the code to change is clearly defined and separated from the presentation and website logic.
  2. Provide the ability to support more than one version of an integration (i.e. different sites use different version)
  3. Move the integrations modules to an integrations platform, if it is the domain model for the customer business.

I hope this blog post gives you some ideas on how to isolate and remove the complexities introduced by integrations from your Sitecore solution, Alan

In my next post, I will explain why and in more detail how to isolate the SolR integration.

 

 

Salesforce Connector – Strange Error (AlreadyExists, contact) Syncing checkbox field from Salesforce to Sitecore

Problem

We had setup the pipeline batch to sync from sitecore to Sales-force, and the from Salesforce to Sitecore and it worked.

Then we had to add a single checkbox that should be mapped from Salesforce to Sitecore, the checkbox was already setup to be sync’d from sitecore to Salesforce.

After setting it up, we got the following error whenever we changed the checkbox  value in Salesforce.


ManagedPoolThread #3 13:40:16 INFO  [Data Exchange] Submitting batch to xConnect. (pipeline: Read Contacts from Salesforce Pipeline, pipeline step: Submit Remaining Operations in xConnect Batch, pipeline step identifier: 1bb0f7dd-1d1f-454a-879e-6655399a42bf, description: Batch from thread 0, operation count: 8)
ManagedPoolThread #3 13:40:16 ERROR [Data Exchange] Exception thrown when processing a pipeline batch. (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect)
ManagedPoolThread #3 13:40:16 ERROR [Data Exchange] Exception while submitting batch to xConnect. (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect)
ManagedPoolThread #3 13:40:16 ERROR [Data Exchange]    at Sitecore.DataExchange.Providers.XConnect.Processors.PipelineSteps.BaseSubmitXConnectBatchStepProcessor.SubmitBatch(String batchDescription, IXdbContext client, PipelineStep pipelineStep, PipelineContext pipelineContext, ILogger logger)
   at Sitecore.DataExchange.Providers.XConnect.Processors.PipelineSteps.SubmitXConnectBatchStepProcessor.ProcessPipelineStep(PipelineStep pipelineStep, PipelineContext pipelineContext, ILogger logger)
   at Sitecore.DataExchange.Processors.Pipelines.PipelineProcessor.ProcessPipelineStep(PipelineStep pipelineStep, PipelineContext pipelineContext, ILogger logger)
   at Sitecore.DataExchange.Processors.Pipelines.PipelineProcessor.ProcessPipeline(Pipeline pipeline, PipelineContext pipelineContext, ILogger logger)
   at Sitecore.DataExchange.Processors.PipelineBatches.BasePipelineBatchProcessor.ProcessPipelineBatch(PipelineBatch pipelineBatch, PipelineBatchContext pipelineBatchContext, ILogger logger)
ManagedPoolThread #3 13:40:16 ERROR [Data Exchange] One or more errors occurred. (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect)
ManagedPoolThread #3 13:40:16 ERROR [Data Exchange]    at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at Sitecore.DataExchange.Providers.XConnect.Processors.PipelineSteps.BaseSubmitXConnectBatchStepProcessor.SubmitBatch(String batchDescription, IXdbContext client, PipelineStep pipelineStep, PipelineContext pipelineContext, ILogger logger)
ManagedPoolThread #3 13:40:16 ERROR [Data Exchange] START AGGREGATE EXCEPTION (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect, ID: 19, HResult: -2146233088)
 Exception thrown when processing a pipeline batch. (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect)
One or more operations did not succeed (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect)
   at Sitecore.XConnect.XdbContext.&amp;amp;lt;ExecuteBatchAsyncInternal&amp;amp;gt;d__79.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Sitecore.XConnect.XdbContext.&amp;amp;lt;SubmitAsync&amp;amp;gt;d__74.MoveNext()
START AGGREGATE EXCEPTION (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect, ID: 20, HResult: -2146233088)
  Exception thrown when processing a pipeline batch. (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect)
Operation #7, AlreadyExists, Contact {0b9e30fe-f081-0000-0000-056ff184830f}, NewsletterInformation (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect)
  Exception thrown when processing a pipeline batch. (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect)
Operation #7, AlreadyExists, Contact {0b9e30fe-f081-0000-0000-056ff184830f}, NewsletterInformation (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect)
END AGGREGATE EXCEPTION (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect, ID: 20, HResult: -2146233088)

 Exception thrown when processing a pipeline batch. (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect)
One or more operations did not succeed (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect)
   at Sitecore.XConnect.XdbContext.&amp;amp;lt;ExecuteBatchAsyncInternal&amp;amp;gt;d__79.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Sitecore.XConnect.XdbContext.&amp;amp;lt;SubmitAsync&amp;amp;gt;d__74.MoveNext()
START AGGREGATE EXCEPTION (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect, ID: 21, HResult: -2146233088)
  Exception thrown when processing a pipeline batch. (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect)
Operation #7, AlreadyExists, Contact {0b9e30fe-f081-0000-0000-056ff184830f}, NewsletterInformation (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect)
  Exception thrown when processing a pipeline batch. (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect)
Operation #7, AlreadyExists, Contact {0b9e30fe-f081-0000-0000-056ff184830f}, NewsletterInformation (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect)
END AGGREGATE EXCEPTION (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect, ID: 21, HResult: -2146233088)

END AGGREGATE EXCEPTION (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect, ID: 19, HResult: -2146233088)

ManagedPoolThread #3 13:40:16 DEBUG [Data Exchange] Pipeline batch processor finished processing pipelines. (pipeline batch: xConnectToSalesforceAndSalesforceToxConnect, completed pipelines: 1)


Now you might of noticed that the issue is related to the contact already existing?

  • Operation #7, AlreadyExists, Contact {0b9e30fe-f081-0000-0000-056ff184830f})

Strange error message? Of course the contact already exists, as the contact is first created via the website and then sync’d to Salesforce?

Solution

The issue was related to the fact, that I had missed to add the “Newsletter Information” facet to the “Facets to Read” field on the “Resolve Contact Model by Salesforce Id from xConnect” item, see image below.

To be honest I believe that the error message was very misleading, hence this blog post. As there are 1000’s of items to associated with the Salesforce connector, it is very easy to miss a field selection and or other required item setup.

Credits

Big thanks to Paul Kravchenko, from Sitecore support, who worked very had to identify and fix this issue, which we managed after a few online meetings 🙂

Hope this helps others out there, Alan

Structured, Type Safe Settings in Sitecore

This feature seems to be overlooked, so I hope this blog post will draw more attention to this feature, and make it’s use more widespread.

In Sitecore, it is easy to map configuration settings to a C# class, whilst maintaining a structure that adheres to the helix principles, see the config below.

Then the mapped C# class can registered with IServiceCollection, so it can be injected into any class using dependency injection.

<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:environment="http://www.sitecore.net/xmlconfig/environment">
<sitecore environment:require="Local">
<feature>
<salesforce>
<clientSettings type="Example.Feature.Salesforce.Infrastructure.SalesforceClientSettings, FKCC.Feature.Salesforce" singleInstance="true">
<Username>example@blog.example.com</Username>
<Password>xxxxxxx</Password>
<Token>yyyyyyy</Token>
<CacheExpiry>60</CacheExpiry>
<OrganisationId>1111111</OrganisationId>
</clientSettings>
</salesforce>
</feature>
</sitecore>
</configuration>

Previously settings used to be a long flat list of settings, which if we were lucky were grouped use prefixes in the name attribute to indicate which feature they were used by.

<setting name="Feature.Salesforce.Authentication.Username" value="xxxx@example.com" />
<setting name="Feature.Salesforce.Authentication.Password" value="BestPasswordInTheWorld" />
<setting name="Feature.Salesforce.Authentication.SfToken" value="Its a SF token" />
<setting name="Feature.Salesforce.Authentication.CacheExpiry" value="60" />

Solution

It is now very simple to map structured configuration to a type safe C# class, and it involves 4 simple steps.

Step 1 – Define C# Class

Define the C# class that stores the data defined by the settings in the config file, for this example, we will define some authentication settings for a sales force client.

namespace Example.Feature.Salesforce.Infrastructure
{
public class SalesforceClientSettings
{
public string Password { get; protected set; }
public string Username { get; protected set; }
public string Token { get; protected set; }
public int CacheExpiry { get; protected set; }
public string OrganisationId { get; set; }
}
}

Step 2 – Define the settings

It is not required, but I would recommend following the Helix principles when defining the settings structure i.e.

[Layer]/[Feature Name]/[Settings Name]

The type attribute defines which class (i.e. the one defined in step 1) to map the settings element to.

<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:environment="http://www.sitecore.net/xmlconfig/environment">
<sitecore environment:require="Local">
<feature>
<salesforce>
<clientSettings type="Example.Feature.Salesforce.Infrastructure.SalesforceClientSettings, FKCC.Feature.Salesforce" singleInstance="true">
<Username>example@blog.example.com</Username>
<Password>xxxxxxx</Password>
<Token>zzzzzz</Token>
<CacheExpiry>60</CacheExpiry>
<OrganisationId>1111111</OrganisationId>
</clientSettings>
</salesforce>
</feature>
</sitecore>
</configuration>

Step 3 – Map the configuration to the C# class

Sitecore makes this so easy, using Factory.CreateObject method, which loads the configuration and maps it to the C# class.

(SalesforceClientSettings) Factory.CreateObject("feature/salesforce/clientSettings", true)

Note: Factory.CreateObject expects that configuration path, is relative to the sitecore configuration, not the complete path.

Step 4 Setup dependency injection.

Register the created class with the IServiceCollection, so we can access the class, where necessary using constructor injection.

namespace Example.Feature.Salesforce.Infrastructure
{
public class ServiceConfigurator : IServicesConfigurator
{
public void Configure(IServiceCollection serviceCollection)
{
serviceCollection.AddSingleton(provider =>
(SalesforceClientSettings) Factory.CreateObject("feature/salesforce/clientSettings", true));

}
}
}

I hope this blog posts, helps you to structure your settings in a more maintainable and coherent structure, Alan

Lower-casing Rewrite Rules Breaks The Sitecore Client

Problem

I was asked to look at a Sitecore solution, where it was not possible to show a custom application in the sitecore client. In fact it was not possible to show a number of the standard dialog’s, for example the presentations dialog (see the image above).

It was strange as some dialog’s worked and others did not, so I opened the developer tools which immediately showed me what the issue was.

As you can see a lot of stuff is missing? This is because Sitecore’s HTTP handler is looking for URL’s that begin with “WebResource.axd” and it is case sensitive.

Rewrite Rules Strike Again

To improve SEO, the following rewrite rule was introduced in the web.config to lower case ALL url’s 

Now whilst this was great for the websites SEO; it was responsible for breaking the sitecore client as there are a number of URL’s which are case sensitive.

Solution

The solution was to identify all the case sensitive sitecore client URL’s and exclude them from the lowercase rule.

Now instead of trying to write the most complex regular expression ever, which would catch all the website URL’s and avoid all the Sitecore client calls.

I decided to add an individual condition match pattern for each (URL) and then used the negate=true to exclude the URL from the redirect rule.

Thanks to Marc Downer for following version which fixes issues relating to the path and query strings being stripped, from the URL.

<rewrite>
   <rules>
     <!-- https://blog.coates.dk/2018/01/15/lower-casing-rewrite-rules-breaks-the-sitecore-client/ -->
     <!-- Take redirectType="Temporary" out of production -->
      <rule name="LowerCaseRule - not including querystring" stopProcessing="true">
         <match url="(.*)" />
          <conditions>
            <add input="{PATH_INFO}" pattern=".*[A-Z]" ignoreCase="false" />            
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
            <add input="{REQUEST_URI}" pattern="^/(sitecore)" negate="true" />
            <add input="{REQUEST_URI}" pattern="^/(sitecore modules)" negate="true" />
            <add input="{REQUEST_URI}" pattern="^/-/" negate="true" />
            <add input="{REQUEST_URI}" pattern=".*(-/media).*" negate="true" />
            <add input="{REQUEST_URI}" pattern=".*(~/media).*" negate="true" />
            <add input="{REQUEST_URI}" pattern=".*(~/icon).*" negate="true" />
            <add input="{REQUEST_URI}" pattern="WebResource.axd" negate="true" />
            <add input="{REQUEST_URI}" pattern="ScriptResource.axd" negate="true" />
            <add input="{REQUEST_URI}" pattern="jsnlog.logger" negate="true" />
            <add input="{REQUEST_URI}" pattern="Telerik.Web.UI.WebResource.axd" negate="true" />
            <add input="{REQUEST_METHOD}" matchType="Pattern" pattern="POST" ignoreCase="true" negate="true" />
          </conditions>
          <action type="Redirect" url="/{ToLower:{R:1}}" appendQueryString="true" redirectType="Temporary" />
      </rule>
   </rules>
</rewrite>

Ignore POST requests

Thanks to Søren Kruse for pointing this out; The redirect will change a POST requests to a GET and you will lose any data in the body of the original request. Therefore you should ensure that POST requests are not redirected.

<add input="{REQUEST_METHOD}" matchType="Pattern" pattern="POST" ignoreCase="true" negate="true" /><span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"></span>

Well I hope this helps, Alan

 

 

How to kill Sitecore – whilst installing an update package

Problem

Whilst installing an update package on the client’s/customer’s development environment the ASP.NET worker process would be killed suddenly. This issue was found on Sitecore 8.1 Update 4.

error

There was nothing shown in the Sitecore log or in the windows Event log. Therefore I took a Memory dump and investigated the dump using Debug Diagnostic 2 . I found at the bottom of the report 100000’s of lines with the same 4 lines of text, so I assumed there was an infinite loop, which was responsible for using all the memory, and crashing the ASP.NET worker process.

loop

I could not reproduce the error in a clean installation of Sitecore, so I assumed it was due to configuration and or some solution specific code. So I started making a comparison between the customers solution and the clean sitecore and I identified that the following settings where defined twice:

  • ServerTimeZone
  • ContentSearch.SearchMaxResults
  • ContentSearch.DefaultIndexConfigurationPath

showconfig.aspx confirmed this as you can see below.

1

2

The first was caused by an error in the solution specific configuration, the remaining were caused by 2 Sitecore includes having the same setting.

Solution

Ensure no settings and or other configuration is duplicate. Typically after I found out what the error was I discovered that Sitecore writes a warning in the log file! Maybe I should pay more attention to warnings.

warn

Anyway I hope this helps 🙂