UWP App中的PostAsync无法正常工作(未发送内容)

时间:2016-11-14 15:48:31

标签: c# uwp httpclient

我有点卡住,我正在尝试创建一个将XML内容发布到Web服务的UWP应用程序。我可以在常规.net控制台应用程序中使用它而不会出现问题。试图使用UWP重新创建它被证明是棘手的。使用fiddler我已经缩小了Web服务端点没有收到我的内容。看起来标题设置正确,内容长度正确发送但实际内容未发送。这是代码的核心,它在以下情况下崩溃/抛出异常:

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

当我尝试执行PostASync时,看着fiddler,我得到了:

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

    }

1 个答案:

答案 0 :(得分:2)

好像我找到了问题的根本原因。使用网络身份验证时,这似乎是System.Net.Http.HttpClient的已知错误。请参阅此文here

我最初的错误是我没有抓住PostAsync抛出的异常。一旦我把它包装在try / catch块中,我就抛出了以下异常:

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

我上面链接的文章的第一段说明:

  

当您使用.NET中的System.Net.Http.HttpClient类时   基于框架的通用Windows平台(UWP)应用程序并发送   HTTP(s)对需要集成Windows的URI的PUT或POST请求   身份验证 - 例如Negotiate / 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);
            }

希望这有助于遇到此问题的其他人。