Read a Store attribute through a typed adapter

Map Store attributes into named rows and expose simple setting methods with deliberate rules for missing labels, numeric defaults, and duplicates.

Znode 9RecipeFoundationGCG engineering guide
Workflow walkthrough

Try the Store-setting experience

Change a fictional Store’s support label and see the display rules in action. This demonstrates the result; SQL and Razor run in your Znode environment.

Open interactive preview
Browser-only demo · example data
Follow the complete recipe
In this guide
  1. current Store context
  2. IStoreAttributeSource
  3. typed StoreSettings
  4. caller
One adapter owns the platform-specific read; callers receive typed, documented behavior.

Keep the platform seam narrow

StoreSettings exposes useful settings instead of platform response objects. IStoreAttributeSource resolves the current Store and maps its attribute response into AttributeRow objects with Code and Value properties. Keep those platform calls in one adapter so callers only ask for SupportLabel or LeadDaysOrDefault.

The source must return the selected Store's complete attribute rows and preserve failures as exceptions. SingleOrDefault requires at most one matching code, so a duplicate cannot silently choose the first value.

StoreSettings.cs csharp

using System;
using System.Collections.Generic;
using System.Linq;

public sealed class AttributeRow
{
    public string Code { get; set; }
    public string Value { get; set; }
}

public interface IStoreAttributeSource
{
    IReadOnlyList<AttributeRow> ReadForCurrentStore();
}

public sealed class StoreSettings
{
    private readonly IStoreAttributeSource source;
    public StoreSettings(IStoreAttributeSource source)
    {
        if (source == null)
            throw new ArgumentNullException(nameof(source));
        this.source = source;
    }

    // null means absent. Dependency failures are not converted to absence.
    public string SupportLabel()
    {
        var row = source.ReadForCurrentStore().SingleOrDefault(x =>
            string.Equals(x.Code, "GcgSupportLabel", StringComparison.OrdinalIgnoreCase));
        return row == null || row.Value == null ? null : row.Value.Trim();
    }

    public int LeadDaysOrDefault(int fallback)
    {
        if (fallback < 0)
            throw new ArgumentOutOfRangeException(nameof(fallback));
        var row = source.ReadForCurrentStore().SingleOrDefault(x =>
            string.Equals(x.Code, "LeadDays", StringComparison.OrdinalIgnoreCase));
        int days;
        return row != null && int.TryParse(row.Value, out days) && days >= 0
            ? days : fallback;
    }
}

If GcgSupportLabel contains ' Technical support ', SupportLabel returns 'Technical support'. A missing row or null value returns null, while whitespace-only text becomes an empty string. LeadDaysOrDefault(3) returns a saved nonnegative integer when valid and otherwise returns 3. Decide whether those missing and invalid-value outcomes suit the consuming feature.

Choose missing-value behavior

An optional display label can return no text. A lead-time fallback may be acceptable when the business has explicitly chosen it. A value controlling permission, pricing, or checkout acceptance needs a stricter policy, such as a configuration error that blocks the affected operation.

Keep dependency failure separate from a missing setting. The helper's fallback handles a missing or invalid LeadDays value; it does not catch a failed attribute-service request.

Verify context and duplicates

Use a test double with two Store contexts. Confirm that each context returns its own value, a missing value takes the documented path, and duplicate GcgSupportLabel rows throw rather than silently choosing one. Then add an integration check against the declared patch to prove the adapter's platform call and locale behavior.

Make the adapter own platform details

Implement IStoreAttributeSource in one infrastructure class. Resolve the Store or portal through the host's trusted Store context, and apply authorization when reading protected configuration. Call the supported global-attribute service for the exact patch and map only the needed code and value. Do not let an arbitrary query-string Store ID select configuration.

Start without caching unless measurement shows a need. If you add a cache, include Store and locale whenever they affect the value, and define how an Admin edit invalidates the entry. Keep raw setting values out of routine logs when they may contain contact or configuration information.

References and further reading

Bring your next engineering question.

Need help reducing risky configuration coupling?

Explore how GCG can help

Independent guidance from GCG. Znode is a trademark of its owner. Examples use fictional data and are not official platform documentation. Suggest a correction.

Previous
Previous

Design a service override and plan its registration

Next
Next

Customer-specific pricing: choose the source of truth before the cache