c# - HttpWebRequest .GetResponse 抛出 WebException 'The operation has timed out'

标签 c# asp.net asp.net-mvc rtc rational-team-concert

我一直在从事一个使用 RTC API 和表单例份验证的项目。我遇到了一些奇怪的行为,但我无法弄清楚这一点。

目前已经上演的场景是我可以在本地端到端地成功运行这个项目。也就是说,这段特定的代码可以:

  1. 联系远程服务器并成功验证
  2. 身份验证后,我可以通过 XML 来更新 RTC 中的票证

当我发布到我们的 IIS (7.5) 服务器时,问题就开始了。一切正常,直到最后一次 .GetResponse 调用使用 PUT 方法传递我的 XML 以更新 RTC 中的票证。我不断收到“操作超时”。

我花了好几天时间试图弄清楚这个问题,做了各种各样的事情,但事实证明没有任何用处。

作为测试,我在第二次调用时将 PUT 方法更改为 GET。它有效!如果我将 PUT 与 .AllowAutoRedirect = false 一起使用,它的工作原理是我会收到回复,但是 RTC 端没有任何反应,因此请求显然被忽略了。我还注意到返回的状态被标记为“找到”而不是“确定”。

有些人在这个阶段认为可能是远程服务器和网络服务器之间缺乏连接。情况并非如此,因为身份验证有效,而且这种情况发生在同一台服务器上。我还使用 Web 服务器上的 RESTClient 手动传递了 XML/PUT 调用,这被接受了。

我只是不明白为什么它在本地运行时端到端工作,但一旦部署到 IIS 就发挥作用?

我尝试使用日志跟踪,但我不完全确定我是否从中获得了任何有用的信息。它可能完全不相关,但我可以在 IIS 服务器上生成的日志中看到这一点:

<EventData>
  <Data Name="ContextId">{00000000-0000-0000-12AF-0080000000F8}</Data>
  <Data Name="ModuleName">ManagedPipelineHandler</Data>
  <Data Name="Notification">128</Data>
  <Data Name="HttpStatus">500</Data>
  <Data Name="HttpReason">Internal Server Error</Data>
  <Data Name="HttpSubStatus">0</Data>
  <Data Name="ErrorCode">0</Data>
  <Data Name="ConfigExceptionInfo"></Data>
 </EventData>

正如我所说,我不确定这是否与我遇到的问题有关,但与其忽略它,我想我会分享。

形成调用的代码(请原谅编码标准,它正在进行中并且尝试不同的东西来解决这个问题变得困惑)

  //Setup webrequest
                CookieContainer _cookies = new CookieContainer();
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(getPath);
                var test44 = test4.ToString();

                request.CookieContainer = _cookies;
                request.ContentType = "application/rdf+xml";
                request.Accept = "application/rdf+xml";
                request.Method = "PUT";
                request.AllowAutoRedirect = true;
                request.AllowWriteStreamBuffering = true;
                request.Timeout = 40000;


                byte[] bytes = Encoding.ASCII.GetBytes(test44);
                request.ContentLength = bytes.Length;
                Stream dataStream = request.GetRequestStream();

                dataStream.Write(bytes, 0, bytes.Length);
                dataStream.Close();



                //Pass request
                logger.Info("Made it up to start of RTC request for secure document.");
                using (HttpWebResponse getrespn = requestSecureDocument(request, "https://myserver:9100/jazz", "username", "pass", test44))
                {

                    //Stream ReceiveStream = getrespn.GetResponseStream();
                    // Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
                    //StreamReader readStream = new StreamReader(ReceiveStream);
                    //response = readStream.ReadToEnd();


                    getrespn.Close();
                }

