Installing Sitecore 9 when you’ve installed 9.1

Installing Sitecore 9 was never the easiest of things, particularly when you compare it to how relatively simple Sitecore 8 was. But if you install Sitecore 9.1 on the same machine and then try your trusty Sitecore 9.0 script you may find it’s got even harder and there’s a bunch of new issues to worry about.

Multiple version of SIF

The first issue your probably going to run into is an error saying a name parameter is missing. Your script hasn’t change, but what has changed is the default version of SIF that’s now running.

So the first change you need to make is to ensure your running the correct version of SIF. You can do this either by adding the command to your script or running this before calling you install script. It will take effect for the duration of your PowerShell session.

#Switch to correct vesion of SIF
Remove-Module -Name SitecoreInstallFramework
Import-Module -Name SitecoreInstallFramework -RequiredVersion 1.2.1

If you want to check what the active version of SIF is you can do this in a PowerShell window using

Get-Command -Module SitecoreInstallFramework | Select-Object -Property name, version

Certificates Error – Part 1

Now we’re calling the right version of SIF, the next issue I encountered was to do with certs. Specifically I got this error:

TerminatingError(New-SignedCertificate): "Cannot process argument transformation on parameter 'Signer'. Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Security.Cryptography.X509Certificates.X509Certificate2"."
Install-SitecoreConfiguration : Cannot process argument transformation on parameter 'Signer'. Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Security.Cryptography.X509Certificates.X509Certificate2".

This is due to the certificate for Sitecore 9.1 that has been installed. You can remove the certificate but then your Sitecore 9.1 install will break instead.

Alternatively add a “RootCertFilename” to the certificate definition:

# Install client certificate for xconnect
$certParams = @{
  Path = "$SCLocation\xconnect-createcert.json"
  CertificateName = "$prefix.xconnect_client"
  RootCertFileName = "SIF121Root"
}
Install-SitecoreConfiguration @certParams -Verbose

Certificate Error – Part 2

This error looks exactly the same as the error above but you’ve already added that Root Cert File Name, so what’s happening now.

Install-SitecoreConfiguration : Cannot process argument transformation on parameter 'Signer'. Cannot convert the
"System.Object[]" value of type "System.Object[]" to type
"System.Security.Cryptography.X509Certificates.X509Certificate2".
At C:\resourceFiles9.0\install.ps1:47 char:1
+ Install-SitecoreConfiguration @certParams -Verbose
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Install-SitecoreConfiguration

The error is saying that it expected to find 1 certificate but found many instead. Each time you run the script the number of thumbprints also keeps going up.

TBH I’m not overly certain what causes this as most of the time you get the one root cert and your done forever more. But somehow you get a second and then get you in a loop of repeatedly deleting certificates only to discover they still exist somewhere. You know it’s also not the certificate for the 9.1 install as the certificate has the new name you added to it.

For me the issue was although I had deleted them from my personal certificates, trusted root certificates, and even the c:\certificates folder they were being added to, what I needed to do was run this in powershell.

 Get-ChildItem -Path "cert:\LocalMachine\Root" | Where-Object { $_.subject -like "*SIF121Root*" }
  | Remove-Item

If your wanting to find out what certificates are installed on your machine you can run these

Get-ChildItem -Path "cert:\LocalMachine\Root" | Format-Table Subject, FriendlyName, Thumbprint
Get-ChildItem -Path "cert:\LocalMachine\My" | Format-Table Subject, FriendlyName, Thumbprint
Get-ChildItem -Path "cert:\CurrentUser\My" | Format-Table Subject, FriendlyName, Thumbprint

Make sure your config is actually correct

This one is really just my mistake. Multiple versions of Siteocore have meant rather than just having one “C:\reousrcefiles\” folder on my machine (as per instructions), I now have a few with the version post-fixed to the end. It only becomes apparent that the path in the install.ps1 file is wrong part way through the install process.

What I learnt at Sugcon 2019

This year Sugcon came to London which given that’s where I’m based is awesome for me. In total it was a 3 day conference starting with Sitecore Experience aimed more at marketers than developers. As a developer I only went to the 2 developer days, so for your benefit here’s a summary of everything I saw.

