Skip to content

Instantly share code, notes, and snippets.

@jbreuer
Created February 19, 2025 10:37
Show Gist options
  • Save jbreuer/06727609ba65444ecdd7254ca9032668 to your computer and use it in GitHub Desktop.
Save jbreuer/06727609ba65444ecdd7254ca9032668 to your computer and use it in GitHub Desktop.
Updating Sitecore using the Authoring API and updating Umbraco with the Management API
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using IdentityModel.Client;
var builder = WebApplication.CreateBuilder(args);
// Register necessary services
builder.Services
.AddLogging(logging => logging.AddConsole())
.AddHttpClient();
var app = builder.Build();
// -------------------------------------------------------------------------
// Configuration - Sitecore
// -------------------------------------------------------------------------
string sitecoreIdentityServer = "https://sitecore-id-server.dev.local/";
string sitecoreClientId = "SitecorePassword";
string sitecoreClientSecret = "sitecore-client-secret";
string sitecoreUserName = @"sitecore\admin";
string sitecoreUserPass = "b";
string sitecoreGraphQLEndpoint = "https://sitecore-cm-server.dev.local/sitecore/api/authoring/graphql/v1";
string sitecoreFaqItemId = "{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}";
// -------------------------------------------------------------------------
// Endpoint: Receive Umbraco Webhook -> Update Sitecore
// -------------------------------------------------------------------------
app.MapPost("/api/webhooks/umbraco", async (HttpContext context, ILogger<Program> logger) =>
{
// 1) Read the raw JSON body
var doc = await context.Request.ReadFromJsonAsync<JsonDocument>();
// 2) Parse JSON for the "FAQ" data
// Fields are in:
// properties.title
// properties.text.markup
string? title = null;
string? textMarkup = null;
var root = doc.RootElement;
// Title
if (root.TryGetProperty("properties", out var propsElem) &&
propsElem.TryGetProperty("title", out var titleElem))
{
title = titleElem.GetString();
}
// Text markup
if (propsElem.TryGetProperty("text", out var textElem) &&
textElem.TryGetProperty("markup", out var markupElem))
{
textMarkup = markupElem.GetString();
}
// 3) Update Sitecore using the parsed fields
var httpFactory = context.RequestServices.GetRequiredService<IHttpClientFactory>();
// (a) Get a token from Sitecore Identity
var sitecoreToken = await GetSitecoreTokenAsync(
httpFactory,
sitecoreIdentityServer,
sitecoreClientId,
sitecoreClientSecret,
sitecoreUserName,
sitecoreUserPass);
// (b) Define a GraphQL mutation that uses two variables: $title and $text
// We pass them into fields: [ { name:"Title", value: $title }, ... ].
var mutation = $@"
mutation UpdateItem($title: String, $text: String) {{
updateItem(
input: {{
itemId: ""{sitecoreFaqItemId}""
fields: [
{{ name: ""Title"", value: $title }},
{{ name: ""Text"", value: $text }}
]
}}
) {{
item {{
name
}}
}}
}}";
// (c) Build a request object with the query and variables
var reqPayload = new
{
query = mutation,
variables = new
{
title,
text = textMarkup
}
};
// (d) Serialize to JSON
var client = httpFactory.CreateClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", sitecoreToken);
var reqJson = JsonSerializer.Serialize(reqPayload);
var content = new StringContent(reqJson, Encoding.UTF8, "application/json");
// (e) Send the POST to Sitecore GraphQL
var response = await client.PostAsync(sitecoreGraphQLEndpoint, content);
var responseBody = await response.Content.ReadAsStringAsync();
logger.LogInformation("Sitecore item updated successfully");
return Results.Ok("Umbraco data used to update Sitecore successfully!");
});
// -----------------------------------------------------------------------
// Helper: Acquire a token from Sitecore Identity (Password Grant)
// -----------------------------------------------------------------------
static async Task<string?> GetSitecoreTokenAsync(
IHttpClientFactory httpFactory,
string identityServer,
string clientId,
string clientSecret,
string userName,
string userPass)
{
using var tokenClient = httpFactory.CreateClient();
tokenClient.BaseAddress = new Uri(identityServer);
var req = new PasswordTokenRequest
{
Address = "/connect/token",
ClientId = clientId,
ClientSecret = clientSecret,
GrantType = IdentityModel.OidcConstants.GrantTypes.Password,
Scope = "openid sitecore.profile sitecore.profile.api",
UserName = userName,
Password = userPass
};
var resp = await tokenClient.RequestPasswordTokenAsync(req);
return resp.AccessToken;
}
// -------------------------------------------------------------------------
// Configuration - Umbraco
// -------------------------------------------------------------------------
string umbracoHost = "https://localhost:44392";
string umbracoClientId = "umbraco-back-office-my-client";
string umbracoClientSecret = "umbraco-client-secret";
string umbracoFaqDocId = "e75d2a2b-295c-48e6-bea0-f83c5100682b";
string umbracoTitleAlias = "title";
string umbracoTextAlias = "text";
// -------------------------------------------------------------------------
// Endpoint: Receive Sitecore Webhook -> Update Umbraco
// -------------------------------------------------------------------------
app.MapPost("/api/webhooks/sitecore", async (HttpContext context, ILogger<Program> logger) =>
{
// 1) Read the raw JSON body
var doc = await context.Request.ReadFromJsonAsync<JsonDocument>();
// 2) Parse JSON for Title/Text. You can get it from:
// - "Item.VersionedFields"
string? titleFromSitecore = null;
string? textFromSitecore = null;
// Look in "VersionedFields" array
if (doc.RootElement.TryGetProperty("Item", out var itemElem) &&
itemElem.TryGetProperty("VersionedFields", out var versionedFieldsElem) &&
versionedFieldsElem.ValueKind == JsonValueKind.Array)
{
foreach (var fieldElem in versionedFieldsElem.EnumerateArray())
{
if (!fieldElem.TryGetProperty("Id", out var fieldIdElem)) continue;
var fieldId = fieldIdElem.GetString() ?? string.Empty;
// Title field
if (fieldId.Equals("75577384-3c97-45da-a847-81b00500e250", StringComparison.OrdinalIgnoreCase))
{
if (fieldElem.TryGetProperty("Value", out var valElem))
{
titleFromSitecore = valElem.GetString();
}
}
// Text field
else if (fieldId.Equals("a60acd61-a6db-4182-8329-c957982cec74", StringComparison.OrdinalIgnoreCase))
{
if (fieldElem.TryGetProperty("Value", out var valElem))
{
textFromSitecore = valElem.GetString();
}
}
}
}
// 3) Update Umbraco using the parsed fields
var httpFactory = context.RequestServices.GetRequiredService<IHttpClientFactory>();
// (a) Acquire an Umbraco token (Client Credentials)
var umbracoToken = await GetUmbracoTokenAsync(httpFactory, umbracoHost, umbracoClientId, umbracoClientSecret);
// (b) Build the JSON for the Umbraco PUT
// We'll update "title" and "text".
var valuesList = new List<object>();
if (!string.IsNullOrEmpty(titleFromSitecore))
{
valuesList.Add(new
{
alias = umbracoTitleAlias,
value = titleFromSitecore
});
}
if (!string.IsNullOrEmpty(textFromSitecore))
{
valuesList.Add(new
{
alias = umbracoTextAlias,
value = textFromSitecore
});
}
var bodyObject = new
{
values = valuesList.ToArray(),
variants = new[]
{
new
{
name = "FAQ item"
}
}
};
var updateJson = JsonSerializer.Serialize(bodyObject, new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true
});
// (c) Send the PUT to Umbraco
var client = httpFactory.CreateClient();
client.BaseAddress = new Uri(umbracoHost);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", umbracoToken);
var content = new StringContent(updateJson, Encoding.UTF8, "application/json");
var response = await client.PutAsync($"/umbraco/management/api/v1/document/{umbracoFaqDocId}", content);
var responseBody = await response.Content.ReadAsStringAsync();
logger.LogInformation("Umbraco FAQ updated successfully");
return Results.Ok("Sitecore data used to update Umbraco successfully!");
});
// -----------------------------------------------------------------------
// Helper: Acquire a token from Umbraco Management API (Client Credentials)
// -----------------------------------------------------------------------
static async Task<string?> GetUmbracoTokenAsync(
IHttpClientFactory httpFactory,
string umbracoHost,
string clientId,
string clientSecret)
{
using var tokenClient = httpFactory.CreateClient();
tokenClient.BaseAddress = new Uri(umbracoHost);
var req = new ClientCredentialsTokenRequest
{
Address = "/umbraco/management/api/v1/security/back-office/token",
ClientId = clientId,
ClientSecret = clientSecret
};
var resp = await tokenClient.RequestClientCredentialsTokenAsync(req);
return resp.AccessToken;
}
app.Run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment