使用C#控制台应用程序将数据动态POST到ASPX页面

时间:2015-01-29 20:05:07

标签: c# asp.net httpwebrequest

我在本地托管的.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个字段?

1 个答案:

答案 0 :(得分:1)

基本上有两种方法可以实现你想要完成的任务。

最佳方式:API和Web服务

如果您尝试从受您控制的ASP .NET Web应用程序中检索信息,最好使用某种形式的API,而不是直接与要在浏览器中查看的页面进行通信。

这有几件事(其中包括):

  1. 您为自己节省了大量代码。

    而不是需要解析/生成/提交表单数据,这实际上只是为了帮助用户提供交互式网页,您编写的代码只需要处理发送和接收所需信息。

    < / LI>
  2. 您可以节省带宽。

    这也可以节省带宽,因为额外的数据(客户端应用程序不需要)不必来回传输。这反过来又使您的客户端应用程序更快,并且还为Web服务器节省了渲染ASP .NET WebForm所需的额外处理时间。

  3. 您可以避免额外的,不必要的错误检查和不稳定。

    当您与最终用户的网页进行通信时,如果网页没有返回您想要的内容,您可能经常需要执行许多错误检查。例如,在页面上仍然导致200 OK HTTP状态代码的错误的情况下,您可能需要解析页面以查找错误文本。这会占用处理时间,代码,并且在对页面进行更改时容易中断。

  4. 为了避免所有这些问题,您可以设置一个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>
    

    选项1:小规模

    就个人而言,我认为这是您的最佳选择,因为您似乎只打算传输一小部分数据。

    如果您只需要沟通一些数据,并且通常不依赖于从客户端应用程序与Web应用程序通信,则可以考虑使用通用处理程序(。 ASHX)即可。这是一种将数据从Web应用程序传输到客户端应用程序的快捷方式。

    <强>优点:

    1. 非常容易实现,特别是对于不熟悉MVC和RESTful服务的开发人员。
    2. 只需很短的时间即可完成。
    3. <强>缺点:

      1. 不易扩展。如果您计划增加服务器和客户端之间通信所需的数据量,请考虑使用完整的Web服务或API。
      2. 可能会导致无标准化的代码。换句话说,因为没有设置与通用处理程序通信的标准方式,如果您不遵守某些规则(例如,每次我需要访问会员的名称时,我和#39;将使用名称字段,并且对于他们的出生日期(DOB),您可能会得到许多彼此非常不同的代码,并且在需要更改时难以维护。
      3. 这里有一些伪代码,告诉你创建一个通用处理程序是多么容易:

        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)

        选项2:大规模

        如果您计划在客户端应用程序和Web应用程序之间传输大量数据,那么最好使用 ASP .NET Web API 促进两者之间的通信,因为它为您提供了一种简单的方法来创建具有可编程API的Web服务。

        <强>优点:

        1. 非常容易扩展并进行更改。您可以轻松地按照自己的意愿轻松添加和删除不同的信息。
        2. 从长远来看,您可以减少工作和代码。很多时候,会根据您的数据库或其他数据源为您部分生成代码,并且可以随时使用模板来帮助您入门。您也不必重新发明轮子,因为您可以获得许多课程和实用方法,因此您可以专注于重要的事项:您的数据。
        3. <强>缺点:

          1. 需要一段时间才能初步设置并适应。当你习惯使用类似Web API的东西时,它会变得更加熟悉,但在开始时它可能会感觉进入一个全新的世界。
          2. 对于小型项目来说可能很麻烦且笨重。如果您只需要一个或两个发送/接收有限数量信息的页面,那么最好再制作一个简单的处理程序。
          3. 深入研究Web API这样的框架是一个非常长期的考验,并不适合在这里处理。但是,有大量资源可以帮助您,例如官方的Getting Started with ASP.NET Web API 2教程。

            不那么好的方式:刮刮信息

            高度建议,尽可能避免使用此方法。如果您无法控制需要与之交谈的Web应用程序,请首先检查提供Web应用程序的开发人员/公司是否提供了文档化的API。相反,以这种方式开发会容易得多。

            然而,有时几乎没有选择,通常情况就是

            1. 您无法控制网络应用程序的代码和
            2. 没有可用的文档API。
            3. 在这种情况下,你必须依靠&#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.NETHow to use HTML Agility pack是很好的起点。

              选择走哪条路

              正如我之前提到的,您选择使用的方法实际上取决于您所处的情况。

              • 如果此应用程序在您的控制之下,我 强烈建议 使用某种形式的API:
                • 如果您真的只需传输一些信息,请使用Generic Handler
                • 之类的东西
                • 如果您计划在客户端和服务器之间进行通信,这是解决方案的一个重要部分,请使用类似ASP .NET Web API的内容。
              • 如果您不负责网络应用程序:
                • 如果有可用的API,请查阅文档并使用它!
                • 如果没有可用的API,也没有别的办法,作为最后的手段,请使用抓取技术。

              祝你好运!