Day 1

Day 1 started with a keynote, sadly life got in the way and I missed the first few hours. I’m told it was good though.

After that the day was split into a mix of sessions in the big room for all and smaller break out sessions where you could pick 1 of 4 to attend.

JSS Immersion – Lessons learned and looking ahead with Anastasiya Flynn

To kick things off I went to a talk on JSS, mostly because JSS is a subject I know very little about. This was something that became even more apparent as the talk went on! At the end of it I came away with an appreciation that I need to invest some time in learning a lot more, but my other take away was a few links on things that will help me out if I ever try some React stuff.

https://www.styled-components.com

https://www.react-spring.io

PAAS It on: Learning’s from a year on Sitecore with Criss Titschinger

Criss works as a dev opps person and over the last year went on the journey of having a Sitecore 8.2 install upgraded to 9 using a fully cloud architecture in Azure.

Overall his experience sounded positive but he did have a few warnings from pain he experienced:

  • Beware of cold start up times with web apps. These can be a real performance hit, especially when Azure decides its going to move your web app instance
  • Web app slots share processing usage so when your warming one up, your live one is taking a hit. If you run on the edge of capacity, this will be an issue
  • Azure search is easy to install but it has a field limitation of 1000 to watch out for
  • Data migration in an upgrade takes a long time the second time. It took 9 days to migrate a years data from mongo! Only do it once.
  • Run your upgrade on clean instances and do the code in visual studio.
  • Web apps need to be on the premium service plan. The others are to weak
  • Use elastic pools for your database to save money. The microservice architecture introduces a LOT of new dbs which are going to cost money in azure resources. Most of the time they also don’t do that much so put them in a pool to share resources
  • Moving to 9 is going to increase hosting charges. Be honest with clients about it.

Day 2

On Day 2 I got to attend from the start so it was a much fuller day for me.

10x your Sitecore development with Mark Cassidy

The day started with a talk on questioning how long it should take to build a Sitecore site. It was a question that never really got answered but the main thing Mark really raised was, do we over engineer what we do and would simpler actually be enough? He went on to show a time lapse video of himself implementing a bootstrap template in Sitecore which took 15 hours.

To build this site he didn’t install any modules (no glass) and used just the standard Sitecore api. As he pointed out, it was all stuff that could be done by a dev with only the basic Sitecore training, which as there’s a short supply of devs in the world, we can potentially make better use of who does what.

Extending and implementing cloud architectures with Rob Habraken

After one talk on cloud the day before I almost gave this one a miss, but I’m glad I didn’t.

Rob gave us some of his learning’s and things to look out for. As the the previous session the theme of Sitecore 9 becoming far more complex came up and he had some interesting takes on it:

  • Use what you need, disable roles that you don’t. I see plenty of Sitecore customers not making use of all the features, and when your in a microservice architecture it does raise the question of why even have this stuff turned on. If you don’t use marketing automation then you don’t need the role running. It’s just costing money to do nothing.
  • Scale down when your not using resource. Unlike a VM web apps can not be turned off so they always cost money. You can delete and recreate, but that’s a pain. Instead set up a pipeline to scale them to the lowest resource setting when not being used.
  • He went on to discuss and show how we can use azure functions and logic apps to implement our code rather than building into the main Sitecore project. However you should be careful overdoing it as it can become complex quickly and it’s easy to end up with a massive unorganised list of individual azure functions.

Automated personalisation with Chris Nash and Niels Kuhnel

Chris and Niels pointed out the flaw in Sitecores reporting on personalised content. How do we know the rate each converts to a goal at? There’s the A/B Test report’s but that’s not quite the same thing.

They went on to show how they had started measuring the display impressions and click through on personalised content. Then linking the results collected in the reporting db up to a Power BI dashboard.

Sitecore identity: A new Sitecore authentication mechanism with Himadri Chakrabarti

Himadri gave us a look at the new Identity Server framework in Sitecore 9.1:

  • Identity server 4 framework
  • Still uses old asp net membership provider underneath
  • Can work with sub providers like Azure

