Sitecore
API Routes stopped working in Sitecore 9

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

1public class FooController : SitecoreController
2{
3 ...
4 [System.Web.Http.HttpPost]
5 public ActionResult GetFoo(FooModel queryModel)
6 {
7 ...
8 }
9}

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.

1<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.

1public override void Application_Start(object sender, EventArgs args)
2{
3 base.Application_Start(sender, args);
4
5 if (System.Configuration.ConfigurationManager.AppSettings["role:define"] == "ContentDelivery")
6 {
7 System.Web.Routing.RouteTable.Routes.MapRoute("Sitecore.Speak.Commands", "api/sitecore/{controller}/{action}");
8 }
9}
Sitecore SXA example site

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.

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

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:

  • Log into Sitecore and switch to the core db
  • Open content editor and navigate to /sitecore/client/Applications/Launch Pad/PageSettings/Buttons
  • You will see groupings for each of the sections that appears on the start screen/launch pad
  • Add a new Launch Pad-Button item to the section you want it to appear in
  • Give it a name, icon and link
  • Your button now appears on the start screen
Sitecore SPEAK 3 - Creating an application

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.

1ng new app-name

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.

1npm install

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.

1import { 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.

1import { 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.

1../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.

1ng 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.

1<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.

1<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.

1<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:

1<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.

1import { 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.

1npm 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