2017-09-14 16 views
1

我有一個C#控制檯應用程序必須創建一個HttpClient並向我們的「3CX電話系統管理」門戶網站(我必須檢索/更改我們的員工電話狀態)發出一些請求。爲此,我必須登錄,將收到的Cookie保存到CookieContainer中,然後繼續使用其他請求使用相同的Cookie。這裏的代碼:C# - 爲什麼HttpClient PostAsync在.exe中阻止,但與Visual Studio 2015一起工作 - >調試?

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(也嘗試使用Admin模式),有時應用程序會稍微延遲一段時間才能正確執行,但在大多數情況下,它仍會在「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() 

有人對此有解釋嗎? 預先感謝您。

UPDATE:

我也嘗試添加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完美運行。

+0

你設置任何所需的請求頭?服務器上是否存在SSL轉發? – DiskJunky

+0

實際上沒有,但是如果我嘗試用Postman複製相同的POST/GET請求,它在沒有任何SSL頭或證書的情況下運行良好。我通過Chrome Network檢查員嗅探了這些請求。 – Jakasha

+0

你在小提琴手中看到了什麼?它在調試/郵遞員中工作,但在通過exe運行時無法工作。出於好奇,你是否在爲發佈而建設? – DiskJunky

回答

0

最後我用Java編寫了程序,它可以從控制檯完美地工作。

try { 
     TrustStrategy acceptingTrustStrategy = new TrustStrategy() { 
      public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
       return true; 
      } 
     }; 

     SSLContextBuilder builder = new SSLContextBuilder(); 
     builder.loadTrustMaterial(null, acceptingTrustStrategy); 
     SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build()); 

     HttpClientContext context = HttpClientContext.create(); 
     CookieStore cookieStore = new BasicCookieStore(); 
     context.setCookieStore(cookieStore); 

     CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultRequestConfig(RequestConfig.custom() 
       .setCookieSpec(CookieSpecs.STANDARD).build()).setDefaultCookieStore(cookieStore).build(); 


     HttpPost request = new HttpPost(mainUrl + loginUrl); 
     StringEntity params = new StringEntity("myJson"); 
     request.addHeader("content-type", "application/json"); 
     request.setEntity(params); 
     HttpResponse response = httpClient.execute(request, context); 

     System.out.println("Response getStatusLine: " + 

     response.getStatusLine()); 
    } catch (...) { ... } 

和輸出:

Response getStatusLine: HTTP/1.1 200 OK 
相關問題