【发布时间】:2018-02-14 11:40:11
【问题描述】:
在成功的 POST 请求之后,我需要使用 WebClient 来获取响应标头内的 url。
但是我在执行WebClient.UploadValues 后得到的标题是页面在被重定向之后的标题。
这段代码使用WebClient模拟与浏览器中相同的操作:
NameValueCollection formData = new NameValueCollection();
formData["username"] = user;
formData["password"] = password;
byte[] responseBytes = webClient.UploadValues(loginUrl, "POST", formData);
string response = Encoding.UTF8.GetString(responseBytes);
string allheaders = "";
for (int i = 0; i < webClient.ResponseHeaders.Count; i++)
{
allheaders += Environment.NewLine + webClient.ResponseHeaders.GetKey(i) + " = " + webClient.ResponseHeaders.Get(i);
}
File.WriteAllText("headers_2.txt", "[HEADER_2] " + allheaders);
...结果 headers_2.txt 不包含 Location 标头(这些标头来自用户被重定向到的页面):
[HEADER_2] Pragma = 无缓存 Cache-Control = 无存储、无缓存、必须重新验证 日期 = 格林威治标准时间 2018 年 2 月 14 日星期三 10:58:10 过期 = 1981 年 11 月 19 日星期四 08:52:00 GMT P3P = fffff 设置 Cookie = sid=ffffff;路径=/,gameapi_console=0;到期=格林威治标准时间 2018 年 3 月 17 日星期六 10:58:10;最大年龄=2678400;路径=/,bptid=ffffff;路径=/ 服务器 = 阿帕奇 变化 = 接受编码,用户代理 访问控制允许来源 = * 内容类型 = 文本/html;字符集=UTF-8 传输编码 = 分块
如何使用 WebClient 获取 Location 标头?如果可以的话。
更新:
感谢 cmets。
我忘了展示我尝试过的内容。
所以我创建了自己的类,它继承自WebClient。我在想,如果我在UploadValuesCompleted 被触发的那一刻阅读标题 - 我将在自动重定向之前获得标题。不幸的是,由于未知原因,即使在我致电 webClient.UploadValues(loginUrl, "POST", formData) 之后,该事件也从未被触发。
class FAWebClient : WebClient
{
public event Action<string> OnLocationHeaderFound;
public FAWebClient(Action<string> pOnLocationHeaderFound = null) :base()
{
UploadValuesCompleted += OnUploadValuesCompleted;
if(pOnLocationHeaderFound != null)
this.OnLocationHeaderFound += pOnLocationHeaderFound;
}
protected override void OnUploadValuesCompleted(object sender, UploadValuesCompletedEventArgs e)
{
if (this.OnLocationHeaderFound != null)
{
for (int i = 0; i < this.ResponseHeaders.Count; i++)
{
System.Diagnostics.Debug.WriteLine(this.ResponseHeaders.GetKey(i) + " = " + this.ResponseHeaders.Get(i));
if (this.ResponseHeaders.GetKey(i).ToLower() == "location")
{
OnLocationHeaderFound(this.ResponseHeaders.Get(i));
}
}
}
base.OnUploadValuesCompleted(e);
}
}
另外请注意,我使用 HttpClient 解决了这个问题,只需将 HttpClient.AllowAutoRedirect 设置为 false:
var handler = new HttpClientHandler()
{
AllowAutoRedirect = false
};
因此,我不得不对我的应用程序逻辑进行大量更改,但它确实有效。
但是,如果有人愿意提供解决方案或回答如何通过WebClient 实现这一目标,我将保持开放状态。
【问题讨论】:
-
如果您需要对请求/响应进行更多控制,您应该考虑使用 WebRequest/WebResponse,它允许您设置
AllowAutoRedirect = false。 @mjwills 链接的一个问题是这样做的,其类派生自WebClient。请注意,并非所有服务器/html 页面都设置了 Location Header。有些只是使用刷新设置为 0 的 http-equiv 元标记或设置新位置的 javascript 创建重定向。发生这种情况时,HttpStatusCode通常是 200(OK)而不是 302(找到)或 301(移动)或 303(重定向)。通常在 Web 窗体身份验证中。 -
在您的自定义 WebClient 的 WebRequest 上设置 AllowAutoRedirect =false 是否有问题?您需要其他解决方案吗?您可以覆盖 GetWebRequest ,将 base.GetWebRequest(address) 转换为 HttpWebRequest 并将 AllowAutoRedirect 设置为 false
-
@GeorgeVovos 我将在下周检查是否可以按照您提到的那样在 WebClient 中设置 AllowAutoRedirect 并在此处发表评论。不,我不是在寻找其他解决方案 - 所以如果这真的有效,请随时创建答案。