c# - UWP 应用程序中的 PostAsync 不起作用(未发送内容)

标签 c# uwp httpclient

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

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("<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="62171107102203010f074c010d0f" rel="noreferrer noopener nofollow">[email protected]</a>", "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());

    }

最佳答案

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

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

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

我链接到的文章的第一段指出:

When you use the System.Net.Http.HttpClient class from a .NET framework based Universal Windows Platform (UWP) app and send a HTTP(s) PUT or POST request to a URI which requires Integrated Windows Authentication – such as Negotiate/NTLM, an exception will be thrown.

The thrown exception will have an InnerException property set to the message:

“This IRandomAccessStream does not support the GetInputStreamAt method because it requires cloning and this stream does not support cloning.”

The problem happens because the request as well as the entity body of the POST/PUT request needs to be resubmitted during the authentication challenge. The above problem does not happen for HTTP verbs such as GET which do not require an entity body.

This is a known issue in the RTM release of the Windows 10 SDK and we are tracking a fix for this issue for a subsequent release.

对我有用的建议和解决方法是使用 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, "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="11646274637f707c745170727c743f727e7c" rel="noreferrer noopener nofollow">[email protected]</a>", "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);
            }

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

关于c# - UWP 应用程序中的 PostAsync 不起作用(未发送内容),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40592683/

相关文章:

c# - socket VLI(可变长度指示器)

c# - 如何正确请求 Azure 不记名 token 或为什么它要求我发送 "scope"参数?

c# - 具有 .Net Core Identity 的 Multi-Tenancy DbContext 的 IoC DI

java - 何时为 apache httpclient 调用 ServiceUnavailableRetryStrategy

Angular 4 HttpInterceptor : show and hide loader

c# - 如何抽象(使用Func?)部分功能

Xamarin.Forms map 自动关注用户位置

xaml - 通过绑定(bind)更改 TextBox 文本时启动 Storyboard

c# - 无法从 UWP 应用程序中的 2 个串行设备读取

java - HttpClient 状态代码