Как сделать XML POST с FlUrl

FlUrl отлично справляется с запросами Json/UrlEncoded. Однако в документации не указано, как обрабатывать другие типы запросов, такие как text/xml.

Как лучше всего выполнить XML POST с помощью FlUrl?

Это (доступ к базовому HttpClient) как бы противоречит цели использования FlUrl, поскольку вам нужно снова создать URI и контент:

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

person Mrchief    schedule 10.03.2015    source источник


Ответы (5)


Поддержка XML еще не встроена, но это зарегистрировано и является одним из немногих остальные функции, которые я хотел бы иметь для Flurl.Http 1.0. (Удивительно, но до сих пор об этом никто не просил.)

Между тем, Flurl довольно легко расширить, и вы можете добавить эту поддержку самостоятельно через методы расширения. Это должно быть все, что вам нужно для быстрой публикации строки 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);
    }
}

ОБНОВЛЕНИЕ:

Я решил не включать поддержку XML во Flurl, в основном потому, что один из членов сообщества создал для него отличную библиотеку расширений:

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

person Todd Menier    schedule 10.03.2015
comment
Есть ли способ указать тип содержимого text/xml при использовании этой библиотеки расширений? Из коробки выглядит так, что все запросы помечены тегом application/xml. - person Matt Koch; 17.03.2017
comment
@user2710915 .WithHeader("Content-Type", "text/xml")... - person Todd Menier; 17.03.2017

Копаясь в источнике, кажется, что работа над SendAsync продолжается. Поскольку последний пакет еще не поддерживает его, я подумал добавить свой собственный:

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);
    }
}

Да, я использовал некоторые ярлыки, такие как принятие сериализованного XML вместо сериализации себя. На данный момент это работает для меня.

Если есть лучший подход, я весь внимание!

person Mrchief    schedule 10.03.2015
comment
Хороший звонок на CapturedStringContent, я забыл об этом. Я обнаружил, что стоит (как правило) крошечный объем памяти, чтобы иметь возможность проверить исходное послесловие тела запроса, если что-то пойдет не так. - person Todd Menier; 11.03.2015
comment
И да, SendAsync находится в стадии разработки. Это немного изменит шаблон расширяемости, поэтому вам не придется самостоятельно выполнять часть try/finally/dispose. Я вернусь и обновлю свой ответ, когда он будет готов, но это не приведет к поломке этой реализации. - person Todd Menier; 11.03.2015

Я немного опоздал к этому, однако мне удалось использовать Flurl изначально с Xml (были проблемы с расширением xml)

Сначала возьмите строку данных xml, преобразуйте ее в содержимое Html.

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

затем используйте этот контент в обычном постасинхронном вызове.

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);

В этом вызове я устанавливаю тип контента. Я также устанавливаю действие мыла (это веб-метод, который я вызываю).

Потом работает как обычно.

person Ashley Jackson    schedule 05.12.2017
comment
Нужно ли устанавливать заголовок Content-Type, когда полезной нагрузкой является Encoding.UTF8, text/xml? - person Pepster; 04.06.2019

Исправление для FlurlRequest

public static class FlurlXmlExtensions
{
    // chain off an existing FlurlRequest:
    public static async Task<HttpResponseMessage> PostXmlAsync(this IFlurlRequest fr, string xml)
    {
        var content = new CapturedStringContent(xml, Encoding.UTF8, "application/xml");
        return await fr.PostAsync(content);
    }

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

    // chain off a url string:
    public static Task<HttpResponseMessage> PostXmlAsync(this string url, string xml)
    {
        return new FlurlRequest(url).PostXmlAsync(xml);
    }
}
person codepen    schedule 21.08.2020

Для моего сценария мне просто нужно было отправить строковое представление моего XML, в то же время имея возможность установить Content-Type на text/xml и кодировку на utf-8. Не уверен, что есть более простой способ сделать это, я просто не вижу, но вот метод расширения, который привел меня туда:

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);
        }

    }
person Matt Koch    schedule 17.03.2017