Slovenská verzeSlovensky

Nastavení JSON formatteru v API dle klienta

Stalo se vám, že jste potřebovali vracet JSON data v odlišném formátu podle toho, jaký klient se dotazuje na vaše API? Pokud ano, velmi snadno se dá tento "problém" vyřešit pomocí ActionFilter atributu a dodatečné konfigurace controlleru.

Miroslav Holec

Miroslav Holec

16. března. 2016
upraven 21. září. 2016

Tento článek je již velmi zastaralý. Zastaralé články nemusí popisovat aktuální stav technologií, nejideálnější řešení a můj aktuální pohled na danou technologii.

Problém

Máme dva klienty, například mobilní aplikaci z roku 2012, která v minulosti konzumovala JSON data ve formátu:

{
	"FirstName" : "Miroslav",
	"LastName" : "Holec"
}

Píše se rok 2016 a vzniká nové API, které bude po vzoru JavaScript konvencí vracet lowerCamelCase JSON:

{
	"firstName" : "Miroslav",
	"lastName" : "Holec"
}

Problém je, že globální změna v API by znemožnila správnou funkci ve starých klientech z roku 2012, které má plno uživatelů nainstalováno v mobilních zařízeních. Jak nastavit API aby uspokojilo všechny klienty?

Řešení

Předpokladem pro řešení je schopnost rozlišit, jaký klient se dotazuje na data. Obvykle máme podobnou informaci přímo v Requestu. Může to být querystring, hlavička, IP adresa nebo jiný příznak. Pokud tuto informaci nemáme, prohlásíme všechny stávající klienty jako legacy a novým přidáme povinnost uvádět verzi API (například v hlavičce).

Pak už si stačí napsat jednoduchý atribut, který na základě requestu nakonfiguruje vhodný formatter.

[FormatterController]
public class MyController : ApiController
{
}

public class FormatterControllerAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var queryParameters = actionContext.Request.GetQueryNameValuePairs().ToList();
        var apiKey = queryParameters.FirstOrDefault(x => x.Key.Equals("API_KEY", StringComparison.InvariantCultureIgnoreCase));

        // pokud se nejedna o stara API calls, ktere pouzivaji API_KEY, nastavi se novy formatter
        if (apiKey.Value != "holec9876api_key_xxxxxxxxxxxxxxxx")
        {
            actionContext.ControllerContext.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        }

        base.OnActionExecuting(actionContext);
    }
}

A to je celé řešení. Právě actionContext.ControllerContext.Configuration nám poskytuje možnost dodatečně nakonfigurovat controller podle potřeby.


👨‍🎓 Webináře pro vývojáře

Vzdělávat se můžete i z pohodlí domova. Klasická školení jsem doplnil o související témata, která si můžete poslechnout v podobě živých webinářů. Přidejte se téměř 200 vývojářům, kteří se již připojili k mým webinářům!

Termín Místo
🍀 Konzumace REST API v .NET Core červen 2020 on-line více
🍀 Nástroje a šablony projektů v .NET Core červen 2020 on-line více
🍀 Entity Framework Core červen 2020 on-line více
Loading
Otevřít chat