Measure if you want to go faster with Jeremy Davis

Jeremy was in the situation where a site they were developing would have TV adverts during one of the most watch programs on British TV. Naturally he got scared and went looking for tools to help with performance. He told us about two of them:

  • Sitecore debug tool in experience editor showing the time it takes for components to load.
  • Using Visual Studio debugger to monitor processor usage and memory usage.

Both of these tools are very good at pointing you in the direction of smelly code and the best part is you already have them.

Unfortunately it’s the kind of demo that really doesn’t convert to text to write here.

We released JSS, you’ll never guess what happened next with Adam Weber & Kam Figy

Adam and Kam showed us JSS working with SXA and Sitecore Forms. As mentioned before I don’t know much about JSS but after this talk I’m convinced I definitely need to.

Right now it doesn’t sound like I would make a site using it, but it could definitely be the future of how we build sites.

The stand out thing is being able to keep your Sitecore install unmodified which would essentially lead us to a real SAAS solution where a Sitecore instance could be spun up from the marketplace and then all other functionality added through server-less functions and a headless front end.

What’s new in Sitecore 9.1

At this year’s Sitecore Symposium, Sitecore shared details of the great new features arriving in Sitecore 9.1 that will benefit everyone from developers to marketers, by offering enhancements in everything from machine learning to aid personalisation down to headless support for JavaScript developers.

Sitecore Cortex

Version 9 was the first introduction to Sitecore Cortex name, which is represents the machine learning capabilities found within Sitecore. In version 9 this was limited to Engagement Value, Optimisation and Path Analysis. Version 9.1 however is building on this base by introducing 3 new Cortex powered capabilities to the platform.

Personalisation Suggestions

Sitecore has been offering the ability to create personalised visitor experiences for a long time now, but half the challenge with this has always been knowing what you should personalise and how you should personalise it.

With Sitecore 9.1 you can now direct the results of content tests to be fed into the machine learning server. Sitecore will then analyse the results of the test and if certain segments responded better to one experience over another, if it did then it will suggest that is set up as a personalisation rule.

Content Tag Automation

Search engines and site searches work far better when content has been tagged correctly. However, tagging is a tedious task most content editors would rather do without. Sitecore 9.1 now helps content editors with this task by hooking into the Open Calais API for natural language processing of content-based fields on an item.

Headless Sitecore

At Symposium 2017, Sitecore announced Sitecore JavaScript Services as the first official step into supporting headless setups using Sitecore. Since then this has been available as a preview while the development continued. With Sitecore 9.1 this is now reaching general availability.

The Headless capabilities mean those working with popular frameworks such as Vue, React and Angular can now build rich applications using Sitecore as the backend without needing to write .net code.

Unlike other headless offerings, Sitecore Headless still retains the functionality that makes Sitecore great. Namely, tracking, optimisation, personalisation and there’s even previews in the Sitecore Experience Editor.

And more

These are just 2 of the stand out features coming in Sitecore 9.1, but as well as this there are;

  • Updates to EXM to help avoid spamming recipients while also being able to classify vital emails such as order confirmations to always be sent
  • Enhancements to Sitecore Forms and Marketing Automation that were introduced in Sitecore 9
  • Sitecore Experience Accelerator now supports WCAG 2.0 accessibility guidelines
  • Preview of Project Horizon, the next version of web content editing
  • Simplification of the installation process with SIF 2.0

How to add a table to content in Sitecore

Although most of my blog posts are aimed at developers, this one is really for a content editor. When we build sites and do all the checks to make sure they work well for SEO and hit AAA accessibility standards, it’s easy to forget that once we’re done the content editors are going to take over with the ability to destroy things 🙂 through the rich text editor.

Scenario

As a content editor you need to display some data in your article, and it makes most sense to put in a table.

Adding a table is actually quite straightforward in Sitecore, it’s not much different to doing it in Microsoft Word. You click the insert table button and choose the size you want. However the problem that often gets missed is accessibility. While a table is actually very good for a screen reader, it does need to have a bit of info on things like table headings. e.g. are the they top row, the first column or do they exist at all.

