我一直致力于一个利用RTC API和表单身份验证的项目。我遇到了一些奇怪的行为,我只是想不出这个。
迄今为止已经发生的情况是我可以在本地端到端地成功运行这个项目。也就是说,这段特定的代码可以:
当我发布到IIS(7.5)服务器时,问题就开始了。一切正常,直到最后一次.GetResponse调用,它使用PUT方法传递我的XML来更新RTC中的票证。我一直在'手术已超时'。
我花了几天的时间试图用这种方式来做各种各样的事情,但没有任何事情证明是有用的。
作为测试,我在第二次调用时将PUT方法更改为GET。它的工作原理!如果我使用带有.AllowAutoRedirect = false的PUT,那么我会得到一个响应,但是RTC端没有任何反应,所以请求显然被忽略了。我还注意到,返回的状态标记为“Found”而不是“OK”。
有些人认为在这个阶段可能是远程服务器和Web服务器之间缺乏连接。这不是这种情况,因为身份验证可以正常工作,而这是针对同一台服务器的。我还使用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)
答案 0 :(得分:1)
我很高兴地说我终于找到了这一个的底部。事实证明,问题与IIS没有任何关系,并且在发布时确实有效。如果&#39;我没有使用RTC客户端来更新故障单。
简短的故事是我们的RTC客户端使用自定义脚本发布到我们的网络API。但是,RTC客户端似乎会对您尝试更新的故障单进行记录锁定,该记录会持续存在,直到我们提供API的响应为止。当然,这不可能发生,因为部分响应是确认更新是否成功,由于RTC客户端的锁定而无法进行更新。
解决方案是尽快让RTC的呼叫关闭。因此,验证并回调给RTC进行更新的代码段现在包含一些新代码以创建新线程。这使得连接在大约5秒内关闭,我们的应用程序继续进行必要的调用以完成交易。
Thread t = new Thread(() = > {
//code here
}