Web API XML Serializer

Miroslav Holec       28.10.2014       C#, ASP.NET MVC, XML, .NET       12525 zobrazení

Při práci s aplikačním rozhraním preferuji formát JSON pro jeho srozumitelnost a úspornost. Přesto se občas hodí mít API nastavené i pro podporu formátu XML a plně tak podporovat content negotiation dle požadovaného typu.

Tento článek doplňuje superdlouhý článek RESTful API Design, který jsem napsal na svém blogu a který doporučuji přečíst.

Podpora agent drivent content negotiation vypadá tak, že ze strany agenta je přijímána HTTP header:

Accept: text/xml

nebo pro JSON například:

Accept: text/json

Webový server pak obvykle (pokud tento formát podporuje) odpovídá odpovídajícím contentem s HTTP hlavičkou:

Content-Type: text/json; charset=utf-8

Formatter config

Prvním krokem k nastavení podpory XML je nastavení XML formatteru. Ve Web API projektu mám všechny formatters pohromadě volané z global.asax aplikačního rozhraní.

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        // other code
        FormatterConfig.RegisterFormatters(GlobalConfiguration.Configuration.Formatters);
    }
}

Nicméně není problém přistoupit k nastavení odkudkoliv přímo

var formatters = GlobalConfiguration.Configuration.Formatters;

Pro XML serializer lze použít následující nastavení:

public class FormatterConfig
{
    public static void RegisterFormatters(MediaTypeFormatterCollection formatters)
    {
        formatters.Add(new XmlMediaTypeFormatter());
        formatters.XmlFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml"));
        formatters.XmlFormatter.UseXmlSerializer = true;
    }
}
  1. Přidáme nový formatter pro XML
  2. Přidáme podporovaný typ (to je value uvedena v HTTP hlavičce Accept)
  3. Explicitně si vyžádáme použití XmlSerializeru

Format text/xml VS. application/xml

Rozdíl z hlediska MIME typu (a netýká se jen XML ale i JSONu) popisují různé RFC. V případě XML je to RFC 3023. Dle bodu 3:

Pokud je XML dokument nezpracovaný (zdrojový XML) a čitelný pro běžné uživatele, pak upřednostňujeme text/xml před application/xml. Naopak application/xml dáváme přednost všude tam, kde není XML čitelný pro běžné uživatele.

Tato definice je nicméně dost nejasná (hlavně kvůli pojmu (ne)čitelný) pro běžné uživatele. Jsem zastáncem toho, že XML dokument by měl být ideálně čitelný vždy a doporučil bych použít plain formát text/xml.

XmlSerializer

Standardně používá Web API vlastní serializer. Ten má celou řadu nešvarů, například v podobě generování ošklivých namespaces. Také se mi nezřídka stávalo, že nebyl schopen některé entity serializovat. Proto je lepší použít "standardní" XmlSerializer místo DataContractSerializeru. To lze provést nastavením:

formatters.XmlFormatter.UseXmlSerializer = true;

XmlSerializer umí serializovat objekty do XML a stejně tak zpětně deserializovat XML do objektů na základě definované struktury tříd.

Serializace

Proces serializace spočívá jen v přípravě tříd pro serializaci. K tomu je vhodné použít data anotace, které jsou ve jmenném prostoru System.Runtime.Serialization.

Příklad objektu pro serializaci:

[DataContract(Namespace = "")]
public class Article
{
    [DataMember]
    public int Id { get; set; }

    [DataMember]
    public string Title { get; set; }

    [DataMember]
    public string Description { get; set; }
}

Pro Web API doporučuji používat [DataContract(Namespace = "")], aby se zamezilo generování jmenných prostorů do XML. Atributů pro popsání serializace je celá řada.

Serializovat data lze i přímo v kódu:

var serializer = new XmlSerializer(typeof (T));
serializer.Serialize(@"c:/output.xml", new Article());

Deserializace

Deserializace je proces, kde již více záleží na přesnosti. Je nutné aby přesně souhlasily názvy properties a elementů XML dokumentu. Při parsování lze však používat vlastní názvy properties odekorované o anotace popisující přesné názvy elementů. Pokud tedy chceme použít API pro zpracování dat třetí strany, často budeme potřebovat další anotace.

[XmlType(TypeName = "PRODUCT")]
public class Product
{
    private double? price?

    [XmlElement("PRODUCTNAME")]
    public string Title { get; set; }

    [XmlElement("PRICESPECIAL")]
    public double? Price 
    {
        get
        {
            if (!price.HasValue)
                return null;

            return Math.Round(price.Value, 2);
        }
        set
        {
            if (!value.HasValue)
                price = null;

            price = value;
        }
    }
}

Závěr

XML stále patří mezi dva velmi významné formáty a vzhledem k snadnému nastavení Web API sle vyplatí podporovat content negotiation. Na druhou stranu u větších projektů, kde není přímá potřeba s XML formátem pracovat může být popisování struktury entit anotacemi nevyužitá práce navíc.

Velkou výhodou content negotiation API je možnost zpracovávat požadavky služeb třetích stran. Požadavky pak není nutné složitě parsovat nebo procházet pomocí XmlDocument ale pouze si vytvořit korespondující datové objekty a nechat na XmlSerializeru proces deserializace bez jakéhokoliv úsilí.

Zdroje

Přednáška Web API

O základních principech Web API budu mluvit na přednášce v Hradci Králové:

5. 11. 2014 17:00 – První středa na FIM UHK – Web API

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

Nový příspěvek

 

Příspěvky zaslané pod tento článek se neobjeví hned, ale až po schválení administrátorem.

                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

Příspěvky zaslané pod tento článek se neobjeví hned, ale až po schválení administrátorem.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback