【问题标题】:C# in UWP: HTTP Get returns error while the browser returns a correct valueUWP 中的 C#:HTTP Get 返回错误,而浏览器返回正确的值
【发布时间】:2021-10-19 17:12:01
【问题描述】:

我有一个用 C# 编写的 UWP 应用。

对于某些特定用户(即特定 PC),该应用无法执行 HTTP 请求。

那些电脑没有使用任何 VPN,他们关闭了任何防火墙或防病毒软件,他们尝试了多个连接(例如家庭路由器、电话热点、公共 wifi 等),但结果总是相同。

打开浏览器并浏览到

https://ltbackend.azurewebsites.net/diagnostic/ping

他们能够看到正确的页面(实际上是纯文本“OK”)。

但如果他们使用应用程序(使用 C# 执行 HTTP GET 调用),则此应用程序会失败。

这是我们使用的 C# 代码:

string pingUrl = "https://ltbackend.azurewebsites.net/diagnostic/ping";
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Get, pingUrl);
using (HttpClient httpClient = new HttpClient())
{
 try
 {
  using (HttpResponseMessage response = await httpClient.SendAsync(req))
  {
    string stringRes = await response.Content.ReadAsStringAsync();
    HttpStatusCode respCode = response.StatusCode;

    // .... our biz logic with stringRes and respCode...
  }
 }
 catch (HttpRequestException e)
 {
    // the ping request for those users throws this exception...
    // the error message is "An error occurred while sending the request."
 }
}

【问题讨论】:

  • 可能有很多东西 - 寻找某些 tls 版本、标头、用户代理等。作为响应,您究竟会得到什么?你的uwp有权限使用网络吗?
  • 通常,这可以工作(对于遍布全球的数十万个安装),但对于那些特定的设备,我们实际上没有得到响应,我们得到一个带有消息“发送时发生错误”的 HttpRequestException请求。”
  • 不要创建/处理大量的 HttpClient。跨请求重用它们。系统时钟是否同步?错误的时钟可能会导致误报 ssl 故障。他们的浏览器是否使用代理?

标签: c# networking uwp httprequest


【解决方案1】:

但如果他们使用应用程序(使用 C# 执行 HTTP GET 调用),则此应用程序会失败。

我已经在 UWP 平台上运行了您的代码,它可以正常运行并返回“ok”字符串。不过貌似你在System.Net.Http命名空间下使用了HttpClient,而且经常用在跨平台,比如xamarin app。

对于在 UWP 中发送 get 请求,我们建议您使用Windows.Web.Http.HttpClient。下面是简单的get方法,大家可以参考一下。

Windows.Web.Http.HttpClient httpClient = new Windows.Web.Http.HttpClient();

//Add a user-agent header to the GET request. 
var headers = httpClient.DefaultRequestHeaders;

//The safe way to add a header value is to use the TryParseAdd method and verify the return value is true,
//especially if the header value is coming from user input.
string header = "ie";
if (!headers.UserAgent.TryParseAdd(header))
{
    throw new Exception("Invalid header value: " + header);
}

header = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)";
if (!headers.UserAgent.TryParseAdd(header))
{
    throw new Exception("Invalid header value: " + header);
}

Uri requestUri = new Uri("https://ltbackend.azurewebsites.net/diagnostic/ping");

//Send the GET request asynchronously and retrieve the response as a string.
Windows.Web.Http.HttpResponseMessage httpResponse = new Windows.Web.Http.HttpResponseMessage();
string httpResponseBody = string.Empty;
try
{
    //Send the GET request
    httpResponse = await httpClient.GetAsync(requestUri);
    httpResponse.EnsureSuccessStatusCode();
    httpResponseBody = await httpResponse.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
    httpResponseBody = "Error: " + ex.HResult.ToString("X") + " Message: " + ex.Message;
}

更多信息请参考HttpClient文档。

【讨论】:

  • 也试过这种方法,没用:(还有其他想法吗?难道是UWP应用的权限有问题?我还没有找到任何方法让用户更改这些虽然权限....
  • 出于权限原因,您可以检查是否为您的应用启用互联网功能。
  • 我们确实在 Manifest 中启用了该功能(事实上,几乎所有其他用户都能够完美地连接到我们的服务器)。但我注意到的是,在目标客户端中打开应用程序设置,在“应用程序权限”部分下,我看不到 Internet 功能切换,只有“文件系统”和“后台应用程序”(在我们的清单中正确列出)
  • 互联网功能不会在应用权限中列出,这是设计使然。
  • 那么,您建议如何解决我们少数用户无法通过 HTTP 调用访问任何远程位置的问题?
【解决方案2】:

如果您使用的是最新版本的 .NET,请尝试使用 WebClient 而不是 HttpClient。 参考:https://docs.microsoft.com/en-us/dotnet/api/system.net.webclient.downloadstringasync?view=net-5.0

string pingUrl = "https://ltbackend.azurewebsites.net/diagnostic/ping";
var client = new WebClient();
string stringRes = await client.DownloadStringTaskAsync(pingUrl);

【讨论】:

  • 感谢@Sudhanshu,但我们不能在我们的项目中使用 .net5.0。我们在一个 UWP 项目中,我们还有一个带有 .NET STandard 2.0 的库
猜你喜欢
  • 2019-09-22
  • 1970-01-01
  • 2015-05-15
  • 1970-01-01
  • 2018-06-19
  • 2021-04-06
  • 2018-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多