Configuration

This guide covers all configuration options for Agility CMS .NET applications, including API settings, caching, environment variables, and multi-locale support.

Configuration Files

appsettings.json

The main configuration file with default settings:

{
  "AppSettings": {
    "InstanceGUID": "",
    "SecurityKey": "",
    "FetchAPIKey": "",
    "PreviewAPIKey": "",
    "Locales": "en-us",
    "ChannelName": "website",
    "CacheInMinutes": 5
  },
  "CacheControl": {
    "MaxAgeSeconds": 30,
    "StaleWhileRevalidateSeconds": 86400,
    "StaleIfErrorSeconds": 86400
  }
}

appsettings.local.json

Local development credentials (gitignored):

{
  "AppSettings": {
    "InstanceGUID": "your-instance-guid",
    "SecurityKey": "your-security-key",
    "FetchAPIKey": "defaultlive.your-fetch-key",
    "PreviewAPIKey": "defaultpreview.your-preview-key"
  }
}

appsettings.Development.json

Development-specific overrides:

{
  "DetailedErrors": true,
  "AppSettings": {
    "CacheInMinutes": 0
  }
}

AppSettings Reference

Required Settings

SettingDescriptionExample
InstanceGUIDYour Agility CMS instance identifierabc123-def456-...
SecurityKeyUsed for preview mode authenticationMySecretKey123
FetchAPIKeyAPI key for published contentdefaultlive.abc...
PreviewAPIKeyAPI key for draft contentdefaultpreview.xyz...

Optional Settings

SettingDefaultDescription
Localesen-usComma-separated locale codes
ChannelNamewebsiteAgility CMS sitemap channel
CacheInMinutes5Server-side cache duration
WebsiteName-Site name for display

Where to Find API Keys

  1. Log in to Agility CMS
  2. Go to Settings > API Keys
  3. Copy the required values:
    • GUID - Instance identifier
    • Security Key - For preview authentication
    • Live API Key - Starts with defaultlive
    • Preview API Key - Starts with defaultpreview

CacheControl Settings

Control CDN caching behavior with stale-while-revalidate headers:

SettingDefaultDescription
MaxAgeSeconds30How long CDN serves fresh content
StaleWhileRevalidateSeconds86400Serve stale while revalidating (1 day)
StaleIfErrorSeconds86400Serve stale if origin is down (1 day)

How It Works

Cache-Control: public, max-age=30, stale-while-revalidate=86400, stale-if-error=86400
  1. First 30 seconds: CDN serves cached content directly
  2. After 30 seconds: CDN serves stale content while fetching fresh in background
  3. If origin fails: CDN continues serving stale content for up to 1 day

Disabling CDN Caching

CDN cache headers are automatically disabled for:

  • Preview mode requests
  • Development environment

Environment Variables

For production deployments (Azure, Docker, etc.), use environment variables instead of config files.

Azure App Service Format

Use double underscores (__) for nested properties:

AppSettings__InstanceGUID=your-guid
AppSettings__SecurityKey=your-key
AppSettings__FetchAPIKey=defaultlive.your-key
AppSettings__PreviewAPIKey=defaultpreview.your-key
AppSettings__Locales=en-us,fr-ca
AppSettings__ChannelName=website
AppSettings__CacheInMinutes=5
CacheControl__MaxAgeSeconds=30
CacheControl__StaleWhileRevalidateSeconds=86400
CacheControl__StaleIfErrorSeconds=86400

Setting in Azure Portal

  1. Go to your App Service
  2. Navigate to Settings > Environment variables
  3. Add each setting as an application setting
  4. Click Save and restart the app

Using Azure CLI

az webapp config appsettings set \
  --name your-app-name \
  --resource-group your-resource-group \
  --settings \
    AppSettings__InstanceGUID=your-guid \
    AppSettings__SecurityKey=your-key \
    AppSettings__FetchAPIKey=defaultlive.your-key \
    AppSettings__PreviewAPIKey=defaultpreview.your-key

Docker Environment Variables

ENV AppSettings__InstanceGUID=your-guid
ENV AppSettings__SecurityKey=your-key
ENV AppSettings__FetchAPIKey=defaultlive.your-key
ENV AppSettings__PreviewAPIKey=defaultpreview.your-key

Or with docker-compose:

services:
  web:
    environment:
      - AppSettings__InstanceGUID=your-guid
      - AppSettings__SecurityKey=your-key
      - AppSettings__FetchAPIKey=defaultlive.your-key
      - AppSettings__PreviewAPIKey=defaultpreview.your-key

Multi-Locale Configuration

Configuring Locales

Specify supported locales as a comma-separated list:

{
  "AppSettings": {
    "Locales": "en-us,fr-ca,es-mx"
  }
}

Locale Detection

The starters detect locale from:

  1. URL prefix - /fr-ca/about uses fr-ca locale
  2. Default locale - First locale in the list is default

Locale-Specific Content