Solution

Adding heading information takes a bit of extra work, but not a lot.

  1. Add you table by clicking the Insert table button and choosing the size you want.
    Table - 1 Insert Table
  2. Fill in your tables content
    Table - 2 Enter Content
  3. Right click the table and select “Table Properties”
    Table - 3 Select Table Properties
  4. Go to the Accessibility tab and set the heading rows and columns. In this example I have set the first row and first column to be marked as headings.
    Table - 4 Set Table Headings
  5. Click on and your table will be updated. If your site has styles for table headings these will also show now too.
    Table - 5 Table Updated
  6. Switching to HTML view will also show the correct HTML tags now being used.
    Table - 6 Correct HTML

An alternative approach to this, is at step 1 to pick table wizard rather than picking the size of the table. This will open the same wizard as in step 4 and allow you to specify the size of the table here too.

API Routes stopped working in Sitecore 9

We recently undertook a Sitecore 9 upgrade and one issue we encountered was controllers we had set up for API routes stopped working on content delivery servers. Content management and single server setups were unaffected.

Our routes had been set up by the controllers inheriting from SitecoreController and then using the default route which Sitecore would create. e.g. /api/sitecore/foo/getFoo

public class FooController : SitecoreController
{
    ...
    [System.Web.Http.HttpPost]
    public ActionResult GetFoo(FooModel queryModel)
    {
        ...
    }
}

MVC.LegalRoutes

After a bit of investigation we found a new setting in Sitecore 9 called MVC.LegalRoutes. From the documentation:

MVC: Pipe separated list of route URL’s that are not valid for use with Sitecore.Mvc.
For instance, the default ASP.NET route ({controller}/{action}/{id}) catches most requests that are actually meant to be handled by the default Sitecore route.
Default: “{controller}/{action}/{id}”

If we added our route to the list everything started to work ok.

<setting name="Mvc.LegalRoutes" value="|Sitecore.Mvc:sitecore/shell/api/sitecore/{controller}/{action}|Sitecore.Mvc.Api:/api/sitecore/{controller}/{action}|" />

A different approach

Not wanting to just change random settings we stumble across we contacted Sitecore support to see what they thought.

The route ‘api/sitecore/{controller}/{action}’ is a pre-defined Sitecore SPEAK route for Sitecore Client usage. So when trying to access on a content delivery server where the Sitecore Client is disabled, it no longer works.

So to get around the issue we can start registering the route on content delivery servers through the Global.asax file.

public override void Application_Start(object sender, EventArgs args)
{
    base.Application_Start(sender, args);

    if (System.Configuration.ConfigurationManager.AppSettings["role:define"] == "ContentDelivery")
    {
        System.Web.Routing.RouteTable.Routes.MapRoute("Sitecore.Speak.Commands", "api/sitecore/{controller}/{action}");
    }
}

Sitecore SXA example site

Recently I’ve been looking into building sites using Sitecore Experience Accelerator (SXA). If you haven’t heard of it, in short SXA cut’s the amount of dev effort by building sites through pre-built re-usable components and then adding some styling. For a brochure type site this can (in some cases) remove virtually all the back end dev. You can read more about it here https://www.sitecore.com/en-gb/products/sitecore-experience-platform/wcm/experience-accelerators

Getting your head around SXA however can be a slight challenge. There is a getting started guide from Sitecore, which covers grid layouts, choosing features etc, but being able to understand how a site should actually be constructed and how the editor will use it can become confusing.

What would really help which Sitecore don’t provide is an example site. However Cognifide have and you can download it from Github here: https://github.com/Cognifide/Sitecore.XA.Showcase

To get started with it:

  1. Install a clean copy of Sitecore with SXA
  2. Download the code from github
  3. Restore the NuGet packages
  4. In the App_Config you will see a config file named Sitecore.XA.Project.Showcase.User.config. This includes one setting that needs updating to point to the folder you downloaded the solution to. This is then going to be used by unicorn to synchronize the items.
  5. Publish the solution into your Sitecore install
  6. Login as an admin and go to http://<yourinstancename>/unicorn.aspx
  7. Click the sync button, to synchronize the items
  8. Publish the site

