Skip to content

.NET SDK — install and configure

The .NET client SDK embeds Oclavex into your application: it activates a license, tells you what the current license permits, and reports what gets used. Everything it does is also available over the REST API — the SDK is the convenience layer for .NET.

The SDK ships as NuGet packages. Most applications need these:

Terminal window
dotnet add package Revenusion.MonetizeIt.Client.LicenseConsumer
dotnet add package Revenusion.MonetizeIt.Client.LicenseConsumer.Connected
dotnet add package Revenusion.MonetizeIt.Client.AspNetCore
  • Client.LicenseConsumer — the licensing engine (activation, validation, usage). Targets netstandard2.0, so it runs on .NET Framework, .NET 8+, MAUI, and Unity.
  • Client.LicenseConsumer.Connected — the online add-on: HTTP transport, background license refresh and usage upload. Any application that activates over the network needs it; it pulls in its Client.Provisioning (API wrappers) and HttpConnector (transport) dependencies for you.
  • Client.AspNetCore — dependency-injection wiring, the authenticated HTTP client, and the background usage reporter for host-based apps.

For disconnected devices, add Client.OfflineStore.

Two configuration sections drive the SDK. Oclavex:Tenant says which tenant to talk to; Oclavex:LicenseConsumer says how licenses behave on this machine.

{
"Oclavex": {
"Tenant": {
"HostName": "example.com",
"TenantName": "acme"
},
"LicenseConsumer": {
"LicenseKey": "the-license-key-for-this-install",
"PublicKey": "<base64 provider public key>",
"License": { "AllowUnsignedLicenses": false },
"Scheduler": {
"UsageReportingIntervalSeconds": 60,
"LicenseRefreshIntervalSeconds": 300
}
}
}
}

HostName + TenantName resolve to your tenant endpoint (https://acme.example.com); LicenseKey is what this install activates. A shipped app needs nothing more — the activation endpoints are anonymous, so it carries no API client of its own.

builder.Services
.AddMonetizeItHttpClientWithAuthentication(builder.Configuration)
.AddMonetizeItLicenseConsumer(builder.Configuration);

AddMonetizeItLicenseConsumer registers ILicenseSession (scoped) as the entry point your code uses. AddMonetizeItHttpClientWithAuthentication gives it an HTTP client pointed at your tenant — anonymous by default, or authenticating with the client credentials when you configure them.

Licenses are signed by the provider. The SDK verifies that signature with the provider’s public key, so a tampered or forged license is rejected. Obtain the key once from the admin API — GET /api/v1/provision/admin/providers/license-signing-key — and set it as Oclavex:LicenseConsumer:PublicKey.

If no key is configured, the SDK refuses to start rather than silently trusting unverified licenses — a licensing runtime that fails open is not enforcing anything. The only opt-out is License:AllowUnsignedLicenses = true, intended for transport-authenticated test setups, never production.

Pinning more than one key, for rotation without downtime

Section titled “Pinning more than one key, for rotation without downtime”

UsePublicKey has a second overload that pins a key by the id it’s published under, and you can call it more than once to pin a set:

.UsePublicKey("provider_a1b2c3...", currentKeyBase64)
.UsePublicKey("provider_d4e5f6...", nextKeyBase64)

A license is verified against whichever key its own key_id names; one naming a key you haven’t pinned is rejected rather than falling back to some other key you happened to pin. That’s what makes rotating the provider’s signing key a non-event for deployed clients — see rotating the signing key for the publish → pin both → promote → retire sequence. The single-key overload above still works unchanged; a bare pinned key verifies a license carrying any key_id, so applications built before key rotation existed keep working, no code change.

A single-install application sets LicenseKey (and optionally NodeId) in configuration. An application that serves many customer tenants from one process supplies the license key per request instead: register your own scoped ILicenseKeyProvider before calling AddMonetizeItLicenseConsumer, and resolve the key from the current request’s tenant.

builder.Services.AddScoped<ILicenseKeyProvider>(sp =>
StaticLicenseKeyProvider.Create(CurrentTenant.LicenseKey));

The same pattern applies to INodeIdProvider when each tenant needs a distinct device identity. See device fingerprints.

Desktop and plain-.NET applications that don’t run a generic host build the client directly. LicenseClientBuilder assembles it from small parts — what identifies the license, what identifies the device, where to cache, and how to talk to the API:

using Revenusion.MonetizeIt.Client.LicenseConsumer;
using Revenusion.MonetizeIt.Client.AspNetCore;
using Revenusion.MonetizeIt.HttpConnector;
// The transport the builder needs. Activation is anonymous — the license token the
// server returns is what authenticates every call after it. Treat this as a singleton:
// each call allocates a fresh HttpClient.
var httpClient = MonetizeItClientFactory.Create(
$"https://{tenantName}.{hostName}", new AnonymousAuthentication());
var client = new LicenseClientBuilder()
.UseMonetizeItHttpClient(httpClient) // points at your API base URL
.UseLicenseKey(StaticLicenseKeyProvider.Create(code)) // the activation code
.UseNodeId(new DeviceIdDeviceFingerprint()) // the device fingerprint
.UsePublicKey(base64PublicKey) // pin the signing key
.UseLicenseStoreBuilder() // cache the license on disk
.UseSystemInfo() // report OS/app diagnostics
.Build();
var session = client.Session;

Build() returns an ILicenseClient: it owns the background schedulers (usage upload, scheduled reporting), exposes the Session, and is IDisposable — keep it for the application’s lifetime and dispose it on shutdown. Call FlushAsync() to push pending usage before exit. BuildSession() is a shortcut when you only want the ILicenseSession.

Two more builder calls appear in most real integrations: WithOptions(...) applies a LicenseConsumerOptions instance — scheduler intervals, license behavior — without a configuration host, and UseApplicationInfo(RuntimeApplicationInfo.Create(...)) reports your application’s identity and version explicitly. UseSystemInfo, shown above, is separate: it collects OS and runtime details for usage reports, and takes an optional lambda that selects what is collected.

Add UseLoggerFactory(loggerFactory) — without it the client logs nowhere, and an activation failure (revoked key, 401, network error) is undiagnosable beyond the LastError on the session.

The provider key requirement applies here too: the builder refuses to build unless you pin the public key with UsePublicKey or explicitly opt out via LicenseConfiguration.AllowUnsignedLicenses.

From here on, everything is identical to the hosted path — the same ILicenseSession, the same activation, entitlement checks and usage reporting.

Hosted app AddMonetizeItLicenseConsumer Desktop / plain .NET LicenseClientBuilder ILicenseSession the one entry point AccessLicenseAsync the license — validation & feature checks UsageReporter report activity — buffered & batched AssetConsumption metered draw-down — server-settled

If you want thin HTTP wrappers instead of the full consumer, Revenusion.MonetizeIt.Client.Provisioning exposes them directly:

  • LicenseActivationApiFetchJwtByActivationCodeAsync, FetchLicenseAsync, RenewLicenseAsync, CheckInAsync, CheckOutAsync.
  • UsageApiProcessTransactionsForSessionAsync, ProcessTransactionsForEntitlementAsync, TryConsumeAsync, TryPreAllocateAsync, AssetConsumptionAsync, AssetUsageAsync, GetRatingPromptAsync. TryConsumeAsync takes an optional idempotentKey — a retried commit with the same key returns the original decision instead of consuming twice.

They map one-to-one onto the REST endpoints and share the authentication providers.