Заполнение формы через HttpWebRequest

karatheodory
Дата: 05.06.2008 14:23:33
Помогите разобраться, что не так :[ На aspx-форме есть два поля - имя и емейл. Нужно её программно заполнить и засобмитить. Делаю так:


req = (HttpWebRequest)HttpWebRequest.Create("http://localhost:8090");
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, application/x-silverlight, */*";
req.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; InfoPath.2; .NET CLR 3.0.04506.648; .NET CLR 3.5.20706)";
string formParams = "TextBoxName=test&TextBoxEmail=test@test.com";

byte[] bytes = Encoding.UTF8.GetBytes(formParams);
req.ContentLength = bytes.Length;
Stream reqStream = req.GetRequestStream();
reqStream.Write(bytes, 0, bytes.Length);
reqStream.Close();
resp = (HttpWebResponse)req.GetResponse();
stream = resp.GetResponseStream();
//выдаю ответ на экран


Не работает, в ответ приходит та же незаполненая форма. Как можно сделать таку штуку?

#include <stdio.h>
webb
Дата: 05.06.2008 14:37:32
karatheodory:
Помогите разобраться, что не так :[ На aspx-форме есть два поля - имя и емейл. Нужно её программно заполнить и засобмитить. Делаю так: req = (HttpWebRequest)HttpWebRequest.Create("http://localhost:8090"); req.Method = "POST"; req.ContentType = "application/x-www-form-urlencoded"; req.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, application/x-silverlight, */*"; req.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; InfoPath.2; .NET CLR 3.0.04506.648; .NET CLR 3.5.20706)"; string formParams = "TextBoxName=test&TextBoxEmail=test@test.com"; byte[] bytes = Encoding.UTF8.GetBytes(formParams); req.ContentLength = bytes.Length; Stream reqStream = req.GetRequestStream(); reqStream.Write(bytes, 0, bytes.Length); reqStream.Close(); resp = (HttpWebResponse)req.GetResponse(); stream = resp.GetResponseStream(); //выдаю ответ на экран Не работает, в ответ приходит та же незаполненая форма. Как можно сделать таку штуку?

а почему Utf8? попробуй ASCII
и попробуй в конце formParams добавить "\r\n" или "\r\n\r\n"
Nisus
Дата: 05.06.2008 14:37:38
если сайт на который вы стучитесь сделан на asp.net 2.0 то там ввели валидацию постбека, посему надо либо отключить ее в конфиге приложения
    <system.web>
        <pages enableEventValidation="false" />
либо делать два запроса, на первом получать значение этого поля для верификации, это одно из <input type="hidden"...> полей формы, с очевидным названием, ну и сабмитить его при втором запросе. Подобная техника, правда для вьюстейта, а не для этого поля, показана тут http://blogs.gotdotnet.ru/personal/nisus/PermaLink.aspx?guid=d8d2ae0c-d7b1-4aab-b7d7-7acb699767bf
Nisus
Дата: 05.06.2008 14:49:16
в общем если быстро и грязно, то как-то так это делается
private string PostRequestToASPX()
{
    string responseData = string.Empty;
    string siteURL = @"http://localhost:8090/default.aspx";
    CookieContainer m_cookies = new CookieContainer();
    // Для начала получим с дефолтовой страницы вьюстейт
    HttpWebRequest request = WebRequest.Create(siteURL) as HttpWebRequest;
    request.CookieContainer = m_cookies;
    using (HttpWebResponse res = (HttpWebResponse)request.GetResponse())
    {
        using (Stream resst = res.GetResponseStream())
            responseData = new StreamReader(resst).ReadToEnd();
        foreach (Cookie cookie in res.Cookies)
            m_cookies.Add( cookie );
    }
    // извлекаем вьюстейт и строим новый запрос
    string postData = String.Format(
       "__VIEWSTATE={0}&TextBoxName=test&TextBoxEmail=test@test.com&BtnSubmit=Submit&__EVENTTARGET=BtnSubmit&__EVENTVALIDATION={1}",
        ExtractViewState(responseData)
        ,ExtractEVENTVALIDATION(responseData));
    byte[] buffer = Encoding.UTF8.GetBytes(postData);
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(siteURL);
    req.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Maxthon; .NET CLR 1.1.4322; .NET CLR 2.0.40607)";
    req.Method = "POST";
    req.ProtocolVersion = new System.Version(1,0);
    req.ContentType = "application/x-www-form-urlencoded";
    req.ContentLength = buffer.Length;
    req.CookieContainer = m_cookies;
    req.AllowAutoRedirect = true;
    // добавим наши параметры в запрос
    using (Stream reqst = req.GetRequestStream())
        reqst.Write(buffer, 0, buffer.Length);
    // отправляем запрос, получаем ответ
    using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
    using (Stream resst = res.GetResponseStream())
        responseData = new StreamReader(resst).ReadToEnd();
    return responseData;
}

private string ExtractViewState(string text)
{
    return ExtractFieldValue(text, "__VIEWSTATE");
}