You will now be able to see the showcase site in the admin and have a click through it on the published version.

SXA Showcase

What’s really great about the SXA showcase site is it’s a site all about SXA with loads of useful information on how you build an SXA site as well as actually be being built in SXA.

Sitecore – Creating an admin menu item

If your building a Sitecore admin application, your going to need to link to them from the Sitecore start screen/launch pad.

To create a menu item on Sitecores start screen:

  1. Log into Sitecore and switch to the core db
  2. Open content editor and navigate to /sitecore/client/Applications/Launch Pad/PageSettings/Buttons
  3. You will see groupings for each of the sections that appears on the start screen/launch pad
    Launchpad buttons
  4. Add a new Launch Pad-Button item to the section you want it to appear in
  5. Give it a name, icon and link
    Button details
  6. Your button now appears on the start screen
    New button

Related Posts

A first look at Sitecore SPEAK 3

Sitecore SPEAK 3 – Creating an application

At the end of last year I wrote a post on A first look at Sitecore SPEAK 3 which gave an overview of what Speak is, and the large architecture change that has happened between Speak 1/2 to 3.

In this post I’m going to share my experience on how to set up a Speak 3 application with Angular.

Step 1 – Creating the Angular project

To start your going to need a few things installed:

  • An IDE – I’m using VS Code
  • NodeJs – This is to get access to node package manager and to run your application in debug mode
  • Angular

If you don’t already have Node and Angular installed, I suggest going through Angular’s quick start guide. If your also new to Angular I suggest going through their Tour of Heroes tutorial first. This will give you a good understanding of how Angular applications are built and some knowledge around a few key files.

One you’ve got everything installed, create a new angular project from the command line.

ng new app-name

1 - Create Angular app

At this point you could try manually installing the various modules Sitecore provide, covering things like common components, logout functionality etc. However I personally found this a bit awkward. Unless you know what your doing your probably going to run into issues such as compatibility between the latest version of Angular and the Sitecore components (at time of writing Angular is on version 5 but Speak 3 only supports Angular 4).

Instead I would recommend downloading the sample application from https://dev.sitecore.net/Downloads/Sitecore_SPEAK/3/Sitecore_SPEAK_3.aspx and then copy over the .npmrc and package.json file to your solution.

By including these files, the .npmrc file will add a reference to Sitecores package repository and the package.json file will make sure the right packages and versions will be installed. Use npm to install the packages.

npm install

1 - Install NPM Packages

Next we need to update a couple of files in the application to reference some Sitecore specific bits. This is explained in Sitecores documentation, in my examples though I’ve also included referencing some modules that you are likely to use.

app.module.ts

The app module file defines the modules that are going to be used in the application. Here we need to add the references to the Sitecore modules.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { ScAccountInformationModule } from '@speak/ng-bcl/account-information';
import { ScActionBarModule } from '@speak/ng-bcl/action-bar';
import { ScApplicationHeaderModule } from '@speak/ng-bcl/application-header';
import { ScButtonModule } from '@speak/ng-bcl/button';
import { ScGlobalHeaderModule } from '@speak/ng-bcl/global-header';
import { ScGlobalLogoModule } from '@speak/ng-bcl/global-logo';
import { ScIconModule } from '@speak/ng-bcl/icon';
import { ScMenuCategory, ScMenuItem, ScMenuItemLink, ScMenuModule } from '@speak/ng-bcl/menu';
import { ScTableModule } from '@speak/ng-bcl/table';
import { ScPageModule } from '@speak/ng-bcl/page';
import { CONTEXT, DICTIONARY } from '@speak/ng-bcl';
import { NgScModule } from '@speak/ng-sc';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    ScAccountInformationModule,
    ScActionBarModule,
    ScApplicationHeaderModule,
    ScButtonModule,
    ScGlobalHeaderModule,
    ScGlobalLogoModule,
    ScIconModule,
    ScPageModule,
    ScMenuModule,
    ScTableModule,
    NgScModule.forRoot({
      contextToken: CONTEXT, // Provide Sitecore context for SPEAK 3 Components (optional)
      dictionaryToken: DICTIONARY, // Provide translations for SPEAK 3 Components (optional)
      translateItemId: '0C979B7C-077E-4E99-9B15-B49592405891', // ItemId where your application stores translation items (optional)
      authItemId: '1BC79B7C-012E-4E9C-9B15-B4959B123653' // ItemId where your application stores user access authorization (optional)
    })
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts

