In my last post, I showed how we can enable the Authoring and Management API and obtain a valid access token from the Sitecore Identity Server. In this post I will continue to use the Authoring and Management API to get a list of running job from Sitecore. Using this list, I have created a custom Sitecore job viewer as a standalone WinForm application.
Introduction
The Authoring and Management API is new GraphQL endpoint in Sitecore 10.3 that give access to authoring and management operations (like creating items, rebuilding indexes and publishing content). Sitecore provides examples queries for the different operation supported by the API here and here, and with a little knowledge of GraphQL, the endpoints are fairly straightforward to use.
However, as I explained in my last post, the endpoint needs an access token for authorization, which we must obtain from the Sitecore Identity Server. In my last post I used a password credentials flow with the existing Password
client (with the client id SitecorePassword
) to request an access token.
When we start developing actual client applications, we might want to create a dedicated client in the Sitecore Identity Server’s configuration. We can use one of the existing clients in sitecore\Sitecore.Plugin.IdentityServer\Config\identityServer.xm
l as a template. The file contains both the SitecorePassword
client using password credentials flow and a commented out client with the client name SitecoreCredentials
using the client credentials flow (see my last post for an introduction to these two ways of authorizing). Please notice that the XML node containing a client and the name of the client are not the same, so e.g. the SitecorePassword
client is contained in a node called PasswordClient
.
When setting up a client, be aware that Sitecore Identity Server uses layered configurations, with sitecore\Sitecore.Plugin.IdentityServer\Config\identityServer.xml
being the base file, and the Config\Sitecore.IdentityServer.Host.xml
and Config\production\Sitecore.IdentityServer.Host.xml
(and other configuration files) being added on “top of it”. So e.g. the
client is configured in the base file, but the client secret is set in the production configuration.SitecorePassword
In this post I will simply continue using the SitecorePassword
client, and the matching client secret that comes OOTB with a Sitecore installation, but if you wish to register at dedicated client, you can see how to do it in my video.
Building a job viewer
Sitecore comes with a job viewer (/sitecore/admin/Jobs.aspx
), but it is a bit simple. So to build a alternative tool, I have used the Authoring and Management API to get a list of running Sitecore jobs.
My job viewer is a standalone WinForms application that queries the API with a fixed time interval (every 2 seconds) and display information about current and past jobs over a period of time (the last 200 seconds). You can download the my job viewer from my GitHub.
The benefit of using an standalone application and the Authoring and Management API is that no changes needs to be done on the Sitecore XM server (except for enabling the Authoring and Management API as described in my last post). So in theory you can attach to any Sitecore instance, provided that by can obtain a valid access token.
The user interface
In the top of the job viewer you find a Attach/Detach button (1), as well as text boxes for user name and password or – as an alternative – a text box for entering a valid access token (2).
Underneath, my job viewer contains a graph that shows the number of jobs in the 200 seconds period sorted by status (3). A second graph shows the individual jobs in the same period (4). Notice that Sitecore jobs has a “after-life”, which means that after they have completed, they hang around for a short time having the state FINISHED
, shown as a light blue bar trailing the yellow period of being in the RUNNING
state.
The list in the bottom of the UI shows the current list of jobs as reported by Sitecore, and is equivalent to the build in job viewer (5).
Configuring the job viewer
In the app.config of my job viewer we need to configure a few settings:
<add key="Server" value="your-server"/>
<add key="IdentityServer" value"your-identity-server"/>
<add key="ClientId" value="SitecorePassword"/>
<add key="ClientSecret" value="your-client-secret"/>
<add key="MaxJobs" value="18"/>
As you can see, we need the server to which to attach. If we want to use user name and password for authorization, we will also need the URL to the Sitecore Identity Server as well as the client id and client secret as set up on the Sitecore Identity Server’s configuration files. On my local test environments, these settings looks like this:
<add key="Server" value="https://sc103xmcm.dev.local" />
<add key="IdentityServer" value="https://sc103identity.dev.local" />
<add key="ClientId" value="SitecorePassword" />
<add key="ClientSecret" value="my-secret" />
<add key="MaxJobs" value="18" />
The code
Appart for the logic around the UI, the job viewer contains two important services: The Services/AccessTokenService.cs
is used to obtain the access token from the Sitecore Identity Server. As you can see I am more or less using the exact same approach as in my last post, except that I am using the latest version of IdentityModel
(6.1.0) instead of the version that is part of Sitecore (3.10.10).
The querying of the Authoring and Management API is done in the Services/GraphQLService.cs
. I am using the GraphQL.Client
to perform the operation. It is one of the many clients available for calling a GraphQL endpoint. The query I am using in configured in the Constants.cs
file, and looks like this:
public static GraphQLRequest GetJobsRequest = new GraphQLRequest
{
Query = @"query {
jobs(input: { jobName: ""*"" })
{
nodes {
name
handle
status {
processed
jobState
}
done
}
}
}"
};
I am using NewtonSoft to deserialize the response into an object (Models/GetJobsResponse.cs
). The latter file has been modelled after the JSON response as described in Sitecores documentation:
{
"data": {
"jobs": {
"nodes": [
{
"name": "Index_Update_IndexName=sitecore_master_index",
"handle": "970372d7-df5a-418f-a603-d6c0b40ed52c;2AD160A8BF9F-Default Web Site",
"status": {
"processed": 1578,
"jobState": "RUNNING"
},
"done": false
},
{
"name": "Index_Update_IndexName=sitecore_core_index",
"handle": "b009bb91-aeae-4d86-86b5-fac785f1861d;2AD160A8BF9F-Default Web Site",
"status": {
"processed": 307,
"jobState": "RUNNING"
},
"done": false
}
]
}
}
}
Notice that the data
wrapper object is part of the general GraphQL response structure, and is not considered part of the actual response payload, so it should not be part of the model used for deserialization (the actual response as presented by the GraphQL.Client
client is the jobs
object inside the data
wrapper).
The rest of the code is simply the UI, and fairly straightforward WinForms application code.
Of course the job viewer can be extended with more features, but hopefully it will offer a start for exploring the possibilities given by the Authoring and Management API and to consume the API in C# code.