Sitecore

Sitecore Express Migration Tool 2.0 skipping Security and Configuration steps

I recently got to know this wonderful tool when upgrading an old Sitecore version. The tool itself allows you to migrate any Sitecore 6.6 or Sitecore 7.2 versions to Sitecore 8.2. It also includes support for migrating Web Forms for Marketers.

My first experience was upgrading a 7.2 to 8.2. and within a day, the solution was fully upgraded and ready for testers. However, my newest attempt at upgrading a 6.6 solution gave a bit trouble. We decided to run at test upgrade to see if everything was migrated as it should, locally first.

All seemed fine, and we ran the migration again, but from using the production environments databases. This time the tool skipped both Security and Configuration. LEaving all users and roles behind. After some debugging and searching, I found that this was a know issue with the Express Tool:

The tool skips security and configuration steps if at least one migration was completed for the same source version (137519). Source

We needed to reset the tool in order to be able re-run the migration. To reset the tool you have to delete the Database file, created during the first run of the tool:

  • Migration.db

It is located in the root folder of the tools. The database file stores information on previous migrations, and somehow Sitecore skips Security and Configuration, if you already migrated the source version once before.

With the tool reset, the migration works perfectly again 🙂

 

 

 

Sitecore

Sitecore Intranet Platform? What happened to it?

If you search for Sitecore Intranet, within the Sitecore regime, you will find the old sdn pages about the intranet portal, with a message saying :

The Sitecore Intranet Platform has been discontinued.

Sitecore officially discontinued the SIP product, after the last release October 22, 2013. The last supported version from Sitecore is Sitecore Intranet 4.1, running on a Sitecore 7.x installation. However, at Oxygen A/S, some of our largest customers were using the Sitecore Intranet Platform throughout their entire organization with multiple integrations. Their employees have one point of entry to most of their systems, the Intranet.

Because of this, we started to develop the Sitecore Intranet platform, upgrade it, remove old deprecated Sitecore elements to replace with newer technology, updated work processes and added much needed features. Today, the intranet runs on Sitecore 8.2.

We have updated it, following these four keywords.

  • Easy
  • Accessible
  • Social
  • Integrated

One of the main feature we have added, is the Social wall:

Oxygen itranet

The wall is where the employee can communicate and share knowledge with each other. They can upload videos, images and direct their messages to groups, users or teams if needed.

Another cool new feature is the groups. The groups in Oxygen Intranet are made both for professional and social purposes. This is an effective way to share knowledge with a project group, but it can also be used in non-work related contexts like film or sport groups.

Group

The new Oxygen Intranet comes with a lot more features than mentioned here. This post was to clarify for Sitecore developers / Marketeers what happened to the old SIP (Sitecore Intranet Portal). If you would like to know more about the Oxygen Intranet, have a look at it here.

 

Sitecore

Getting standard Sitecore fields as a list?

I had a task where I needed to get field names present on an item. By getting all fields on an item using Item.Fields, I could easily convert this list to a list of strings, containing the name of the field:

var fieldNames = contextItem.Fields.Select(field => field.Name).ToList();

In my case the client would provide a exclude pipe-separated list of item names which we didn’t need for this operation:

Exlucde

Removing these values:

var excludedFields = templateFieldValue.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
// Removed excludes.
foreach (string fieldName in excludedFields)
{
     fieldNames.RemoveAll(x => x.ToLower().Equals(fieldName.ToLower()));
}

However, this will leave you with a list of custom fields for the item, along with standard fields from Sitecore. In our case we needed to have a complete list of custom fields, without Sitecores standard fields.

To achieve this, Sitecore has a static class which contains all of the standard fields for Sitecore:

Sitecore.FieldIDs

This class has 82 fields, which return a Sitecore.Data.ID. I needed a list of those IDs, so I could filter my field names, and remove all unneeded fields. To get this list you can use reflection:

/// <summary>
/// Use reflection to get all sitecore standard field ids from FieldIDs class
/// </summary>
/// <returns>List of Sitecore standard fields IDs</returns>
private static List<ID> GetStandardSitecoreFields()
{
     Type myType = typeof(FieldIDs);
     FieldInfo[] fields = myType.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
     return fields.Select(field => (ID) field.GetValue(myType)).ToList();
}

With this list you can easily remove Sitecore standard fields, when using Item.Fields:

var fieldNames = contextItem.Fields.Where(f => !sitecoreStandardFieldIDs.Contains(f.ID)).ToList().Select(field => field.Name).ToList();
ASP.NET, Coding

Automatic AssemblyInfo creation on build!

I am currently developing a Sitecore module for a client, who needed a versioning based on builddate. They wanted the module to display an message to the user if it was out of date. We therefore needed to update the assembly files versions on each release. To ensure we remember to to update the version with every release, I looked into making this automatic. This can be usefull for Sitecore modules and all other applications.

To achieve this, I used AssemblyInfo for versioning. First we need to retrive the version form the assembly file:

var version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion;

We use it to check against a webservice, where the client provided the newest version number in XML.

<ApplicationVersions>
   <SitecoreConnector>2017.05.31.1003</SitecoreConnector>
</ApplicationVersions>

There is a lot of modules or plugins which can auto increment the version in assemblyinfo. However we needed it to be based on date and time. Therefore I decided to use T4 TextTemplates, to create a AssemblyVersion.cs file:

