【发布时间】:2017-09-14 16:21:13
【问题描述】:
我有一个 C# 控制台应用程序,它必须创建一个 HttpClient 并向我们的“3CX 电话系统管理”门户网站发出一些请求(我必须检索/更改我们员工的电话状态)。为此,我必须登录,将收到的 cookie 保存到 CookieContainer 中,然后继续处理必须使用相同 cookie 的其他请求。代码如下:
public static CookieContainer cookies = null;
public static HttpClientHandler handler = new HttpClientHandler();
static void Main(string[] args) {
Task.Run(() => ExtListAsync());
Console.ReadLine();
}
static async Task<bool> LoginAsync() {
try {
cookies = new CookieContainer();
handler = new HttpClientHandler();
handler.CookieContainer = cookies;
using (HttpClient client = new HttpClient(handler, disposeHandler: false)) {
client.BaseAddress = new Uri("https://my.uri.com:5001");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
StringContent parameters = new StringContent(@"{""key"":""value"",""key2"":""value2""}", Encoding.UTF8, "application/json");
// BLOCKS HERE....
using (HttpResponseMessage response = await client.PostAsync("/api/other", parameters).ConfigureAwait(false)) {
using (HttpContent content = response.Content) {
string responseContent = content.ReadAsStringAsync().Result;
var responseCookies = cookies.GetCookies(uri).Cast<Cookie>();
if (responseCookies.Count() > 0)
{
return true;
}
else
{
return false;
}
}
}
}
} catch (HttpRequestException ex) {
Console.WriteLine("\n\r EXCEPTION MESSAGE: " + ex.Message);
Console.WriteLine("\n\r DATA: " + ex.Data);
Console.WriteLine("\n\r InnerException: " + ex.InnerException);
Console.WriteLine("\n\r Source: " + ex.Source);
Console.WriteLine("\n\r StackTrace: " + ex.StackTrace);
Console.WriteLine("\n\r TargetSite: " + ex.TargetSite);
return true;
}
}
static async Task ExtListAsync() {
bool loggedIn = await LoginAsync();
if (loggedIn) { ... }
}
我有这个简单的代码,用 Visual Studio 启动的“开始调试”可以正确执行。 如果我尝试从命令提示符启动 .exe(也尝试使用管理员模式),有时应用程序会在稍有延迟的情况下正确执行,但在大多数情况下,它仍会在“await client.PostAsync(...) "... ,然后抛出一个 HttpRequestException:
EXCEPTION MESSAGE: An error occurred while sending the request.
DATA: System.Collections.ListDictionaryInternal
InnerException: System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond xxx.xxx.xxx.xxx:5001
at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult)
at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context)
at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
Source: mscorlib
StackTrace: at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at statusmng3cx.Program.<LoginAsync>d__15.MoveNext() in ...\myPath\Program.cs:line 254
TargetSite: Void Throw()
有人对此有解释吗? 提前谢谢你。
更新:
我也尝试添加 SSL 证书:
WebRequestHandler whandler = new WebRequestHandler();
whandler.ClientCertificateOptions = ClientCertificateOption.Manual;
var pem = System.IO.File.ReadAllText("mycert.pem");
byte[] certBuffer = GetBytesFromPEM(pem, "CERTIFICATE");
X509Certificate2 certificate = new X509Certificate2(certBuffer);
whandler.ClientCertificates.Add(certificate);
using (var httpClient = new HttpClient(whandler)) { ... as above ... }
并且发生了同样的事情:通过调试它完美地工作: 状态码 200,ReasonPhrase: 'OK', responseContent: AuthSuccess, ...
通过提示,.exe 不会协作。但是如果我将 3CX 门户 URL 更改为另一个简单的网站,该网站检索静态网页(没有 SSL),.exe 可以完美运行。
【问题讨论】:
-
您是否设置了任何必需的请求标头?服务器上是否有 SSL 转发?
-
实际上没有,但是如果我尝试使用 Postman 复制相同的 POST/GET 请求,它可以在没有任何 SSL 标头或证书的情况下运行良好。我已经用 Chrome 网络检查器嗅探了这些请求。
-
您在 Fiddler 中看到了什么?它在调试/邮递员中有效,但在通过 exe 运行时无效,这绝对是奇怪的。出于好奇,你是在为 Release 做准备吗?
-
我还没有尝试过使用 Fiddler.. 但是我尝试在调试/发布中为 x64/任何 CPU 的任何组合构建它.. 前 2-3 次它可以工作,然后它抛出 HttpRequestException。服务器是我们的“3CX 电话系统管理”门户,我必须检索我们的员工状态..
-
@Jakasha 这是因为您在 async/await 中混合了阻塞调用 (
.Result),这可能导致死锁。代码需要一直异步。
标签: c# post cookies visual-studio-2015 httpclient