我在本地托管的.aspx页面包含一个文本字段,用户可以在其中输入他/她的ID并获取一些信息。
我理解HttpWebRequest
如何工作并多次使用它来POST许多PHP和JSP页面,但现在的问题是我尝试POST的ASP .NET页面有很多隐藏像__VIEWSTATE
这样的字段是动态的,每次用户输入他/她的ID并按下提交按钮时都会发送到服务器。
如何将这些动态字段的值与ID一起发布?
标题看起来像这样(从Firefox中的开发人员工具中获取):
__EVENTTARGET=&__EVENTARGUMENT=&__LASTFOCUS=&__VIEWSTATE=%2FwEPDwUJMjk5MjYyMjY5D2QWAgIDD2QWBAIHDxcAZAIJDxcGBQZIZWlnaHQHAAAAAAA8kEAFBHJzSUQFFENyeXN0YWxSZXBvcnRTb3VyY2UxBQ9SZXBvcnRWaWV3U3RhdGUXBgUKRGVzaWduTW9kZWgFElBhZ2VSZXF1ZXN0Q29udGV4dBcEBQpQYWdlTnVtYmVyAgEFDVByb21wdGluZ0luZm8UKVhTeXN0ZW0uQnl0ZSwgbXNjb3JsaWIsIFZlcnNpb249Mi4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5ygUDPAM%2FA3gDbQNsAyADdgNlA3IDcwNpA28DbgM9AyIDMQMuAzADIgM%2FAz4DDQMKAzwDQQNyA3IDYQN5A08DZgNQA2EDcgNhA20DZQN0A2UDcgNGA2kDZQNsA2QDIAN4A20DbANuA3MDOgN4A3MDaQM9AyIDaAN0A3QDcAM6Ay8DLwN3A3cDdwMuA3cDMwMuA28DcgNnAy8DMgMwAzADMQMvA1gDTQNMA1MDYwNoA2UDbQNhAy0DaQNuA3MDdANhA24DYwNlAyIDIAN4A20DbANuA3MDOgN4A3MDZAM9AyIDaAN0A3QDcAM6Ay8DLwN3A3cDdwMuA3cDMwMuA28DcgNnAy8DMgMwAzADMQMvA1gDTQNMA1MDYwNoA2UDbQNhAyIDPgMNAwoDIAMgAzwDUANhA3IDYQNtA2UDdANlA3IDRgNpA2UDbANkAyADXwNEA2UDZgNhA3UDbAN0A1YDYQNsA3UDZQNEA2kDcwNwA2wDYQN5A1QDeQNwA2UDPQMiAzADIgMgA1ADYQNyA2EDbQNlA3QDZQNyA0YDaQNlA2wDZANOA2EDbQNlAz0DIgNAA1IDZQNnA2kDcwN0A2UDcgNhA3QDaQNvA24DbgN1A20DYgNlA3IDIgMgA1ADcgNvA20DcAN0A1QDZQN4A3QDPQMiAyIDIANSA2UDcANvA3IDdANOA2EDbQNlAz0DIgMiAyADRQNkA2kDdANNA2EDcwNrAz0DIgMiAyADSANhA3MDQwN1A3IDcgNlA24DdANWA2EDbAN1A2UDPQMiA3QDcgN1A2UDIgMgA0UDbgNhA2IDbANlA0EDbANsA28DdwNFA2QDaQN0A2kDbgNnA0QDZQNmA2EDdQNsA3QDVgNhA2wDdQNlAz0DIgN0A3IDdQNlAyIDIANFA24DYQNiA2wDZQNBA2wDbANvA3cDTQN1A2wDdANpA3ADbANlA1YDYQNsA3UDZQM9AyIDZgNhA2wDcwNlAyIDIANFA24DYQNiA2wDZQNOA3UDbANsA1YDYQNsA3UDZQM9AyIDdANyA3UDZQMiAyADVQNQA2EDcgNhA20DZQN0A2UDcgNWA2EDbAN1A2UDSwNpA24DZAM9AyIDMAMiAyADVQNQA2EDcgNhA20DZQN0A2UDcgNUA3kDcANlAz0DIgMwAyIDIANVA0QDaQNzA2MDcgNlA3QDZQNPA3IDUgNhA24DZwNlA0sDaQNuA2QDPQMiAzADIgMgA1UDRANlA2YDYQN1A2wDdANWA2EDbAN1A2UDUwNvA3IDdANPA3IDZANlA3IDPQMiAzADIgMgA1UDRANlA2YDYQN1A2wDdANWA2EDbAN1A2UDUwNvA3IDdANNA2UDdANoA28DZAM9AyIDMAMiAz4DDQMKAyADIAMgAyADPANQA2EDcgNhA20DZQN0A2UDcgNDA3UDcgNyA2UDbgN0A0QDaQNzA2MDcgNlA3QDZQNWA2EDbAN1A2UDIANVA0sDaQNuA2QDPQMiAzADIgM%2BAw0DCgMgAyADIAMgAyADIAM8A0QDZQNzA2MDcgNpA3ADdANpA28DbgMgAy8DPgMNAwoDIAMgAyADIAMgAyADPANWA2EDbAN1A2UDUwN0A3IDaQNuA2cDPgMxAzEDMwMxAzADNgM5AzQDPAMvA1YDYQNsA3UDZQNTA3QDcgNpA24DZwM%2BAw0DCgMgAyADIAMgAzwDLwNQA2EDcgNhA20DZQN0A2UDcgNDA3UDcgNyA2UDbgN0A0QDaQNzA2MDcgNlA3QDZQNWA2EDbAN1A2UDPgMNAwoDIAMgAzwDLwNQA2EDcgNhA20DZQN0A2UDcgNGA2kDZQNsA2QDPgMNAwoDPAMvA0EDcgNyA2EDeQNPA2YDUANhA3IDYQNtA2UDdANlA3IDRgNpA2UDbANkAz4FFUlzTGFzdFBhZ2VOdW1iZXJLbm93bmcFDkxhc3RQYWdlTnVtYmVyAgIFB0ZhY3RvcnkFlgFDcnlzdGFsRGVjaXNpb25zLlJlcG9ydFNvdXJjZS5SZXBvcnRTb3VyY2VGYWN0b3J5LENyeXN0YWxEZWNpc2lvbnMuUmVwb3J0U291cmNlLCBWZXJzaW9uPTEwLjIuMzYwMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPTY5MmZiZWE1NTIxZTEzMDQFB1JlZnJlc2hoBQlSZXBvcnRVUkllBQlScHRTb3VyY2UFN0NyeXN0YWxEZWNpc2lvbnMuUmVwb3J0U291cmNlLk5vbkhUVFBDYWNoZWRSZXBvcnRTb3VyY2UFA2Nzc2UFBEJBU0UPFgYeBkhlaWdodBsAAAAAADyQQAEAAAAeBVdpZHRoGwAAAAAAKIhAAQAAAB4EXyFTQgKAA2QFBVdpZHRoBwAAAAAAKIhAFgICAg8XAQUCYnMC3%2F7%2F%2Fw8WAgILDxAPFgIeC18hRGF0YUJvdW5kZ2QPFgFmFgEQBQtNYWluIFJlcG9ydAWoA0FBRUFBQUQvLy8vL0FRQUFBQUFBQUFBRUFRQUFBQnhUZVhOMFpXMHVRMjlzYkdWamRHbHZibk11U0dGemFIUmhZbXhsQndBQUFBcE1iMkZrUm1GamRHOXlCMVpsY25OcGIyNElRMjl0Y0dGeVpYSVFTR0Z6YUVOdlpHVlFjbTkyYVdSbGNnaElZWE5vVTJsNlpRUkxaWGx6QmxaaGJIVmxjd0FBQXdNQUJRVUxDQnhUZVhOMFpXMHVRMjlzYkdWamRHbHZibk11U1VOdmJYQmhjbVZ5SkZONWMzUmxiUzVEYjJ4c1pXTjBhVzl1Y3k1SlNHRnphRU52WkdWUWNtOTJhV1JsY2dqc1VUZy9Bd0FBQUFvS0N3QUFBQWtDQUFBQUNRTUFBQUFRQWdBQUFBTUFBQUFHQkFBQUFBNU1ZWE4wVUdGblpVNTFiV0psY2dZRkFBQUFGVWx6VEdGemRGQmhaMlZPZFcxaVpYSkxibTkzYmdZR0FBQUFDbEJoWjJWT2RXMWlaWElRQXdBQUFBTUFBQUFJQ0FJQUFBQUlBUUVJQ0FFQUFBQUxnFgFmZBgBBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3RCYWNrS2V5X18WCwUgQ3J5c3RhbFJlcG9ydFZpZXdlcjEkY3RsMDIkY3RsMDAFIENyeXN0YWxSZXBvcnRWaWV3ZXIxJGN0bDAyJGN0bDAxBSBDcnlzdGFsUmVwb3J0Vmlld2VyMSRjdGwwMiRjdGwwMgUgQ3J5c3RhbFJlcG9ydFZpZXdlcjEkY3RsMDIkY3RsMDMFIENyeXN0YWxSZXBvcnRWaWV3ZXIxJGN0bDAyJGN0bDA0BSBDcnlzdGFsUmVwb3J0Vmlld2VyMSRjdGwwMiRjdGwwNQUgQ3J5c3RhbFJlcG9ydFZpZXdlcjEkY3RsMDIkY3RsMDYFIENyeXN0YWxSZXBvcnRWaWV3ZXIxJGN0bDAyJGN0bDA3BSBDcnlzdGFsUmVwb3J0Vmlld2VyMSRjdGwwMiRjdGwxMAUgQ3J5c3RhbFJlcG9ydFZpZXdlcjEkY3RsMDIkY3RsMTIFIENyeXN0YWxSZXBvcnRWaWV3ZXIxJGN0bDAyJGN0bDE0jI2pRkImY%2FKY6U%2Fd3%2FdGqZgVpS8%3D&__PREVIOUSPAGE=JxnGN13k9OAmlpqF3Z8SW9w-B2b4vBfG7WIz-XQ5-GZ_4P1GIClbgn0lEpxdarTxDVAekfH3QhOqCwpdtv2ml9I79qLZb5EFP7Nh-zun2qPkprmn0&TextBox1=11310694&Button1=Show&CrystalReportViewer1%24ctl02%24ctl09=&CrystalReportViewer1%24ctl02%24ctl11=AAEAAAD%2F%2F%2F%2F%2FAQAAAAAAAAAEAQAAABxTeXN0ZW0uQ29sbGVjdGlvbnMuSGFzaHRhYmxlBwAAAApMb2FkRmFjdG9yB1ZlcnNpb24IQ29tcGFyZXIQSGFzaENvZGVQcm92aWRlcghIYXNoU2l6ZQRLZXlzBlZhbHVlcwAAAwMABQULCBxTeXN0ZW0uQ29sbGVjdGlvbnMuSUNvbXBhcmVyJFN5c3RlbS5Db2xsZWN0aW9ucy5JSGFzaENvZGVQcm92aWRlcgjsUTg%2FAwAAAAoKCwAAAAkCAAAACQMAAAAQAgAAAAMAAAAGBAAAAA5MYXN0UGFnZU51bWJlcgYFAAAAFUlzTGFzdFBhZ2VOdW1iZXJLbm93bgYGAAAAClBhZ2VOdW1iZXIQAwAAAAMAAAAICAIAAAAIAQEICAEAAAAL&CrystalReportViewer1%24ctl02%24ctl13=&CrystalReportViewer1%24ctl02%24ctl15=100
相反,我可用于POST的所有信息都是TextBox1=11310694
如果我在代码中使用与上面相同的标题,我会得到500 INTERNAL SERVER ERROR
。
我用来获取页面的C#代码:
try{
ASCIIEncoding encoding = new ASCIIEncoding();
string post_data = "TextBox1=123456";
byte[] data = encoding.GetBytes(post_data);
WebRequest share_url = WebRequest.Create("http://172.19.2.6:8080/webopac/html/memberlogin");
share_url.Method = "POST";
share_url.ContentLength = data.Length;
share_url.ContentType = "application/x-www-form-urlencoded";
Stream stream = share_url.GetRequestStream();
stream.Write(data, 0, data.Length);
stream.Close();
WebResponse resp = share_url.GetResponse();
stream = resp.GetResponseStream();
StreamReader sr = new StreamReader(stream);
var oup = sr.ReadToEnd();
Console.WriteLine(oup);
Console.ReadLine();
}
catch (Exception err)
{
Console.WriteLine("ERROR: " + err.Message);
}
如何发布VIEWSTATE
个字段?
答案 0 :(得分:1)
基本上有两种方法可以实现你想要完成的任务。
如果您尝试从受您控制的ASP .NET Web应用程序中检索信息,最好使用某种形式的API,而不是直接与要在浏览器中查看的页面进行通信。
这有几件事(其中包括):
您为自己节省了大量代码。
而不是需要解析/生成/提交表单数据,这实际上只是为了帮助用户提供交互式网页,您编写的代码只需要处理发送和接收所需信息。
< / LI>您可以节省带宽。
这也可以节省带宽,因为额外的数据(客户端应用程序不需要)不必来回传输。这反过来又使您的客户端应用程序更快,并且还为Web服务器节省了渲染ASP .NET WebForm所需的额外处理时间。
您可以避免额外的,不必要的错误检查和不稳定。
当您与最终用户的网页进行通信时,如果网页没有返回您想要的内容,您可能经常需要执行许多错误检查。例如,在页面上仍然导致200 OK HTTP状态代码的错误的情况下,您可能需要解析页面以查找错误文本。这会占用处理时间,代码,并且在对页面进行更改时容易中断。
为了避免所有这些问题,您可以设置一个API或Web服务,它将充当您的Web应用程序用于与客户端应用程序通信的特殊通信点。您只发送所需的数据,简化代码并使应用程序更可靠。
如果您只是在WebForm或其他网页上查询所需的表单值,那么您的程序必须对所有这些进行排序:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head><script type="text/javascript" charset="UTF-8">
(function (global) {
global.outsystems = global.outsystems || {};
global.outsystems.internal = global.outsystems.internal || {};
})(this);
outsystems.internal.timerspolyfillResponseStart = new Date().getTime();
outsystems.internal.beaconURL = '/PerformanceProbe/Beacon.aspx';
</script><title>
Login
</title><link rel="apple-touch-icon" href="apple-touch-icon.png" /><link type="image/x-icon" rel="shortcut icon" href="/WodifyUI/img/favicon.png" /><script type="text/javascript" src="/wodify/js/libs/modernizr-2.5.3.min.js"></script><script type="text/javascript" src="/WodifyUI/js/pusher.min.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Script-Type" content="text/javascript" /><meta http-equiv="Content-Style-Type" content="text/css" />
</head>
<body>
<form name="WebForm1" method="post" action="Login.aspx" onsubmit="javascript:return WebForm_OnSubmit();" id="WebForm1">
<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__OSVSTATE" id="__OSVSTATE" value="eNp1jcEKgkAURXOwFi1yE1MRzB+0SGrhUloJJSK0lodvNEFnZGbM+vpSQaigzYN3D/eel+WgM53vXPfged7ePTp0xtaFiEBB5ZelbP3GyJhjoXhqcrZpzVVzFULFA1E3JrmAQDBSPQcWgdatVPjLKCGdiJJsPPb4977l6KvrskjBFFIESCy2uoM6px9pzNNuXNMJ2/5BCZdZjkjsfv3L6VDCFkPrVHIQIX+YG+Ib9DFO1Q==" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="" />
</div>
<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['WebForm1'];
if (!theForm) {
theForm = document.WebForm1;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
...
如果您使用API或网络服务,最终会得到类似以下代码的内容,这样更容易使用:
<?xml version="1.0" encoding="UTF-8"?>
<member>
<id>12345</id>
<name>Jane Doe</name>
<dob>01/01/1980</dob>
</member>
就个人而言,我认为这是您的最佳选择,因为您似乎只打算传输一小部分数据。
如果您只需要沟通一些数据,并且通常不依赖于从客户端应用程序与Web应用程序通信,则可以考虑使用通用处理程序(。 ASHX)即可。这是一种将数据从Web应用程序传输到客户端应用程序的快捷方式。
<强>优点:
<强>缺点:
这里有一些伪代码,告诉你创建一个通用处理程序是多么容易:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Xml;
using MyDatabase;
namespace MyWebApplication
{
public class MemberHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
Member requestedMember = null;
Exception error = null;
try
{
requestedMember = MyDatabaseClient.GetMemberByID(int.Parse(context.Request.QueryString["id"]));
}
catch (Exception ex)
{
error = ex;
}
context.Response.ContentType = "text/xml";
context.Response.ContentEncoding = Encoding.UTF8;
using (XmlTextWriter xmlTextWriter = new XmlTextWriter(context.Response.OutputStream, Encoding.UTF8) { Formatting = Formatting.Indented })
{
xmlTextWriter.WriteStartDocument();
if (requestedMember != null)
{
xmlTextWriter.WriteStartElement("member");
xmlTextWriter.WriteStartElement("id");
xmlTextWriter.WriteValue(requestedMember.ID);
xmlTextWriter.WriteEndElement();
xmlTextWriter.WriteStartElement("name");
xmlTextWriter.WriteValue(requestedMember.Name);
xmlTextWriter.WriteEndElement();
xmlTextWriter.WriteStartElement("dob");
xmlTextWriter.WriteValue(requestedMember.DOB);
xmlTextWriter.WriteEndElement();
xmlTextWriter.WriteEndElement();
}
else
{
xmlTextWriter.WriteStartElement("error");
xmlTextWriter.WriteValue(error.Message);
xmlTextWriter.WriteEndElement();
}
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
现在,通过对/MemberHandler.ashx?id=12345
的简单Web请求,您可以从控制台应用程序中检索所需的正确信息。现在,这只是一个例子,因此,例如,如果找不到该成员,它就不会发送404。但是,这些是非常容易实现的功能!
然后,从客户端应用程序中,您只需检索XML并使用System.Xml
中的类对其进行解析。这使您必须做的工作几乎为零,并且是一种简单,快速,快速的服务器和客户端之间通信实现。
如果您进行了良好的搜索,网上有很多优秀的资源可以帮助您制作处理程序,例如.NET: A simple AJAX service using Plain Old XML (POX)
如果您计划在客户端应用程序和Web应用程序之间传输大量数据,那么最好使用 ASP .NET Web API 促进两者之间的通信,因为它为您提供了一种简单的方法来创建具有可编程API的Web服务。
<强>优点:
<强>缺点:
深入研究Web API这样的框架是一个非常长期的考验,并不适合在这里处理。但是,有大量资源可以帮助您,例如官方的Getting Started with ASP.NET Web API 2教程。
我高度建议,尽可能避免使用此方法。如果您无法控制需要与之交谈的Web应用程序,请首先检查提供Web应用程序的开发人员/公司是否提供了文档化的API。相反,以这种方式开发会容易得多。
然而,有时几乎没有选择,通常情况就是
在这种情况下,你必须依靠&#34;刮擦&#34;您需要的网页信息。理论很简单,但执行得相当恶劣。
在您的示例中,如果您必须依赖抓取,则首先会向相关网页发送请求以检索其VIEWSTATE
以及您可能需要的任何其他表单值。此外,如果Web应用程序依赖于cookie,则当您尝试检索所需的数据时,可能需要存储它们并在下一个请求中重复使用它们。
这需要反复试验并仔细分析网页以及正常浏览网站时发送/接收的请求/响应(这是您在查找发送的表单数据时所做的工作)
此外,您必须向服务器运行两个请求,这会引入更多故障点,并使客户端运行速度更慢。
有许多资源可供详细说明如何从网页中删除信息。其中许多处理.NET的人都会提到 HtmlAgilityPack 库(在NuGet上可用),这是一个很棒的工具,可以让你从HTML页面中获取一些信息。必须通过原始文本运行不准确和昂贵的搜索。
想象一下,好像你的服务器上有一个Javascript DOM版本,所以你不会用HTML搜索字符串,而是使用类似的东西:
HtmlAgilityPack.HtmlNode FormElement = htmlResponse.DocumentNode.SelectSingleNode("//form");
如果您需要帮助开始抓取,Scraping HTML DOM elements using HtmlAgilityPack (HAP) in ASP.NET和How to use HTML Agility pack是很好的起点。
正如我之前提到的,您选择使用的方法实际上取决于您所处的情况。
祝你好运!