【问题标题】:PostAsync in UWP App not working (no content sent)UWP 应用程序中的 PostAsync 不起作用(未发送内容)
【发布时间】:2016-11-14 15:48:30
【问题描述】:

我有点卡住了,我正在尝试创建一个将 XML 内容发布到 Web 服务的 UWP 应用程序。我可以让它在常规的 .net 控制台应用程序中正常工作。尝试使用 UWP 重新创建它被证明是棘手的。使用提琴手,我缩小了网络服务端点没有接收我的内容的范围。看起来标头设置正确,内容长度正确发送,但实际内容未发送。这是代码的核心,它在之后崩溃/抛出异常:

HttpResponseMessage ResponseMessage = await request.PostAsync(requestUri, httpContent2).ContinueWith(
                                    (postTask) => postTask.Result.EnsureSuccessStatusCode());

当我尝试执行 PostASync 时,看着提琴手,我得到:

HTTP/1.1 408 Request body incomplete
Date: Mon, 14 Nov 2016 15:38:53 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
Cache-Control: no-cache, must-revalidate
Timestamp: 10:38:53.430

请求正文未包含指定的字节数。得到 0,预期 617

我很肯定我得到了正确发布的内容(我从一个文件中读取它,我将它发送到调试窗口以验证它是否正确)。我认为这可能与 HttpContent httpContent2 有关 - 在常规的 .NET 中,我从来不需要使用它,但使用 PostAsync 我需要使用它。

任何想法都将不胜感激,谢谢!

    public async void PostWebService()
    {


        string filePath = "Data\\postbody.txt";
        string url = "https://outlook.office365.com/EWS/Exchange.asmx";

        Uri requestUri = new Uri(url); //replace your Url  

        var myClientHandler = new HttpClientHandler();
        myClientHandler.Credentials = new NetworkCredential("user@acme.com", "password");

        HttpClient request = new HttpClient(myClientHandler);

        string contents = await ReadFileContentsAsync(filePath);
        Debug.WriteLine(contents);

        HttpContent httpContent2 = new StringContent(contents, Encoding.UTF8, "text/xml");

        string s = await httpContent2.ReadAsStringAsync();
        Debug.WriteLine(s); //just checking to see if httpContent has the correct data

        //HttpResponseMessage ResponseMessage = await request.PostAsync(requestUri, httpContent);
        request.MaxResponseContentBufferSize = 65000;



        HttpResponseMessage ResponseMessage = await request.PostAsync(requestUri, httpContent2).ContinueWith(
                                    (postTask) => postTask.Result.EnsureSuccessStatusCode());

        Debug.WriteLine(ResponseMessage.ToString());

    }

【问题讨论】:

  • 我建议你使用像 Fiddler 这样的代理来获取整个请求,看看是否正确。
  • 我确实这样做了 - 这就是我知道它正在发送正确的内容大小但它没有发送实际的帖子数据的方式。
  • 复制了您的代码,我无法重现您的问题,您的代码似乎对我来说是正确的。你是如何让它在控制台应用程序中工作的?如果您将System.Net.Http 用于HttpClient,则UWP 应用中的代码应与控制台应用中的代码相同。
  • Grace 感谢您的尝试,我实际上发现这是一个错误,这是使用网络凭据时 System.Net.Http.HttpClient 中的一个已知错误。我将发布适当的回复,以便对其他人有所帮助。很好奇,你说它对你有用(看起来很奇怪——你构建的是哪个版本的 Windows 10?)。我应该澄清“在控制台应用程序中工作”的意思。在我的测试控制台应用程序中,我使用了 System.Net 和 HttpWebRequest。有兴趣了解它是如何工作的。

标签: c# uwp httpclient


【解决方案1】:

看来我找到了问题的根本原因。这似乎是使用网络身份验证时 System.Net.Http.HttpClient 的一个已知错误。看这篇文章here

我最初的错误是我没有捕获 PostAsync 引发的异常。一旦我将它包裹在一个 try/catch 块中,我就会抛出以下异常:

“此 IRandomAccessStream 不支持 GetInputStreamAt 方法,因为它需要克隆,而此流不支持克隆。”

我在上面链接的文章的第一段指出:

当您使用 .NET 中的 System.Net.Http.HttpClient 类时 基于框架的通用 Windows 平台 (UWP) 应用程序并发送 对需要集成 Windows 的 URI 的 HTTP(s) PUT 或 POST 请求 身份验证——如协商/NTLM,会抛出异常。

抛出的异常将有一个 InnerException 属性设置为 留言:

“这个 IRandomAccessStream 不支持 GetInputStreamAt 方法 因为它需要克隆,而此流不支持克隆。”

问题的发生是因为请求以及实体主体 认证过程中需要重新提交POST/PUT请求 挑战。 HTTP动词不会发生上述问题,例如 GET 不需要实体主体。

这是 Windows 10 SDK 的 RTM 版本中的一个已知问题,我们 正在为后续版本跟踪此问题的修复。

对我有用的建议和解决方法是使用 Windows.Web.Http.HttpClient 而不是 System.Net.Http.HttpClient

使用该建议,以下代码对我有用:

      string filePath = "Data\\postbody.txt";
            string url = "https://outlook.office365.com/EWS/Exchange.asmx";

            Uri requestUri = new Uri(url); //replace your Url  

            string contents = await ReadFileContentsAsync(filePath);
            string search_str = txtSearch.Text;

            Debug.WriteLine("Search query:" + search_str);
            contents = contents.Replace("%SEARCH%", search_str);

            Windows.Web.Http.Filters.HttpBaseProtocolFilter hbpf = new Windows.Web.Http.Filters.HttpBaseProtocolFilter();
            Windows.Security.Credentials.PasswordCredential pcred = new Windows.Security.Credentials.PasswordCredential(url, "username@acme.com", "password");
            hbpf.ServerCredential = pcred;
             
            HttpClient request = new HttpClient(hbpf);

            Windows.Web.Http.HttpRequestMessage hreqm = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Post, new Uri(url));
            Windows.Web.Http.HttpStringContent hstr = new Windows.Web.Http.HttpStringContent(contents, Windows.Storage.Streams.UnicodeEncoding.Utf8, "text/xml");
            hreqm.Content = hstr;

            // consume the HttpResponseMessage and the remainder of your code logic from here.


            try
            {
                Windows.Web.Http.HttpResponseMessage hrespm = await request.SendRequestAsync(hreqm);

                Debug.WriteLine(hrespm.Content);
                String respcontent = await hrespm.Content.ReadAsStringAsync();

            }
            catch (Exception ex)
            {
                string e = ex.Message;
                Debug.WriteLine(e);
            }

希望这对遇到此问题的其他人有所帮助。

【讨论】:

    猜你喜欢
    • 2018-08-19
    • 2017-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-19
    • 2018-10-23
    • 1970-01-01
    相关资源
    最近更新 更多