The component file needs updating to call init on the ngScService.

import { Component, OnInit  } from '@angular/core';
import { NgScService } from '@speak/ng-sc';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  constructor(
    private ngScService: NgScService
  ) {}

  ngOnInit() {
    this.ngScService.init();
  }
}

.angular-cli.json

In the angular-cli.json file you will see a styles section which references the main css file in the solution. Here you will need to add an additional reference to Sitecores css file.

../node_modules/@speak/styling/dist/styles/sitecore.css

Launch

You can now launch your application from the command line and see the default start screen.

ng serve --open

Step 2 – Building your application

It’s not time to start building your application. If you don’t know Angular I suggest going through a couple of tutorials, and go from there. I’m not going to go into any details about how Angular apps are and should be written, but I am going to go through a few of the Sitecore controls needed to make an application that fit’s the Sitecore admin.

Example Page


To make this page first I cleared out everything from app.component.html and started adding some Sitecore components. Normally you would start generating your own components to represent things like pages, but for the purposes of the example I placing everything in the one file.

To start I have a sc-page containing a header. This comes out of Sitecores demo application and will give you the standard bar that sites at the top of the Sitecore admin, informing users where they are.


<div>
    
      <a href="#"></a>
      <!-- AccountInformation gets accountName and accountImageUrl automatically from Sitecore context which is configured in AppModule -->
      
    </div>

To create the menu I’m using an sc-menu. Notice how some items are marked as active.


<aside>
    
      
        
          <a>Menu item 1</a>
        
        
          <a>Menu item 2</a>
        
      
      
        
          <a>Menu item 3</a>
        
        
          <a>Menu item 4</a>
        
      
    
  </aside>

Lastly to create the main content of the page I’m using a scPageAppHeader, scPageContent and an scTable for the table.

<div>
    </div>
<article>
<table>
<thead>
<tr>
<th>Name</th>
<th>Status</th>
<th>Created by</th>
<th>Created data</th>
</tr>
</thead>
<tbody>
<tr>
<td>Lorem</td>
<td>Active</td>
<td>sitecore\admin</td>
<td>Jan 20, 2018</td>
</tr>
<tr>
<td>Ipsum</td>
<td>Active</td>
<td>sitecore\admin</td>
<td>Jan 20, 2018</td>
</tr>
<tr>
<td>Foop</td>
<td>Inactive</td>
<td>sitecore\admin</td>
<td>Jan 22, 2018</td>
</tr>
</tbody>
</table>
</article>


The complete code looks like this:


<div>
    
      <a href="#"></a>
      <!-- AccountInformation gets accountName and accountImageUrl automatically from Sitecore context which is configured in AppModule -->
      
    </div>
<aside>
    
      
        
          <a>Menu item 1</a>
        
        
          <a>Menu item 2</a>
        
      
      
        
          <a>Menu item 3</a>
        
        
          <a>Menu item 4</a>
        
      
    
  </aside>
<div>
    </div>
<article>
<table>
<thead>
<tr>
<th>Name</th>
<th>Status</th>
<th>Created by</th>
<th>Created data</th>
</tr>
</thead>
<tbody>
<tr>
<td>Lorem</td>
<td>Active</td>
<td>sitecore\admin</td>
<td>Jan 20, 2018</td>
</tr>
<tr>
<td>Ipsum</td>
<td>Active</td>
<td>sitecore\admin</td>
<td>Jan 20, 2018</td>
</tr>
<tr>
<td>Foop</td>
<td>Inactive</td>
<td>sitecore\admin</td>
<td>Jan 22, 2018</td>
</tr>
</tbody>
</table>
</article>


