2015-03-10 2 views
2

FlUrl fait un excellent travail dans le traitement des requêtes Json/UrlEncoded. Cependant, la documentation ne précise pas comment gérer d'autres types de requêtes tels que text/xml.Comment faire XML POST avec FlUrl

Quelle est la meilleure façon de faire un POST XML en utilisant FlUrl?

Cette (accès sous-jacente HttpClient) défaites un peu le but d'utiliser Flurl puisque vous avez besoin pour construire l'URI et le contenu à nouveau:

var result = await "http://someUrl" 
        .AppendPathSegment(pathSegment) 
        .SetQueryParam("name", name) 
        .WithBasicAuth(_userName, _apiToken) 
        .HttpClient 
        .PostAsync(<uri>, <content>); 

Répondre

3

support XML n'est pas cuit dans encore, mais c'est logged et est l'un des quelques fonctionnalités restantes que j'aimerais avoir en place pour Flurl.Http 1.0. (Étonnamment, personne ne l'a demandé jusqu'à maintenant.)

En attendant, Flurl is pretty easy to extend, et vous pourriez ajouter ce soutien vous-même via des méthodes d'extension. Cela devrait être tout ce que vous devez poster une couramment chaîne XML:

public static class FlurlXmlExtensions 
{ 
    // chain off an existing FlurlClient: 
    public static async Task<HttpResponseMessage> PostXmlAsync(this FlurlClient fc, string xml) { 
     try { 
      var content = new CapturedStringContent(xml, Encoding.UTF8, "application/xml"); 
      return await fc.HttpClient.PostAsync(fc.Url, content); 
     } 
     finally { 
      if (AutoDispose) 
       Dispose(); 
     } 
    } 

    // chain off a Url object: 
    public static Task<HttpResponseMessage> PostXmlAsync(this Url url, string xml) { 
     return new FlurlClient(url, true).PostXmlAsync(xml); 
    } 

    // chain off a url string: 
    public static Task<HttpResponseMessage> PostXmlAsync(this string url, string xml) { 
     return new FlurlClient(url, true).PostXmlAsync(xml); 
    } 
} 

MISE À JOUR:

j'ai décidé de ne pas inclure le support XML dans Flurl, en grande partie parce qu'un membre de la communauté a intensifié et a créé une grande bibliothèque d'extension pour cela:

https://github.com/lvermeulen/Flurl.Http.Xml

+0

Ha! Quel timing! – Mrchief

+0

Existe-t-il un moyen de spécifier un type de contenu "text/xml" lors de l'utilisation de cette bibliothèque d'extension? De la boîte, il semble que toutes les demandes soient marquées avec "application/xml". – user2710915

+0

@ user2710915 '.WithHeader (" Content-Type "," text/xml ") ...' –

1

Creuser à travers la source, il semble que SendAsync est en cours de développement. Depuis le dernier paquet ne supporte pas encore, je pensais à ajouter mon propre:

public static class FlurlHttpExtensions 
{ 
    /// <summary> 
    /// Sends an asynchronous POST request of specified data (usually an anonymous object or dictionary) formatted as XML. 
    /// </summary> 
    /// <param name="client">The FlurlClient</param> 
    /// <param name="serializedXml">Data to be serialized and posted.</param> 
    /// <returns>A Task whose result is the received HttpResponseMessage.</returns> 
    public static Task<HttpResponseMessage> PostXmlAsync(this FlurlClient client, string serializedXml) 
    { 
     var request = new HttpRequestMessage(HttpMethod.Post, client.Url.ToString()) 
     { 
      Content = new CapturedStringContent(serializedXml, Encoding.UTF8, "text/xml"), 
      Method = HttpMethod.Post 
     }; 
     return client.HttpClient.SendAsync(request); 
    } 
} 

Oui, je pris quelques raccourcis comme accepter un XML sérialisé au lieu de me sérialisation. En ce moment, cela fonctionne pour moi.

S'il y a une meilleure approche, je suis tout ouïe!

+1

Bon appel sur 'CapturedStringContent', j'ai oublié à ce sujet. J'ai trouvé que ça valait bien l'empreinte de la mémoire (typiquement) minuscule de pouvoir inspecter la postface du corps de la requête d'origine si quelque chose ne va pas. –

+0

Et oui, 'SendAsync' est en quelque sorte un travail en cours. Cela changera un peu le modèle d'extensibilité, donc vous n'aurez pas à faire l'essai/finalement/disposer vous-même. Je reviendrai et mettrai à jour ma réponse quand elle sera prête, mais cela ne fera pas casser cette implémentation. –

0

Pour mon scénario, j'ai juste besoin de POSTER une représentation sous forme de chaîne de mon XML tout en étant en mesure de définir le Content-Type à text/xml et l'encodage à utf-8. Je ne sais pas s'il y a une façon plus simple de ce faire, je ne suis pas voir, mais voici une méthode d'extension qui me est arrivé là:

public static class FlurlXmlExtensions 
    { 
     /// <summary> 
     /// Sends an asynchronous POST request that contains an XML string. 
     /// </summary> 
     /// <param name="client">The IFlurlClient instance.</param> 
     /// <param name="data">Contents of the request body.</param> 
     /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation. Optional.</param> 
     /// <param name="completionOption">The HttpCompletionOption used in the request. Optional.</param> 
     /// <returns>A Task whose result is the received HttpResponseMessage.</returns> 
     public static Task<HttpResponseMessage> PostXmlStringAsync(this IFlurlClient client, string data, CancellationToken cancellationToken = default(CancellationToken), HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead) 
     { 
      var content = new CapturedStringContent(data, Encoding.UTF8, "text/xml"); 

      return client.SendAsync(HttpMethod.Post, content: content, cancellationToken: cancellationToken, completionOption: completionOption); 
     } 

    } 
0

Je suis un peu en retard à cela, cependant, j'ai manged à utiliser Flurl nativement, avec Xml (a eu du mal avec l'extension xml)

Tout d'abord, prenez votre chaîne de données xml, convertir au contenu Html

var httpContent = new StringContent(xmlDateString, Encoding.UTF8, "text/xml"); 

alors, utilisez ce contenu dans un appel postasync normal.

var response = await "http://localhost/Notices/webservices/importer.asmx" 
     .WithHeader("Authorization", "Basic ssssserrrrr") 
     .WithHeader("Content-Type", "text/xml") 
     .WithHeader("SOAPAction", "\"http://tempuri.org/ImportData\"") 
     .PostAsync(httpContent); 

Dans cet appel, je définis le type de contenu. Je suis également en train de mettre en place l'action soap (c'est la méthode web que j'appelle).

Ensuite, cela fonctionne normalement.