填写表格C#&发布错误

时间:2011-11-15 17:18:00

标签: c# httpwebrequest

我举了一个例子,用另一个问题在C#中填写表单,但是当我运行代码时,我只是再次返回页面(好像我没有提交任何内容)。我尝试手动转到网址并添加了?variable=value&variable2=value2,但这似乎没有预先填充表单,不确定这是不是为什么这不起作用。

private void button2_Click(object sender, EventArgs e)
{
    var encoding = new ASCIIEncoding();
    var postData = "appid=001";
    postData += ("&email=chris@test.com");
    postData += ("&receipt=testing");
    postData += ("&machineid=219481142226.1");
    byte[] data = encoding.GetBytes(postData);

    var myRequest =
       (HttpWebRequest)WebRequest.Create("http://www.example.com/licensing/check.php");
    myRequest.Method = "POST";
    myRequest.ContentType = "application/x-www-form-urlencoded";
    myRequest.ContentLength = data.Length;
    var newStream = myRequest.GetRequestStream();
    newStream.Write(data, 0, data.Length);
    newStream.Close();

    var response = myRequest.GetResponse();
    var responseStream = response.GetResponseStream();
    var responseReader = new StreamReader(responseStream);
    label2.Text = responseReader.ReadToEnd();
}

1 个答案:

答案 0 :(得分:5)

要以编程方式提交表单,一般的想法是您要模拟浏览器。为此,您需要找到URL,HTTP标头和POST数据的正确组合以满足服务器的要求。

了解服务器需求的最简单方法是使用Fiddler,FireBug或其他工具,它可以让您准确检查浏览器通过网络发送的内容。然后,您可以通过添加或删除标头,更改POST数据等来试验您的代码,直到服务器接受请求为止。

以下是您可能遇到的一些问题:

  • 首先,确保您将表单提交到正确的目标网址。许多表单不会发布到自己,但会发布到不同的URL
  • 接下来,表单可能正在检查会话cookie或身份验证cookie,这意味着您需要发出一个请求(以获取cookie),然后提交后续的提交请求以提交表单。
  • 表单可能包含您忘记填写的隐藏字段。使用Fiddler或Firebug查看在浏览器中手动填写表单时提交的表单字段,并确保在代码中包含相同的字段
  • 根据服务器实现,您可能需要将@字符编码为%40

也可能存在其他挑战,但上述情况最有可能发生。要查看完整列表,请查看my answer到另一个屏幕抓取问题。

顺便说一句,您用来提交表单的代码比需要的代码更难和更冗长。相反,您可以使用WebClient.UploadValues()并使用更少的代码完成相同的操作,并自动为您完成编码。像这样:

NameValueCollection postData = new NameValueCollection();
postData.Add ("appid","001");
postData.Add ("email","chris@test.com");
postData.Add ("receipt","testing");
postData.Add ("machineid","219481142226.1");
postData.Add ("checkit","checkit");

WebClient wc = new WebClient();
byte[] results = wc.UploadValues (
                       "http://www.example.com/licensing/check.php", 
                       postData);
label2.Text = Encoding.ASCII.GetString(results); 

更新:

鉴于我们在评论中的讨论,您遇到的问题是我最初提到的原因之一:

  

表单可能正在检查会话cookie或身份验证   cookie,意味着你需要提出一个请求(拿起   cookie)然后做出随后提出的提交表格的请求。

在使用Cookie进行会话跟踪或身份验证的服务器上,如果请求显示没有附加cookie,则服务器通常会重定向到相同的URL。重定向将包含Set-Cookie标头,这意味着当重新请求重定向的URL时,它将具有客户端附加的cookie。如果第一个请求是表单POST,则此方法会中断,因为服务器和/或客户端不处理POST的重定向。

正如我最初描述的那样,修复程序是初始GET请求以获取cookie,然后将POST作为第二个请求,并传回cookie。

像这样:

using System;

public class CookieAwareWebClient : System.Net.WebClient
{
    private System.Net.CookieContainer Cookies = new System.Net.CookieContainer();

    protected override System.Net.WebRequest GetWebRequest(Uri address)
    {
        System.Net.WebRequest request = base.GetWebRequest(address);
        if (request is System.Net.HttpWebRequest)
        {
            var hwr = request as System.Net.HttpWebRequest;
            hwr.CookieContainer = Cookies;
        }
        return request;
    }
} 

class Program
{
    static void Main(string[] args)
    {
        var postData = new System.Collections.Specialized.NameValueCollection();
        postData.Add("appid", "001");
        postData.Add("email", "chris@test.com");
        postData.Add("receipt", "testing");
        postData.Add("machineid", "219481142226.1");
        postData.Add("checkit","checkit");

        var wc = new CookieAwareWebClient();
        string url = "http://www.example.com/licensing/check.php";

        // visit the page once to get the cookie attached to this session. 
        // PHP will redirect the request to ensure that the cookie is attached
        wc.DownloadString(url);

        // now that we have a valid session cookie, upload the form data
        byte[] results = wc.UploadValues(url, postData);
        string text = System.Text.Encoding.ASCII.GetString(results);
        Console.WriteLine(text);
    }
}