<#@ template language="C#" #>
<#@ output extension=".cs" #>  
using System;
using System.Reflection;
 
[assembly: AssemblyVersion("<#=DateTime.Now.ToString("yyyy.MM.dd.HHmm")#>")]
[assembly: AssemblyFileVersion("<#=DateTime.Now.ToString("yyyy.MM.dd.HHmm")#>")]
[assembly: AssemblyCopyright("Copyright © Customer <#=DateTime.Now.Year#>")]

T4 is used by developers as part of an application or tool framework to automate the creation of text files with a variety of parameters. These text files can ultimately be any text format, such as code (for example C#), XML, HTML or XAML. T4 Text transformation (Wiki)

I use C# to get the date and time, and format it to my versioning needs. It can also be used to set the Copyright year dynamically. When this file is saved, Visual Studio automatically runs the template and create a AssemblyVersion.cs file:

using System;
using System.Reflection;
 
[assembly: AssemblyVersion("2017.05.31.1003")]
[assembly: AssemblyFileVersion("2017.05.31.1003")]
[assembly: AssemblyCopyright("Copyright © Customer 2017")]

To automate this creation, I have created a pre-build event for the project. This event uses TextTransform.exe to transform the T4 template before the build.

set textTemplatingPath="%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\texttransform.exe"
if %textTemplatingPath%=="\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\texttransform.exe" set textTemplatingPath="%CommonProgramFiles%\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\texttransform.exe"
%textTemplatingPath% "$(ProjectDir)AssemblyVersion.tt"

And thats it! Automatic created AssemblyVersion.cs which runs on every build.

Sitecore

Pasting ‘CLEAN’ text into Single line text fields

We come across a lot of customers complaining about pasting text into Sitecore fields. When pasting text from e.g Outlook or any other Microsoft applications, you usually get a lot of MSO styling with your text:

<p class="MsoNormal" style="background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;">
<span style="font-size:10.0pt;font-family:"Arial",sans-serif">
Copied text from Outlook
</span> 
<o:p></o:p> 
</p>

When using the Rich Text Editor, you get the option to “clean” the pasted text. However, this is not the case for Single Line Text fields in Sitecore. Getting styling saved have the potential to break Sitecore Experience editor or any other custom code depending on the usage of the text field.

To clean the pasted text, you can simply implement a javascript on your layout and it will be applied to your fields:

    function handlePaste(e) {
        var clipboardData, pastedData;
 
        // Stop data being pasted into div
        e.stopPropagation();
        e.preventDefault();
 
        // Get pasted data via clipboard API
        clipboardData = e.clipboardData || window.clipboardData;
        pastedContent = clipboardData.getData('Text');
 
        // Execute paste with clean data
        document.execCommand('insertText', false, pastedContent);
    }
 
    document.addEventListener('paste', handlePaste);

 

Sitecore

Editcontext inside editcontext == Bad things.

As a developer, you need to be able to edit a Sitecore item for different reasons. We had a issue were we updated users data on login. The process was a bit complex and we needed to calculate multiple fields and values for each user and set it on their profileitem.

When editing a Sitecore item, the developer uses a editcontext:

using (new EditContext(item))
{
    item["FieldName"] = "Value";
}

However we had multiple fields needed to be edited, so we combined the field edits in one editcontext. At some point a nested method created a new editcontext with the same item.

using (new EditContext(item))
{
    // Update item
    CalculateFieldValueAndSet(item)
    // Update item
    item["Field1"] = "FieldValue";
}
private void CalculateFieldValueAndSet(Item item)
{
     // Calculate value
     var value = "a" + "b";
     using (new EditContext(item))
     {
          item["FieldName"] == value;
     {
}

When the editcontext inside CalculateFieldValueAndSet is closed, it closes all editing of the item resulting in a “Item is not en editing mode” error:

Exception: Sitecore.Exceptions.EditingNotAllowedException
Message: Item '/sitecore/content/user/B/bd/bd' is not in editing mode. Item ID: {0}
Source: Sitecore.Kernel

So be careful when using editcontext for complex and editing multiple fields on a item. 🙂

Sitecore, Uncategorized

Log files piled up? Cleanup agent log pattern fix.

In Sitecore 7.x they added some new standard logs to the solution.

  • Log – All-purpose, general Sitecore log.
  • WebDAV – Log for WebDAV activity.
  • Search – Activity from searches performed using Sitecore search providers.
  • Crawling – Activity from crawling performed by Sitecore search providers.
  • Publishing – Activity from publishing performed by Sitecore servers.
  • Fxm – Activity from Federated Experience Manager. If you are not using FXM, this log will be empty.

One thing they forgot, was to update the Cleanup agent’s log pattern.

<remove folder="$(dataFolder)/logs" pattern="log.*.txt" maxCount="20" minAge="7.00:00:00" />

This pattern will only match files starting with “log.”. The new log files prefixes with their name:

logs

Without the proper patteren, teh cleanup agent will never delete any of the new log files. To fix this you will need to update the pattern, to match the new Sitecore  standard log names:

<remove folder="$(dataFolder)/logs" pattern="*log.*.txt" maxAge="30.00:00:00" />

This is fixed in Sitecore 8.0 – update 1, however it is still a issue on solutions running older versions of Sitecore.