SitecoreAPIGraphQLClient 0.9.0
See the version list below for details.
dotnet add package SitecoreAPIGraphQLClient --version 0.9.0
NuGet\Install-Package SitecoreAPIGraphQLClient -Version 0.9.0
<PackageReference Include="SitecoreAPIGraphQLClient" Version="0.9.0" />
<PackageVersion Include="SitecoreAPIGraphQLClient" Version="0.9.0" />
<PackageReference Include="SitecoreAPIGraphQLClient" />
paket add SitecoreAPIGraphQLClient --version 0.9.0
#r "nuget: SitecoreAPIGraphQLClient, 0.9.0"
#:package SitecoreAPIGraphQLClient@0.9.0
#addin nuget:?package=SitecoreAPIGraphQLClient&version=0.9.0
#tool nuget:?package=SitecoreAPIGraphQLClient&version=0.9.0
SitecoreAPIGraphQLClient
A .NET 8 class library that provides a DI-friendly, thread-safe factory for GraphQL clients targeting Sitecore endpoints. It integrates with an authorization service to inject bearer tokens and supports configurable token refresh behavior.
Features
- Thread-safe GraphQL client factory with per-URL and credential caching (key: url::clientId)
- Token injection via HttpClient DelegatingHandler using ISitecoreTokenService
- Configurable refresh on 401 Unauthorized (EnableUnauthorizedRefresh, MaxUnauthorizedRetries)
- Manual token refresh API: ISitecoreGraphQLFactory.RefreshTokenAsync()
- Options binding, validation, and DI extension for easy setup
- Named clients support via configuration (multiple endpoints/credentials)
- Optional internal logging setup toggle to assist authorization service logging without requiring host AddLogging
- Unit tests using xUnit, Shouldly, and Moq
Requirements
- .NET 8 SDK/runtime
Installation
- NuGet package ID: SitecoreGraphQLClient
- Using CLI
dotnet add package SitecoreGraphQLClient
- Using PackageReference
<ItemGroup> <PackageReference Include="SitecoreGraphQLClient" Version="x.y.z" /> </ItemGroup>
Configuration (appsettings.json)
{
"Sitecore": {
"GraphQL": {
"Endpoint": "https://your.sitecore/graphql",
"ClientId": "your-client-id",
"ClientSecret": "your-client-secret",
"EnableUnauthorizedRefresh": true,
"MaxUnauthorizedRetries": 1,
"EnableInternalLoggingSetup": true,
"Clients": {
"content": {
"Endpoint": "https://content/graphql",
"ClientId": "content-id",
"ClientSecret": "content-secret"
},
"search": {
"Endpoint": "https://search/graphql",
"ClientId": "search-id",
"ClientSecret": "search-secret"
}
}
}
}
}
Registration (Program.cs)
var builder = WebApplication.CreateBuilder(args);
// Bind options and register factory + HTTP pipeline
builder.Services.AddSitecoreGraphQL(builder.Configuration);
// Also register an ISitecoreTokenService implementation provided by Sitecore API Authorization
Optional internal logging setup
By default, AddSitecoreGraphQL will try to register minimal logging services (LoggerFactory and ILogger<T>) if the host did not already add logging, so that downstream services like the Sitecore Token Service can receive ILogger<T>. To opt out, set EnableInternalLoggingSetup to false in configuration.
Basic usage
public class Consumer
{
private readonly ISitecoreGraphQLFactory _factory;
public Consumer(ISitecoreGraphQLFactory factory) => _factory = factory;
public async Task QueryAsync(CancellationToken ct = default)
{
// Uses Endpoint, ClientId, ClientSecret from configuration
var client = await _factory.CreateClientAsync(ct);
var request = new GraphQL.Client.Abstractions.GraphQLRequest
{
Query = "query Example { ping }"
};
var response = await client.SendQueryAsync<System.Text.Json.JsonDocument>(request, ct);
var data = response.Data;
}
}
Named clients usage
// appsettings.json contains Sitecore:GraphQL:Clients:content and :search
var contentClient = await factory.CreateClientByNameAsync("content", ct);
var searchClient = await factory.CreateClientByNameAsync("search", ct);
// contentClient and searchClient are cached independently by url::clientId
Advanced: named client from sub-section configuration
// You can bind a sub-section rather than full configuration, e.g. from an options object
var graphQlSection = builder.Configuration.GetSection("Sitecore:GraphQL");
builder.Services.AddSitecoreGraphQL(new ConfigurationBuilder().AddConfiguration(graphQlSection).Build());
// Or compose programmatic options (e.g., in tests)
services.Configure<SitecoreGraphQLOptions>(o =>
{
o.Clients["analytics"] = new SitecoreGraphQLClientOptions
{
Endpoint = "https://analytics/graphql",
ClientId = env["ANALYTICS_ID"],
ClientSecret = env["ANALYTICS_SECRET"]
};
});
var analytics = await factory.CreateClientByNameAsync("analytics", ct);
Overloads
// 1) Explicit endpoint (uses configured credentials)
var c1 = await factory.CreateClientAsync("https://your.sitecore/graphql", ct);
// 2) Explicit endpoint and explicit credentials (bypasses configured credentials)
var c2 = await factory.CreateClientAsync(
url: "https://another/graphql",
clientId: "client-id",
clientSecret: "client-secret",
cancellationToken: ct);
// 3) Default endpoint and credentials from configuration
var c3 = await factory.CreateClientAsync(ct);
// 4) Named client from configuration
var c4 = await factory.CreateClientByNameAsync("content", ct);
Manual token refresh
var refreshed = await factory.RefreshTokenAsync(ct);
if (!refreshed)
{
// handle refresh failure (log, alert, etc.)
}
Options reference
- Endpoint: default GraphQL endpoint used when not passing a URL into CreateClientAsync (must be valid http/https if provided)
- ClientId: OAuth client id used to acquire tokens
- ClientSecret: OAuth client secret used to acquire tokens
- EnableUnauthorizedRefresh: when true, refresh and retry on 401 responses
- MaxUnauthorizedRetries: number of additional retries after the first 401 (0 disables retries)
- EnableInternalLoggingSetup: when true (default), DI will TryAdd minimal logging so downstream services can receive ILogger<T>; set to false to opt out
- Clients: named client map; each entry requires Endpoint (valid http/https), ClientId, ClientSecret
API surface
- Interfaces
- ISitecoreGraphQLFactory
- Task<IGraphQLClient> CreateClientAsync(string url, string clientId, string clientSecret, CancellationToken ct = default)
- Task<IGraphQLClient> CreateClientAsync(string url, CancellationToken ct = default)
- Task<IGraphQLClient> CreateClientAsync(CancellationToken ct = default)
- Task<IGraphQLClient> CreateClientByNameAsync(string clientName, CancellationToken ct = default)
- Task<bool> RefreshTokenAsync(CancellationToken ct = default)
- ITokenValueAccessor (advanced)
- string GetAccessToken(SitecoreAuthToken token)
- ISitecoreTokenCache (advanced)
- string? CurrentToken { get; }
- Task<string?> GetOrRefreshAsync(CancellationToken ct)
- Task<string?> ForceRefreshAsync(CancellationToken ct)
- ISitecoreGraphQLFactory
- Classes
- DependencyInjection.ServiceCollectionExtensions
- IServiceCollection AddSitecoreGraphQL(IConfiguration configuration)
- SitecoreGraphQLOptions
- string? Endpoint, string? ClientId, string? ClientSecret
- bool EnableUnauthorizedRefresh (default true), int MaxUnauthorizedRetries (default 1)
- bool EnableInternalLoggingSetup (default true)
- Dictionary<string, SitecoreGraphQLClientOptions> Clients
- Http.SitecoreTokenHandler
- DelegatingHandler that injects Authorization: Bearer and retries on 401 with exponential backoff
- SitecoreGraphQLFactory
- public const string NamedHttpClient = "SitecoreGraphQL"
- DependencyInjection.ServiceCollectionExtensions
Testing
- Run tests locally
dotnet test -v minimal
- Generate coverage locally (example)
dotnet test --configuration Release --collect:"XPlat Code Coverage"
- Stack: xUnit, Shouldly, Moq
- Pattern: Arrange�Act�Assert
CI
- GitHub Actions workflows build and test on .NET SDK 8 and 9
- Coverage artifacts are uploaded from CI
- NuGet publishing triggered on version tags (v*)
Versioning and changelog
- See CHANGELOG.md for release notes
License
- See LICENSE for terms
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- GraphQL (>= 8.5.0)
- GraphQL.Client (>= 6.1.0)
- GraphQL.Client.Abstractions (>= 6.1.0)
- GraphQL.Client.Serializer.SystemTextJson (>= 6.1.0)
- Microsoft.Extensions.Configuration.Binder (>= 9.0.8)
- Microsoft.Extensions.Http (>= 9.0.8)
- Microsoft.Extensions.Options (>= 9.0.8)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 9.0.8)
- SitecoreAPIAuthorization (>= 0.9.1)
-
net9.0
- GraphQL (>= 8.5.0)
- GraphQL.Client (>= 6.1.0)
- GraphQL.Client.Abstractions (>= 6.1.0)
- GraphQL.Client.Serializer.SystemTextJson (>= 6.1.0)
- Microsoft.Extensions.Configuration.Binder (>= 9.0.8)
- Microsoft.Extensions.Http (>= 9.0.8)
- Microsoft.Extensions.Options (>= 9.0.8)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 9.0.8)
- SitecoreAPIAuthorization (>= 0.9.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.