To avoid some build errors later on we also need to update the app.components.ts file (think of this as a code behind file), to have an additional property and service.

import { Component, OnInit  } from '@angular/core';
import { NgScService } from '@speak/ng-sc';
import { SciLogoutService } from '@speak/ng-sc/logout';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  isNavigationShown = false;

  constructor(
    private ngScService: NgScService,
    public logoutService: SciLogoutService
  ) {}

  ngOnInit() {
    this.ngScService.init();
  }
}

How to find more components

Unfortunately the Sitecore documentation doesn’t currently contain a list of what’s available. However if you look in your node_modules folder there is a change log containing information on each component here \node_modules\@speak\ng-bcl\CHANGELOG.md.

Step 3 – Publishing the application

Once you’ve built the application you need to publish it and copy it into Sitecore.

There are some differences in the way a Speak 3 Angular application needs to work which differ from the normal way an Angular application runs. Among others these include having an index.apsx page rather than an index.html and the application not being located in the root of a site. You can read more about this in Sitecores documentation. The good news though is Sitecore have provided a post build step to sort this out for you.

If you copied the package.json file at the beginning this will already be set up, one thing you do need to do though is update the base location to be where your application is going to live.

Once this is done you can run a build.

npm run-script build

Note this is using npm to run the build script from the packages.json file rather than doing a regular ng build from Angulars CLI.

If all succeeds your dist folder will now contain a compiled version of the application.

Copy these files into the destination folder in your Sitecore site. For me this is \sitecore\shell\client\Applications\Speak-Example. You should now be able to log in and view your application.

Notice the logout button now functions and the current user is displayed in the top right. The menu sections are also collapsible, but other than that our application doesn’t actually do anything.

Moving on from this there’s lot’s more to cover on building out the functionality in the application and you may have also noticed in the app.module.ts file a reference for translations which I never created, but this should be enough to get anyone started with building an Angular Speak 3 project and then publishing it into Sitecore.

Related Links

Speak 3 Official documentation
Speak 3 Downloads

Sitecore Alias as Redirect

One feature of Sitecore that I have always disliked is Alias’s. On each page of a site, content editors have the ability to click an alias button on the presentation tab and add alternative urls for the page.

Alias Toolbar

Once added these will appear in the Aliases folder under system.

Alias

However all this accomplishes is multiple URLs existing for one page which is a big SEO no no.

Content editors like to do this in order to create simple URLs for things like landing pages. e.g. himynameistim.com/Sitecore but search engines hate it as they see multiple pages with the exact same content. As a result the value of each page gets lowered and appears lower in search engine results. What Content editors really want is to set up a 301 redirect so that they can have the simple URL but redirect users to the actual page on the site.

Aliases as Redirects

One solution is to updated the aliases functionality to cause a redirect to it’s linked item rather than resolve the page.

To do this we need to create a pipeline processor that inherits from AliasResolver.

using Sitecore;
using Sitecore.Configuration;
using Sitecore.Diagnostics;
using Sitecore.Pipelines.HttpRequest;
using System.Net;
using System.Web;
using AliasResolver = Sitecore.Pipelines.HttpRequest.AliasResolver;

namespace HiMyNameIsTim.Pipelines
{
    public class AliasAsRedirectResolver : AliasResolver
    {
		public override void Process(HttpRequestArgs args)
		{
			if (!Settings.AliasesActive)
			{
				return; // if aliases aren't active, we really shouldn't confuse whoever turned them off
			}

			var database = Context.Database;

			if (database == null)
			{
				return; // similarly, if we don't have a database, we probably shouldn't try to do anything
			}

			if (!Context.Database.Aliases.Exists(args.LocalPath))
			{
				return; // alias doesn't exist
			}

			var targetID = Context.Database.Aliases.GetTargetID(args.LocalPath);

			// sanity checks for the item
			if (targetID.IsNull)
			{
				Tracer.Error("An alias for \"" + args.LocalPath + "\" exists, but points to a non-existing item.");
				return;
			}
			var item = args.GetItem(targetID);

			if (database.Aliases.Exists(args.LocalPath) && item != null)
			{
				if (Context.Item == null)
				{
					Context.Item = item;
					Tracer.Info(string.Concat("Using alias for \"", args.LocalPath, "\" which points to \"", item.ID, "\""));
				}

				HttpContext.Current.Response.RedirectLocation = item.Paths.FullPath.ToLower()
					.Replace(Context.Site.StartPath.ToLower(), string.Empty);
				HttpContext.Current.Response.StatusCode = (int)HttpStatusCode.MovedPermanently;
				HttpContext.Current.Response.StatusDescription = "301 Moved Permanently";
				HttpContext.Current.Response.End();
			}
		}
    }
}

