How to add a minimally configured Web API to Sitecore XM/XP 10.2
Tags: sitecore, aspnet
Published: 2022-08-19 07:46:04

There are many situations where you may want to use data stored in Sitecore XM or XP on an external site, and this step-by-step guide explains how to add a customized Web API on Sitecore XM/XP 10.2.

# System Requirements
- Visual Studio 2019 or higher (The author's environment is Visual Studio 2022)
- NET Framework 4.8
- Windows 10
- Sitecore XM/XP 10.2

# Target audience
- Sitecore Developers

# Preparation
## Add Sitecore to NuGet package sources
Open Visual Studio configuration.
![](https://storage.googleapis.com/zenn-user-upload/f053b0886d44-20220819.png)

1. select Package Sources
2. click on +
3. Select the added Package srouces
4. Enter `Sitecore` for Name and `https://sitecore.myget.org/F/sc-packages/api/v3/index.json` for Source
5. Click `Update`
6. Click `OK`.
![](https://storage.googleapis.com/zenn-user-upload/2f1796e22c88-20220819.png)

That's all.

# Complete Repository
Here is the completed source so you can build and try it out right away.
https://github.com/nnasaki/SimpleWebApi

# Steps to create a new solution
## Create new solution

![](https://storage.googleapis.com/zenn-user-upload/eb9102f2e587-20220819.png)

Select `ASP.NET Web Application(.NET Framework)`, note that it is not ASP.NET Core.
![](https://storage.googleapis.com/zenn-user-upload/6f377d2cef4f-20220819.png)

Enter the Project name. Make sure again that the Framework is `.NET Framework 4.8`.
![](https://storage.googleapis.com/zenn-user-upload/b425d17ef0d0-20220819.png)

Select `Empty` as the Project Type. Uncheck all the checkboxes on the right side.
![](https://storage.googleapis.com/zenn-user-upload/fd819f250d8b-20220819.png)

Press `Create` to finish creating a new solution and project.
![](https://storage.googleapis.com/zenn-user-upload/27ed455e02af-20220819.png)

## Add a NuGet package
From Visual Studio `Tools`, click `Package Manager Console` under `Nuget Package Manager`.
![](https://storage.googleapis.com/zenn-user-upload/24e194e1d86b-20220819.png)

When the `Package Manager Console` appears at the bottom of the screen, type `Install-Package Sitecore.Services.Infrastructure` !
[](https://storage.googleapis.com/zenn-user-upload/23547733c82a-20220819.png)

If you see `Successfully installed` like this, it is successful. It took about 2 minutes in my environment.
![](https://storage.googleapis.com/zenn-user-upload/503e90ab549e-20220819.png)

## Add controllers
Add a folder of `Controllers` and add a class
![](https://storage.googleapis.com/zenn-user-upload/34e9f562318a-20220819.png)

Enter `SimpleWebApiController` and click Add 
![](https://storage.googleapis.com/zenn-user-upload/d27ecfbc9807-20220819.png)

Enter the following code
```csharp
using Sitecore.Services.Infrastructure.Web.Http;
using System.Web.Http;
using System.Web.Http.Cors;

namespace SimpleWebApi.Controllers
{
    // TODO Be sure to narrow down the CORS settings in the production environment. This is all allowed.
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    public class SimpleWebApiController : ServicesApiController
    {
        public SimpleWebApiController()
        {
        }

        [HttpGet]
        public string Stats()
        {
            return "ok SimpleWebApi";
        }
    }
}
```

## Add route definition
Same procedure as for the controller. Add the `Pipelines` folder and add the `RegisterHttpRoutes` class.

Enter the following code
```csharp
using System.Web.Http;
using Sitecore.Pipelines;

namespace SimpleWebApi.Pipelines
{
    public class RegisterHttpRoutes
    {
        public void Process(PipelineArgs args)
        {
            GlobalConfiguration.Configure(Configure);
        }
        protected void Configure(HttpConfiguration configuration)
        {
            var routes = configuration.Routes;
            routes.MapHttpRoute("SimpleWebApi.stats", "api/simplewebapi/stats", new
            {
                controller = "SimpleWebApi",
                action = "Stats"
            });

        }
    }
}
```

## Add config.
Create a hierarchical folder `App_Config\Include\ZZZZZ_CustomConfigs` and add `SimpleWebApi.config`.
![](https://storage.googleapis.com/zenn-user-upload/956dbe8fbbc7-20220819.png)

Enter the following settings
````
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"
			   xmlns:set="http://www.sitecore.net/xmlconfig/set/"
			   xmlns:role="http://www.sitecore.net/xmlconfig/role/">
  <sitecore>
    <pipelines>
      <initialize>
        <processor
           type="SimpleWebApi.Pipelines.RegisterHttpRoutes, SimpleWebApi" />
      </initialize> 
    </pipelines>
  </sitecore>
</configuration>
```

## Deploy
Deploy the built module
### Add dll to bin
Copy the `SimpleWebApi.dll` created in the project `bin` to `C:\inetpub\wwwroot\sitecoresc.dev.local\bin` in IIS. Rewrite the `sitecoresc.dev.local` part in your environment.
! [](https://storage.googleapis.com/zenn-user-upload/ca257d9e4861-20220819.png)

### Add configurations to include
Copy `SimpleWebApi.config` added to the project to `C:\inetpub\wwwroot\sitecoresc.dev.local\App_Config\Include\ZZZZZ_CustomConfigs`.
![](https://storage.googleapis.com/zenn-user-upload/22cb2b397f05-20220819.png)

# Check the operation
## Access the API
Access the site where Sitecore is deployed using a browser.
In this example, access `https://sitecoresc.dev.local/api/simplewebapi/stats` and check it.

If the deployment is successful, you will see a simple `"ok SimpleWebApi"` as shown below.
![](https://storage.googleapis.com/zenn-user-upload/bf2be6dbcf00-20220819.png)

If you encounter errors, please see Troubleshooting.

# Summary
As shown in this article, Sitecore can be easily customized, so please try it out.

# Troubleshooting
Here is a summary of the errors I encountered while trying it out and how I handled them.

## No type was found that matches the controller named 'MinimumTest4'
### Error details.
````
{"Message": "No HTTP resource was found that matches the request URI 'https://sitecoresc.dev.local/api/minimumtest4/stats'." , "MessageDetail": "No type was found that matches the controller named 'MinimumTest4'"}
```
![](https://storage.googleapis.com/zenn-user-upload/95fde7408b22-20220819.png)
### Solution.
There are two patterns.
#### 1. Controller name is incorrectly set in MapHttpRoute.
Please check if the controller name is correct. If `MinimumTest4Controller` is the controller name, specify up to `MinimumTest4` without `Controller`.
![](https://storage.googleapis.com/zenn-user-upload/2da6703ce68a-20220819.png)

#### 2. optimizeCompilations="true" is enabled in Web.config
In Web.config, set `<compilation defaultLanguage="c#" debug="true" targetFramework="4.8" optimizeCompilations="true">` like this If `optimizeCompilations` is `true`, set `optimizeCompilations="false"`.

`optimizeCompilations` is a feature that can speed up reloading when updating modules, but new pipeline processors may not be recognized. It is usually better to set it to `false`.

## A route named 'MinimumTestApi.stats' is already in the route collection. Route names must be unique.
### Error details.
````
Server Error in '/' Application.
A route named 'MinimumTestApi.stats' is already in the route collection.
Parameter name: name
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ArgumentException: A route named 'MinimumTestApi.stats' is already in the route collection.
Parameter name: name

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
```

![](https://storage.googleapis.com/zenn-user-upload/7d1bdc143317-20220819.png)

### Solution
The definition name of `MapHttpRoute` is shared by another module. Change the definition name of `MapHttpRoute` in `RegisterHttpRoutes.cs`.
![](https://storage.googleapis.com/zenn-user-upload/54fd16b449d9-20220819.png)

## "Multiple types were found that match the controller named 'MinimumTestApi'
### Error Details.
```
{"Message": "An error has occurred.", "ExceptionMessage": "Multiple types were found that match the controller named 'MinimumTestApi'. This can happen if the route that services this request ('api/minimumtest3/stats') found multiple controllers defined with the same name but differing namespaces, which is not supported. \r\n\r\nThe request for 'MinimumTestApi' has found the following matching Controllers:\r\nMinimumTest.Controllers.MinimumTestApiController\r\nMinimumTest.Controllers.MinimumTestApiController", "ExceptionType": "System.InvalidOperationException", "StackTrace":""   at System.Web.Http.Dispatcher.DefaultHttpControllerSelector.SelectController(HttpRequestMessage request)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()"}
```
![](https://storage.googleapis.com/zenn-user-upload/830414c2e16f-20220819.png)
### Solution.
Name resolution is not working because there is a duplicate controller class name with another module. Change the controller class name to something else.