private string ExtractEVENTVALIDATION(string text)
{
    return ExtractFieldValue(text, "__EVENTVALIDATION");
}

private string ExtractFieldValue(string s, string fieldName)
{
    string viewStateNameDelimiter = fieldName;
    string valueDelimiter = "value=\"";
    int viewStateNamePosition = s.IndexOf(viewStateNameDelimiter);
    int viewStateValuePosition = s.IndexOf(valueDelimiter, viewStateNamePosition);
    int viewStateStartPosition = viewStateValuePosition +
        valueDelimiter.Length;
    int viewStateEndPosition = s.IndexOf("\"", viewStateStartPosition);
    return System.Web.HttpUtility.UrlEncodeUnicode(
        s.Substring(viewStateStartPosition
            ,viewStateEndPosition - viewStateStartPosition));
}
karatheodory
Дата: 05.06.2008 15:19:47
Заработало! Спасибо огромное!
P.S. Какая классная вещь регулярные выражения. А я поиском по строке разбирал :)

#include <stdio.h>
karatheodory
Дата: 06.06.2008 14:49:23
Вдруг кому пригодится :) Результаты моих трудов. Собраны из двух примеров, один из которых выше :), а другой Dimon'a aka Manowar'a.
public static class FillWebForm
{

    static private string ExtractViewState(string content)
    {
        System.Text.RegularExpressions.Regex _regex =
            new Regex(@"[\s\S]+?)\""[\s\S]*?/>",
            RegexOptions.IgnoreCase | RegexOptions.Compiled);
        System.Text.RegularExpressions.Match _match = _regex.Match(content);
        return System.Web.HttpUtility.UrlEncodeUnicode(
            _match.Success
            ? _match.Groups["value"].Value
            : string.Empty);
    }

    static private string ExtractEventValidation(string content)
    {
        System.Text.RegularExpressions.Regex _regex =
            new Regex(@"[\s\S]+?)\""[\s\S]*?/>",
            RegexOptions.IgnoreCase | RegexOptions.Compiled);
        System.Text.RegularExpressions.Match _match = _regex.Match(content);
        return System.Web.HttpUtility.UrlEncodeUnicode(
            _match.Success
            ? _match.Groups["value"].Value
            : string.Empty);
    }

    static private string ExtractEventTarget(string content)
    {
        System.Text.RegularExpressions.Regex _regex =
            new Regex(@"[\s\S]+?)\""[\s\S]*?/>",
            RegexOptions.IgnoreCase | RegexOptions.Compiled);
        System.Text.RegularExpressions.Match _match = _regex.Match(content);
        return System.Web.HttpUtility.UrlEncodeUnicode(
            _match.Success
            ? _match.Groups["value"].Value
            : string.Empty);
    }

    public static string FillASPXPOSTForm(string args, string url, string btnName, string encoding)
    {
        // getting form
        HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
        req.Method = "GET";
        req.ContentType = "application/x-www-form-urlencoded";
        req.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, application/x-silverlight, */*";
        req.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; InfoPath.2; .NET CLR 3.0.04506.648; .NET CLR 3.5.20706)";
        req.ContentLength = 0;        

        HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
        Stream stream = resp.GetResponseStream();

        string[] cookieVal = null;
        if (resp.Headers["Set-Cookie"] != null)
            cookieVal = resp.Headers["Set-Cookie"].Split(new char[] { ',' });

        StreamReader reader = new StreamReader(stream, Encoding.GetEncoding(encoding));
        string ans = reader.ReadToEnd();
        stream.Close();

        // filling and sending
        CookieContainer cookie = new CookieContainer();
        if (cookieVal != null)
        {
            foreach (string cook in cookieVal)
            {
                string[] cookie1 = cook.Split(new char[] { ';' });
                if (cookie1.Length  2 ? cookie1[2].Split(new char[] { '=' })[1] : ""));
            }
        }

        req = (HttpWebRequest)HttpWebRequest.Create(url);
        req.Method = "POST";
        req.ContentType = "application/x-www-form-urlencoded";
        req.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, application/x-silverlight, */*";
        req.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; InfoPath.2; .NET CLR 3.0.04506.648; .NET CLR 3.5.20706)";
        req.CookieContainer = cookie;

        string view = ExtractViewState(ans);
        string eventValidation = ExtractEventValidation(ans);
        string formParams = args + "&__VIEWSTATE=" + view + "&__EVENTTARGET=" + btnName + "&__EVENTVALIDATION=" + eventValidation;

        byte[] bytes = Encoding.UTF8.GetBytes(formParams);
        req.ContentLength = bytes.Length;

        Stream reqStream = req.GetRequestStream();
        reqStream.Write(bytes, 0, bytes.Length);
        reqStream.Close();
        resp = (HttpWebResponse)req.GetResponse();
        stream = resp.GetResponseStream();
        StreamReader sr = new StreamReader(stream, Encoding.GetEncoding(encoding));
        ans = sr.ReadToEnd();
        return ans;
    }
}

#include <stdio.h>
savsergey
Дата: 12.03.2009 03:03:50
Спасибо