Vin*_*nod 6 c# asp.net-mvc-4 asp.net-web-api dotnet-httpclient iis-8
我正在使用 HttpClient 调用 Web Api REST 端点,偶尔我会看到一个随机的 401 未授权状态。
这是我的 HttpClient 包装器,它是为可重用性目的而创建的。我已经修改了它以保持这篇文章的简单而不修改核心部分。
public class HttpHelper
{
public const string JsonContentType = "application/json";
public T PostAsJsonObject<T>(string uri, T t) where T : class
{
using (HttpResponseMessage response = PostJsonHttpRequest(uri, JsonContentType, t))
{
response.EnsureSuccessStatusCode();
return response.Content.ReadAsAsync<T>().Result;
}
}
private HttpResponseMessage PostJsonHttpRequest<T>(string uri, string contentType, T content) where T : class
{
if (String.IsNullOrEmpty(uri))
{
throw new ArgumentNullException("uri");
}
HttpResponseMessage response = CreateHttpClient(contentType).PostAsJsonAsync(uri, content).Result;
return response;
}
private HttpClient CreateHttpClient(string contentType)
{
var credentials = new NetworkCredential("srvuser", "somepwd", "somedomain");
return new HttpClient(new HttpClientHandler { Credentials = credentials, PreAuthenticate = true });
}
}
Run Code Online (Sandbox Code Playgroud)
这是我调用它的方式。
var httpHelper = new HttpHelper();
var response = httpHelper.PostAsJsonObject("https://xyz.pvt/inventory/api/orders", "234");
Run Code Online (Sandbox Code Playgroud)
大多数情况下它工作正常,但偶尔我会收到 401 Unauthorized 错误。我试图找出可能导致它的原因。
System.Net.Http.HttpRequestException:响应状态代码未指示成功:401(未经授权)。在 System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() 在 HttpHelper.PostAsJsonObject[T](String uri, T t)
我查看了asp.net日志,发现了一个奇怪的模式。大多数情况下,我会看到一对条目(401 后跟 200 OK),例如
2017-02-09 12:04:13 104.68.45.152 POST /inventory/api/orders/ - 80 - 132.64.78.120 HTTP/1.1 - 401 2 5 764
2017-02-09 12:04:16 104.68.45.152 POST /inventory/api/orders/ - 80 somedomain\srvusr 132.64.78.120 HTTP/1.1 - 200 0 0 2917
2017-02-09 12:04:16 104.68.45.152 POST /inventory/api/orders/ - 80 - 132.64.78.120 HTTP/1.1 - 401 2 5 0
2017-02-09 12:04:19 104.68.45.152 POST /inventory/api/orders/ - 80 somedomain\srvusr 132.64.78.120 HTTP/1.1 - 200 0 0 2230
Run Code Online (Sandbox Code Playgroud)
但偶尔我只看到 401
2017-02-09 12:14:04 104.68.45.152 POST /inventory/api/orders/ - 80 - 132.64.78.120 HTTP/1.1 - 401 2 5 0
Run Code Online (Sandbox Code Playgroud)
REST api 是使用在 .NET 4.6.1 和 IIS 7.5 上运行的 ASP.NET Web Api 2 实现的,它仅使用 Windows 身份验证进行设置。
不确定是什么导致身份验证偶尔失败。
更新:
这是我使用异步等待模式编写的新代码。
public class HttpHelper
{
public const string JsonContentType = "application/json";
private HttpClient CreateHttpClient(string url, string contentType)
{
var handler = new HttpClientHandler
{
Credentials = new CredentialCache { { new Uri(url), "NTLM", new NetworkCredential("srvuser", "somepwd", "somedomain") } },
PreAuthenticate = true
};
var httpClient = new HttpClient(handler);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(contentType));
return httpClient;
}
private async Task<HttpResponseMessage> PostJsonHttpRequestAsync<T>(string url, string contentType, T content) where T : class
{
if (string.IsNullOrEmpty(url))
{
var exception = new ArgumentNullException("url");
throw exception;
}
var response = await CreateHttpClient(url, contentType).PostAsJsonAsync(url, content);
return response;
}
public async Task<T> PostAsJsonObjectAsync<T>(string uri, T t) where T : class
{
using (var response = await PostJsonHttpRequestAsync(uri, JsonContentType, t))
{
return await response.Content.ReadAsAsync<T>(new[]
{
new JsonMediaTypeFormatter
{
SerializerSettings = { NullValueHandling = NullValueHandling.Ignore, TypeNameHandling = TypeNameHandling.Auto }
}
}.AsEnumerable());
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我最终调用它的方式。
static class TestMe
{
static void Main()
{
var httpHelper = new HttpHelper();
var responseTask = httpHelper.PostAsJsonObjectAsync("https://xyz.pvt/inventory/api/orders", "234");
responseTask.Wait(120000);
var response = responseTask.Result;
Console.WriteLine(response);
}
}
Run Code Online (Sandbox Code Playgroud)
即使现在我也看到同样的问题。仍然随机出现 401 Unauthorized 错误。
更新 2
我做了更多调查,发现这些神秘的 401 错误来自 IIS。当这些神秘的 401 错误发生时,IIS 日志中有一个相应的 401 错误条目,但在这种情况下,请求永远不会到达 asp.net 管道。好像出于某种原因,请求被 IIS 以 401 错误退回。
无需深入研究,我知道 IIS 中的 Windows 身份验证使用 2 个请求来管理基于 HttpClient 的配置方式的身份验证。因此,成功的身份验证请求将具有 401.2 后跟 200 OK。这是大多数时候发生的事情。有时你我会注意到有一个 401.2,然后是 401。重试时相同的请求会通过(401.2 后跟 200 OK)。
如果有人对这个问题有一些洞察力和潜在的解决方案,真的很感激。
Joe*_*rby -2
您确定您的代码是问题所在吗?我不知道您的具体情况,但网络服务器有时可能会无缘无故地向您发送 401 响应。
您可以执行以下操作来测试该理论:同时运行程序的两个(或更多)实例,最好是在不同的机器上。等到出现 401 错误为止。如果代码的所有实例同时开始收到 401 错误,那么几乎可以肯定是 Web 服务器上出现了问题。