在HttpWebRequest中,如果你使用了如下代码:
HttpWebResponse oResponse = (HttpWebResponse)oRequest.GetResponse();
那么当你的HttpWebRequest访问某个页面时出现500错误,并且执行上面这步时
这个时候HttpWebRequest将抛出一个异常WebException,上面这步将不会运行
你原本的oResponse对象是不会存在的
相关的解决方法是捕获这个异常,从异常对象上获取Response。代码
... {
oResponse = (HttpWebResponse)oRequest.GetResponse();
}
catch (WebException ex)
... {
oResponse = (HttpWebResponse)ex.Response;
}
虽然系统出现了500错误,但是并不代表一切,比如下面的返回数据:
HTTP/1.1 100 Continue
Server: Microsoft-IIS/5.0
Date: Tue, 10 Jul 2007 12:43:29 GMT
X-Powered-By: ASP.NET
HTTP/1.1 500 Internal Server Error
Server: Microsoft-IIS/5.0
Date: Tue, 10 Jul 2007 12:43:29 GMT
X-Powered-By: ASP.NET
Content-Length: 663
Content-Type: text/html
Set-Cookie: oblog=CookieDate=3&Password=xxxxxx&UserLevel=7&UserName=xxxx; expires=Tue, 08-Jul-2008 16:00:00 GMT; path=/
Cache-control: private
<html>
<head>
<script>window.location = 'http://xxx.cn/indexlogin.asp';</script> <font face="宋体" size=2>
<p>Microsoft VBScript 运行时错误</font> <font face="宋体" size=2 > 错误 '800a01a8'</font>
<p>
<font face="宋体" size=2>缺少对象: 'rs'</font>
<p>
<font face="宋体" size=2>/User_ChkLogin.asp</font><font face="宋体" size=2>,行108</font>
虽然页面500了,但是这个页面在运行时却传回了Cookies值,并且告诉浏览器跳转到'http://xxx.cn/indexlogin.asp'
如果不捕获这个Response对象的话,这里的Cookies值是得不到的。
很疑惑的是为什么Microsoft在设计webRequest对象时遇到500错误会抛出一个异常,而把Response对象重新放在异常对象中?
为什么不可以不抛出异常直接运行下去?
这种做法有点画蛇添足:不但这种异常抛出无用,而且还有不少的反作用。
HttpWebRequest编程相关问题(2)
在使用 HttpWebRequest访问需要登陆的页面时必然会涉及到Cookies,但是HttpWebRequest对象和相关方法在设计时还是存在一些问题
比如:
- 访问页面A,得到Cookie o1包含jspsessionid;
- 把o1给HttpWebRequest然后登陆页面B,得到一个新的Cookies o2,里面包含了很多相关信息;
- 把o2给HttpWebRequest然后登陆页面C.
一般情况下你会使用如下代码:
oRequest.ProtocolVersion = new Version( " 1.1 " );
oRequest.Referer = oHead.Referer;
oRequest.Accept = " image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, */* " ;
oRequest.CookieContainer = new CookieContainer();
oRequest.CookieContainer .Add(o2)
oRequest.UserAgent = " blogmove.cn " ;
oRequest.Credentials = CredentialCache.DefaultCredentials;
上面的oRequest.CookieContainer.Add(o2)基本上没有错,而且按照道理来说也不会有错
但是事实上,Micosoft在设计这一部分是存在缺陷的,或者“Microsoft有独立的定位”,也许还有我不知道的地方
上文的代码一般情况下不会有错,Cookies值会被正常传递给服务器,但是如果o2的内容是下面的内容的话,上面的代码就可能会存在缺陷:
Set-Cookie: JSESSIONID=555287820C8B46311649EF947F77DF12; Path=/control
Set-Cookie: Code=b4874b74; Domain=blogmove.cn; Path=/
Set-Cookie: mc=1%2cplatform%2c0; Domain=blogmove.cn; Path=/
(注意这里是HttpHeader方式)
上面的这段Head假设是在访问http://file.blogmove.cn/t1.aspx 时,服务器写给浏览器的。
o2被传递给oRequest,oRequest访问http://file.blogmove.cn/test.aspx 时,上面三个cookie,只有第一个被oRequest传递给了服务器,服务器收不到后面两个cookies,Test.aspx页面就会返回错误的结果。
原因就是Cookie是有Domain的,
第一个Cookie的Domain是默认http://file.blogmove.cn;
第二和三个Cookie的Domain是blogmove.cn;
oRequest在上行Cookie时只上行了当前Domain=http://file.blogmove.cn的Cookie,而放弃了Domin=blogmove.cn的Cookie,oRequest分辨了Uri;
这种行为和我们正常预想的不符,因为我们平常是按照浏览器的行为在思考:应该上行所有blogmove.cn下的所有Cookies.
按照道理来说,我认为Request对象应该自动分辨和解析Cookies里面的domain.
因此为了保证oRequest能够达到我们的目的,所以应该修改上面的C#代码如下:
... {
HttpWebResponse oResponse=null;
HttpWebRequest oRequest = (HttpWebRequest)HttpWebRequest.Create(oHead.Host+ oHead.Action);
oRequest.ProtocolVersion = new Version("1.1");
oRequest.Referer = oHead.Referer;
oRequest.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, */*";
oRequest.CookieContainer = new CookieContainer();
if (oHead.Cookies != null)
...{
string cookiesValue = "";
foreach (Cookie o in oHead.Cookies)
...{
cookiesValue += o.Name+"="+ o.Value+",";
}
oRequest.CookieContainer.SetCookies(new Uri(oHead.Host), cookiesValue);
}
//oRequest.CookieContainer.SetCookies(oRequest.RequestUri,cookies[].
oRequest.UserAgent = "NutsSoft.com.cn";
oRequest.Credentials = CredentialCache.DefaultCredentials;
//设置POST数据
if (oHead.Method.ToLower() == "post")
...{
oRequest.Method = "POST";
byte[] byteData = ASCIIEncoding.ASCII.GetBytes(oHead.PostData);
oRequest.ContentType = "application/x-www-form-urlencoded";
oRequest.ContentLength = byteData.Length;
Stream WriteStream = oRequest.GetRequestStream();
WriteStream.Write(byteData, 0, byteData.Length);
WriteStream.Close();
}
try
...{
oResponse = (HttpWebResponse)oRequest.GetResponse();
}
catch (WebException ex)
...{
oResponse = (HttpWebResponse)ex.Response;
}
oResponse.Cookies = oRequest.CookieContainer.GetCookies(oRequest.RequestUri);
Stream dataStream = oResponse.GetResponseStream();
string en = oResponse.CharacterSet;
if (en == null) en = "gb2312";
if (en.ToLower() == "iso-8859-1") en = "gb2312";
StreamReader reader = new StreamReader(dataStream, Encoding.GetEncoding(en));
string responseFromServer = reader.ReadToEnd();
Cookies = oRequest.CookieContainer.GetCookies(oRequest.RequestUri);
oHead.Cookies = oRequest.CookieContainer.GetCookies(oRequest.RequestUri);
reader.Close();
dataStream.Close();
oResponse.Close();
return oHead.Html=responseFromServer;
}
这是一个相当完整的Send方法。不做过多的解释.
PS:这个Cookies上行问题耗费了一天时间来找出原因。
另:本文言语有点混乱。