与 RTC 服务器交互的代码段(基于来自 https://nkumar83.wordpress.com/2013/06/13/consuming-rtc-rational-team-concert-oslc-apis-using-c-post-1-authentication/ 的示例并进行了我自己的调整):

 public static HttpWebResponse requestSecureDocument(HttpWebRequest _requestItem, string _rtcServerURL, string _userName, string _password, string passXml)
    {
        try
        {
            //FormBasedAuth Step 1: Request the resource 
            HttpWebRequest _request = (HttpWebRequest)WebRequest.Create(_requestItem.RequestUri);
            _request.CookieContainer = _requestItem.CookieContainer;

            //store the response in _docResponse variable
            HttpWebResponse _docResponse = (HttpWebResponse)_request.GetResponse();

            //HttpStatusCode.OK indicates that the request succeeded
            if (_docResponse.StatusCode == HttpStatusCode.OK)
            {
                //X-com-ibm-team... header signifies form based authentication is being used
                string _rtcAuthHeader = _docResponse.Headers["X-com-ibm-team-repository-web-auth-msg"];
                if ((_rtcAuthHeader != null) && _rtcAuthHeader.Equals("authrequired"))
                {
                    _docResponse.GetResponseStream().Flush();
                    _docResponse.Close();

                    //Prepare form for authentication 

                    HttpWebRequest _formPost = (HttpWebRequest)WebRequest.Create(_rtcServerURL + "/j_security_check");


                    _formPost.Method = "POST";
                    _formPost.Timeout = 30000;
                    _formPost.CookieContainer = _request.CookieContainer;
                    _formPost.Accept = "text/xml";
                    _formPost.ContentType = "application/x-www-form-urlencoded";



                    string _authString = "j_username=" + _userName + "&j_password=" + _password;
                    Byte[] _outBuffer = Encoding.UTF8.GetBytes(_authString);
                    _formPost.ContentLength = _outBuffer.Length;
                    Stream _str = _formPost.GetRequestStream();
                    _str.Write(_outBuffer, 0, _outBuffer.Length);
                    _str.Close();


                    //FormBasedAuth Step 2: Submit the login form and get response

                    HttpWebResponse _formResponse = (HttpWebResponse)_formPost.GetResponse();

                    _rtcAuthHeader = _formResponse.Headers["X-com.ibm-team.repository-web-auth-msg"];

                    //Check if auth failed
                    if ((_rtcAuthHeader != null) && _rtcAuthHeader.Equals("authfailed"))
                    {
                        //auth fialed
                        var fail = "";
                    }
                    else
                    {
                        //login successful

                        //FormBasedAuth Step 3: Resend the request for the protected resource
                        _formResponse.GetResponseStream().Flush();
                        _formResponse.Close();

                       using (HttpWebResponse getresp = (HttpWebResponse)_requestItem.GetResponse()) *** THIS IS TH LINE WHICH THROWS THE EXCEPTION ***
                       {
                           return getresp;
                       }
                    }
                }
            }
            return _docResponse;

        }
        catch (WebException e)
        {
             var filePath = AppDomain.CurrentDomain.GetData("DataDirectory") + @"/trapA.xml";
                    using (StreamWriter writer = new StreamWriter(filePath, true))
                    {
                        writer.WriteLine("Message: Failed to trigger getresponse successfully: " + e);
                    }

        }
        return null;
    }

希望有人能帮忙:o)

最佳答案

好吧,我很高兴地说我终于弄清了这个问题的真相。事实证明问题与 IIS 无关,并且在“如果”我没有使用 RTC 客户端更新票证时发布时确实有效。

简而言之,我们的 RTC 客户端使用自定义脚本发布到我们的 Web API。然而,RTC 客户端似乎在您尝试更新的票证上设置了记录锁,该记录锁一直存在,直到提供来 self 们 API 的响应。当然这不可能发生,因为响应的一部分是确认更新是否成功,而由于 RTC 客户端的锁定,这不可能发生。

解决方案是尽快关闭来自 RTC 的调用。因此,验证和回调 RTC 以进行更新的代码段现在被一些新代码包裹起来以创建一个新线程。这允许连接在大约 5 秒内关闭,同时我们的应用程序继续进行必要的调用以完成交易。

Thread t = new Thread(() = > {
//code here

}

关于c# - HttpWebRequest .GetResponse 抛出 WebException 'The operation has timed out',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30912152/

相关文章:

c# - 如何使用 webservice C# 为基于事件的函数应用异步/等待?

asp.net - 文本 - 空文本节点问题

c# - JsonValueProviderFactory : System. ArgumentException:已添加具有相同键的项目

C# - 从现有字典创建列表

c# - 索引超出范围。必须是非负数且小于集合的大小

asp.net - 在 asp.net mvc 应用程序中处理未处理异常的一些策略是什么?

c# - 在 Entity Framework 中将对象添加到数据库时出现问题

c# - 使用 Asp.Net MVC 和 IIS 上传大于 3GB 的文件

c# - 当 actionName 类似于 "/controllerName/action/"时,Html.ActionLink() 添加不需要的文件夹

c# - 单引号和双引号 html 属性之间的功能区别是什么?