And patch in in place of the regular Alias Resolver.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <httpRequestBegin>
        <processor type="HiMyNameIsTim.Core.Pipelines.AliasAsRedirectResolver, LabSitecore.Core" 
                   patch:instead="*[@type='Sitecore.Pipelines.HttpRequest.AliasResolver, Sitecore.Kernel']"/>
      </httpRequestBegin>
    </pipelines>
  </sitecore>
</configuration>

The above code is adapted from a solution given by Jordan Robinson but with a bug fixed to stop every valid URL without an alias writing an error to the log file.

Using compile options for version compatibility

Here’s the scenario; Your building a module and it needs to be compatible with different versions of a platform. e.g. Sitecore, and everything’s great up until the day you need to call different methods in different versions of the platform. You’d rather not drop support for the old versions, and nor do you want to start maintaining two code bases. So what do you do?

C# Preprocessor Directives

Preprocessor directives provide a way to give the compiler instructions to follow while its compiling a project. By using this we can give the compiler conditions to compile different versions in different ways. Thereby allowing us to maintain one codebase, but produce compilations for different versions of the platform. e.g. One for Sitecore 8.0 and another for Sitecore 9.0.

#if, #else and #endif

When the compiler encounters an #if followed by an #endif, it will only compile the code between the two if the specified symbol had been defined.

#if DEBUG
    Console.WriteLine("Debug version");
#else
    Console.WriteLine("Non Debug version");
#endif

Defining a preprocessor symbol

For the if statement to work, your going to need to define your symbol which is being evaluate.

This can be included in code as follows

#define YOURSYMBOL

A more useful was of defining this however is to include it in your call to MSBuild (this is particularly useful when using a build server).

-define:name[;name2]

If your compiling from Visual Studio an easier solution is to set up a new build configuration with a conditional compilation symbol.

  1. Right click your solution item in Solution Explorer and select Properties
  2. Click Configuration Properties on the left and then Configuration Manager on the right
  3. In the pop up window click the Active solution configuration drop down and then click New
    BuildConfiguration
  4. Enter the name of the build config. In my example above I have SC82 for Sitecore 8.2 and SC90 for Sitecore 9.0.
  5. Click Ok and close all the windows you just opened
  6. Right click the project that your going to build and select Properties
  7. Select the Build tab
  8. Select your build configuration from the configuration at the top
  9. Enter the symbol your using for the #if directives
    Conditional Compilation Symbols

Reference different versions of an assembly

Adding conditions to our code is good, but for this to fully work we also need to reference different versions of the assemblies that are causing the issue in the first place.

There’s no way of doing this through Visual Studio but by editing the .csproj file manually we can update the hint path on a reference to include the configuration name as a variable.

    
       ..\libraries\$(Configuration)\Sitecore.Kernel.dll
      False
    

This example shows how different versions of the Sitecore Kernel can be referenced by keeping each version in a subfolder that corresponds with the build configuration name.

As well as different versions of assemblies, it may also be needed to target different versions of the .net framework. This can be done in the .csproj file by including additional proerty groups that have a condition on the configuration name.

  
    bin\SC82\
    TRACE;SC82
    true
    v4.5.2
  
  
    bin\SC90\
    TRACE;SC90
    true
    v4.6.2
  

In this example I’m targeting .net 4.5.2 for my Sitecore 8.2 configuration and 4.6.2 for my Sitecore 9 configuration.

Useful Links

C# preprocessor directives
-define (C# Compiler Options)