【问题标题】:How to do XML POST with FlUrl如何使用 FluUrl 进行 XML POST
【发布时间】:2015-03-10 18:06:41
【问题描述】:

FlUrl 在处理 Json/UrlEncoded 请求方面做得很好。但是,文档并没有真正指出如何处理其他请求类型,例如 text/xml

使用 FluUrl 进行 XML POST 的最佳方式是什么?

这(访问底层HttpClient)有点违背了使用FlUrl的目的,因为您需要再次构建URI和内容:

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

【问题讨论】:

    标签: c# c#-5.0 dotnet-httpclient flurl


    【解决方案1】:

    XML 支持尚未推出,但这是logged,是我希望为 Flurl.Http 1.0 提供的为数不多的剩余功能之一。 (令人惊讶的是,直到现在还没有人提出要求。)

    与此同时,Flurl is pretty easy to extend,您可以通过扩展方法自己添加此支持。这应该是您流畅地发布 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);
        }
    }
    

    更新:

    我决定不在 Flurl 中包含 XML 支持,主要是因为社区成员站出来为它创建了一个很棒的扩展库:

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

    【讨论】:

    • 在使用此扩展库时,是否可以指定 Content-Type 为“text/xml”?开箱即用,看起来所有请求都标有“application/xml”。
    • @user2710915 .WithHeader("Content-Type", "text/xml")...
    【解决方案2】:

    通过源代码挖掘,似乎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 而不是序列化自己。目前,这对我有用。

    如果有更好的方法,我会全力以赴!

    【讨论】:

    • 请致电CapturedStringContent,我忘记了。我发现如果出现任何问题,那么(通常)很小的内存占用能够检查原始请求正文是非常值得的。
    • 是的,SendAsync 正在进行中。它会稍微改变可扩展性模式,因此您不必自己执行 try/finally/dispose 部分。准备好后,我会回来更新我的答案,但这不会导致此实现中断。
    【解决方案3】:

    我对此有点晚了,但是,我已经设法将 Flurl 与 Xml 一起使用(xml 扩展有问题)

    首先,获取你的 xml 数据字符串,将其转换为 Html 内容

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

    然后,在正常的 postasync 调用中使用该内容。

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

    在此调用中,我正在设置内容类型。我也在设置肥皂动作(这是我正在调用的网络方法)。

    然后它就正常工作了。

    【讨论】:

    • payload为Encoding.UTF8, "text/xml"时是否需要设置Content-Type header?
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      对于我的场景,我只需要 POST 我的 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);
              }
      
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-06-04
        • 2016-11-29
        • 2020-09-29
        • 1970-01-01
        • 2012-09-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多