【问题标题】:WebService Post is working on emulator but not on deviceWebService Post 正在模拟器上工作,但不在设备上
【发布时间】:2016-06-03 12:42:45
【问题描述】:

我正在尝试通过 SSL 认证将数据发布到 WebService。 它在模拟器中运行良好,但设备一直停留在GetResponseAsync()。我在有和没有 ModernHttpClient-Library 的情况下使用 HttpClient 进行了尝试,但它卡在PostAsync() 上,所以它也不起作用。

我尝试过的另一个线程的一个解决方案就是添加

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
        (sender, cert, chain, sslPolicyErrors) => true;

^但它也不起作用

在清单中我添加了 Internet 权限。

这就是GetResponseAsync()的代码

    public async Task<Response<V>> CallWebServiceAsync<T, V>(string ticket, string url, T requestData)
    {
        try
        {
            var request = new Request<T>
            {
                Ticket = ticket,
                Data = requestData
            };

            DataContractJsonSerializer serializer = new DataContractJsonSerializer(request.GetType(), this._knownTypes);

            var httpRequest = WebRequest.CreateHttp(url);
            httpRequest.Method = "POST";
            httpRequest.UseDefaultCredentials = true;
            httpRequest.ContentType = "application/json";

            var requestStream = await httpRequest.GetRequestStreamAsync().ConfigureAwait(false);
            serializer.WriteObject(requestStream, request);

            var response = await httpRequest.GetResponseAsync().ConfigureAwait(false);

            var resultStream = response.GetResponseStream();
            if (resultStream == null)
            {
                throw new FailedWebServiceInteractionException($"Got no response stream from request. URL:{url}");
            }

            var jsonResponseSerializer = new DataContractJsonSerializer(typeof(Response<V>), this._knownTypes);

            Response<V> result = (Response<V>)jsonResponseSerializer.ReadObject(resultStream);

            resultStream.Dispose();
            return result;
        }
        catch (Exception e)
        {
            throw new FailedWebServiceInteractionException("Deserialization from json response failed", e);
        }
    }

带有PostAsync() 的代码 (+- ModernHttpClient)

    public async Task<Response<V>> CallWebServiceAsync<T, V>(string ticket, string url, T requestData)
    {
        try
        {
            var request = new Request<T>
            {
                Ticket = ticket,
                Data = requestData
            };

            var httpClientHandler = new NativeMessageHandler
            {
                UseDefaultCredentials = true
            };

            var httpRequest = new HttpClient(httpClientHandler)
            {
                BaseAddress = new Uri(url)
            };

            httpRequest.DefaultRequestHeaders.Accept.Clear();
            httpRequest.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            var content = JsonConvert.SerializeObject(request);

            var response =
                await
                    httpRequest.PostAsync(url, new StringContent(content, Encoding.UTF8, "application/json"))
                        .ConfigureAwait(false);

            var jsonString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

            return JsonConvert.DeserializeObject<Response<V>>(jsonString);
        }
        catch (Exception e)
        {
            throw new FailedWebServiceInteractionException("Deserialization from json response failed", e);
        }
    }

我不知道证书是问题还是其他原因。 它们不是自签名的。

【问题讨论】:

  • 您对此有什么解决方案吗?我遇到了同样的问题。
  • 在下面发布解决方案

标签: c# android web-services ssl xamarin


【解决方案1】:

我找到了解决方案。从那以后时间已经过去了。我不知道确切的解决方案,但这是我现在可以正常工作的代码:

var request = new Request<T>
            {
                Ticket = ticket,
                Data = requestData
            };

            var httpClientHandler = new OkHttpClientHandler
            {
                UseDefaultCredentials = true,
                AllowAutoRedirect = true,
                AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
                ClientCertificateOptions = ClientCertificateOption.Automatic
            };

            var client = new HttpClient(httpClientHandler)
            {
                BaseAddress = new Uri(url),
                Timeout = TimeSpan.FromSeconds(15)
            };

            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));


            var jsonRequest = this.SerializeToJson(request);

            var compressedRequest = StringCompressor.CompressString(jsonRequest);
            var httpRequest = new HttpRequestMessage(HttpMethod.Post, url)
            {
                Content = new ByteArrayContent(compressedRequest)
                {
                    Headers = {ContentType = new MediaTypeHeaderValue("application/json")}
                }
            };

            var httpResponse = await client.SendAsync(httpRequest, cancellationToken).ConfigureAwait(false);
            client.Dispose();
            httpResponse.EnsureSuccessStatusCode();

            var compressedResponse = await httpResponse.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
            httpResponse.Dispose();

            var jsonResponse = StringCompressor.DecompressString(compressedResponse);

            var jsonResponseSerializer = new DataContractJsonSerializer(typeof(Response<V>), this._knownTypes);
            Response<V> result;
            using (var jsonResponseStream = this.GenerateStreamFromString(jsonResponse))
            {
                result = (Response<V>) jsonResponseSerializer.ReadObject(jsonResponseStream);
            }

            return result;

我正在使用 OkHttpClient 库的自编译包装器。我认为 ModernHttpClient(它也引用了 OkHttp)也可以。有人需要测试它。

重要的是要知道引用该项目的任何其他项目也需要该库。

  • App.Base 项目 - 实现了上述代码以连接到 网络服务
  • App 项目 - 对 App.Base 的引用。需要图书馆 也是。

【讨论】:

    猜你喜欢
    • 2011-04-14
    • 1970-01-01
    • 2012-08-19
    • 2023-03-23
    • 2012-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多