// Fetch content for a specific locale
var posts = await _fetchApi.GetTypedContentList<Post>(
    referenceName: "posts",
    locale: "fr-ca",  // French Canadian
    take: 10
);

Locale Switching

Implement locale switching in your header:

@foreach (var locale in Locales)
{
    <a href="/@locale@CurrentPath"
       class="@(locale == CurrentLocale ? "active" : "")">
        @GetLocaleDisplayName(locale)
    </a>
}

Caching Configuration

Server-Side Cache

The CacheInMinutes setting controls how long API responses are cached in memory:

EnvironmentRecommended Value
Development0 (disabled)
Staging1-2
Production5-10
{
  "AppSettings": {
    "CacheInMinutes": 5
  }
}

Cache Behavior

  • CacheInMinutes = 0: Every request fetches fresh data
  • CacheInMinutes > 0: Data cached for specified duration
  • Preview mode: Caching always disabled

Cache Invalidation

Configure webhooks in Agility CMS to invalidate cache on publish:

  1. Go to Settings > Webhooks in Agility CMS
  2. Add webhook URL: https://your-site.com/api/revalidate
  3. Select events to trigger invalidation

Preview Mode Configuration

How Preview Works

  1. Development: Preview is always enabled
  2. Production: Preview requires authentication via query parameter

Preview URL Format

https://your-site.com/page-path?agilitypreviewkey=HASH

The agilitypreviewkey is generated from your SecurityKey.

Setting Up Preview in Agility CMS

  1. Go to Settings > Preview URLs
  2. Add your site URL with the preview parameter placeholder:
    https://your-site.com{path}?agilitypreviewkey={previewkey}
    

Custom Preview Key Validation

public static bool ValidatePreviewKey(string key, string securityKey)
{
    using var sha256 = SHA256.Create();
    var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(securityKey));
    var expectedKey = Convert.ToBase64String(hash);
    return key == expectedKey;
}

Reading Configuration

In Program.cs / Startup.cs

var builder = WebApplication.CreateBuilder(args);

// Access configuration
var instanceGuid = builder.Configuration["AppSettings:InstanceGUID"];
var locales = builder.Configuration["AppSettings:Locales"]?.Split(',') ?? new[] { "en-us" };

// Bind to strongly-typed options
builder.Services.Configure<AppSettings>(
    builder.Configuration.GetSection("AppSettings"));

In Services (Dependency Injection)

public class MyService
{
    private readonly AppSettings _settings;

    public MyService(IOptions<AppSettings> options)
    {
        _settings = options.Value;
    }

    public string GetInstanceGuid() => _settings.InstanceGUID;
}

In Razor Components/Pages

@inject IOptions<AppSettings> AppSettings

@code {
    private string InstanceGuid => AppSettings.Value.InstanceGUID;
}

Configuration Classes

AppSettings Class

public class AppSettings
{
    public string InstanceGUID { get; set; } = "";
    public string SecurityKey { get; set; } = "";
    public string FetchAPIKey { get; set; } = "";
    public string PreviewAPIKey { get; set; } = "";
    public string Locales { get; set; } = "en-us";
    public string ChannelName { get; set; } = "website";
    public int CacheInMinutes { get; set; } = 5;
    public string? WebsiteName { get; set; }

    public string[] GetLocales() => Locales.Split(',', StringSplitOptions.RemoveEmptyEntries);
    public string DefaultLocale => GetLocales().FirstOrDefault() ?? "en-us";
}

CacheControl Class

public class CacheControl
{
    public int MaxAgeSeconds { get; set; } = 30;
    public int StaleWhileRevalidateSeconds { get; set; } = 86400;
    public int StaleIfErrorSeconds { get; set; } = 86400;
}

Security Best Practices

Never Commit Secrets

  1. Use appsettings.local.json for local development (gitignored)
  2. Use environment variables for production
  3. Never commit API keys to version control

Verify .gitignore

Ensure your .gitignore includes:

appsettings.local.json
appsettings.*.local.json
*.local.json

Use Azure Key Vault (Production)

For enhanced security, use Azure Key Vault:

builder.Configuration.AddAzureKeyVault(
    new Uri($"https://{keyVaultName}.vault.azure.net/"),
    new DefaultAzureCredential()
);

Troubleshooting

"InstanceGUID is required"

  1. Check appsettings.local.json exists
  2. Verify the JSON is valid
  3. Confirm the value is not empty

"Invalid API Key"

  1. Verify the key is copied correctly (no extra spaces)
  2. Check you're using the correct key (live vs preview)
  3. Regenerate the key in Agility CMS if needed

Cache Not Invalidating

  1. Verify webhook URL is correct
  2. Check webhook is receiving events (Agility logs)
  3. Confirm CacheInMinutes > 0

Preview Mode Not Working

  1. Verify SecurityKey matches Agility settings
  2. Check the preview URL format
  3. Clear browser cookies

Next Steps