2015-09-16 3 views
0

Я использую HTML Agility Pack для загрузки некоторых страниц, я также сохраняю информацию о файлах cookie и информацию для входа из формы. Проблема, с которой я сталкиваюсь, заключается в том, что я делаю операцию GET, чтобы получить информацию о файле cookie и детали формы, поэтому на следующем шаге он может войти с использованием имени пользователя и пароля, тогда я пытаюсь установить значение имени пользователя и поля ввода пароля, чтобы затем я мог отправить на страницу входа. Поля ввода сохраняются в Dictionary<string,string>. Я могу изменить одно из значений словаря, но после того, что я получаю ошибку:C# Изменение нескольких значений словаря вызывает ошибку

"Object reference not set to an instance of an object.".

Если я пытаюсь изменить пароль и имя пользователя по имени пользователя бросает ошибку, и наоборот. Это код im, использующий:

class Main 
{ 
private void testLogin() 
     { 
       BrowserSession b = new BrowserSession(); 
       b.Get("login.html"); 
       b.FormElements["email_address"] = @"email"; 
       b.FormElements["password"] = "password"; 
       string response = b.Post("index.php?main_page=login"); 
      } 
     } 
} 

public class BrowserSession 
{ 
    private bool _isPost; 
    private HtmlDocument _htmlDoc; 

    /// <summary> 
    /// System.Net.CookieCollection. Provides a collection container for instances of Cookie class 
    /// </summary> 
    public CookieCollection Cookies { get; set; } 

    /// <summary> 
    /// Provide a key-value-pair collection of form elements 
    /// </summary> 
    public FormElementCollection FormElements { get; set; } 

    /// <summary> 
    /// Makes a HTTP GET request to the given URL 
    /// </summary> 
    public string Get(string url) 
    { 
     _isPost = false; 
     CreateWebRequestObject().Load(url); 
     return _htmlDoc.DocumentNode.InnerHtml; 
    } 

    /// <summary> 
    /// Makes a HTTP POST request to the given URL 
    /// </summary> 
    public string Post(string url) 
    { 
     _isPost = true; 
     CreateWebRequestObject().Load(url, "POST"); 
     return _htmlDoc.DocumentNode.InnerHtml; 
    } 

    /// <summary> 
    /// Creates the HtmlWeb object and initializes all event handlers. 
    /// </summary> 
    private HtmlWeb CreateWebRequestObject() 
    { 
     HtmlWeb web = new HtmlWeb(); 
     web.UseCookies = true; 
     web.PreRequest = new HtmlWeb.PreRequestHandler(OnPreRequest); 
     web.PostResponse = new HtmlWeb.PostResponseHandler(OnAfterResponse); 
     web.PreHandleDocument = new HtmlWeb.PreHandleDocumentHandler(OnPreHandleDocument); 
     return web; 
    } 

    /// <summary> 
    /// Event handler for HtmlWeb.PreRequestHandler. Occurs before an HTTP request is executed. 
    /// </summary> 
    protected bool OnPreRequest(HttpWebRequest request) 
    { 
     AddCookiesTo(request);    // Add cookies that were saved from previous requests 
     if (_isPost) AddPostDataTo(request); // We only need to add post data on a POST request 
     return true; 
    } 

    /// <summary> 
    /// Event handler for HtmlWeb.PostResponseHandler. Occurs after a HTTP response is received 
    /// </summary> 
    protected void OnAfterResponse(HttpWebRequest request, HttpWebResponse response) 
    { 
     SaveCookiesFrom(response); // Save cookies for subsequent requests 
    } 

    /// <summary> 
    /// Event handler for HtmlWeb.PreHandleDocumentHandler. Occurs before a HTML document is handled 
    /// </summary> 
    protected void OnPreHandleDocument(HtmlDocument document) 
    { 
     SaveHtmlDocument(document); 
    } 

    /// <summary> 
    /// Assembles the Post data and attaches to the request object 
    /// </summary> 
    private void AddPostDataTo(HttpWebRequest request) 
    { 
     string payload = FormElements.AssemblePostPayload(); 
     byte[] buff = Encoding.UTF8.GetBytes(payload.ToCharArray()); 
     request.ContentLength = buff.Length; 
     request.ContentType = "application/x-www-form-urlencoded"; 
     System.IO.Stream reqStream = request.GetRequestStream(); 
     reqStream.Write(buff, 0, buff.Length); 
    } 

    /// <summary> 
    /// Add cookies to the request object 
    /// </summary> 
    private void AddCookiesTo(HttpWebRequest request) 
    { 
     if (Cookies != null && Cookies.Count > 0) 
     { 
      request.CookieContainer.Add(Cookies); 
     } 
    } 

    /// <summary> 
    /// Saves cookies from the response object to the local CookieCollection object 
    /// </summary> 
    private void SaveCookiesFrom(HttpWebResponse response) 
    { 
     if (response.Cookies.Count > 0) 
     { 
      if (Cookies == null) Cookies = new CookieCollection(); 
      Cookies.Add(response.Cookies); 
     } 
    } 

    /// <summary> 
    /// Saves the form elements collection by parsing the HTML document 
    /// </summary> 
    private void SaveHtmlDocument(HtmlDocument document) 
    { 
     _htmlDoc = document; 
     FormElements = new FormElementCollection(_htmlDoc); 
    } 
} 

public class FormElementCollection : Dictionary<string, string> 
{ 
    /// <summary> 
    /// Constructor. Parses the HtmlDocument to get all form input elements. 
    /// </summary> 
    public FormElementCollection(HtmlDocument htmlDoc) 
    { 
     var inputs = htmlDoc.DocumentNode.SelectSingleNode("//div[@id = 'loginDefault']").Descendants("input"); 
     foreach (var element in inputs) 
     { 
      string name = element.GetAttributeValue("name", "undefined"); 
      string value = element.GetAttributeValue("value", ""); 
      if (!name.Equals("undefined")) { Add(name, value); } 
     } 
    } 

    /// <summary> 
    /// Assembles all form elements and values to POST. Also html encodes the values. 
    /// </summary> 
    public string AssemblePostPayload() 
    { 
     StringBuilder sb = new StringBuilder(); 
     foreach (var element in this) 
     { 
      string value = HttpUtility.UrlEncode(element.Value); 
      sb.Append("&" + element.Key + "=" + value); 
     } 
     return sb.ToString().Substring(1); 
    } 
} 

Любая помощь будет очень признательна.

+2

В качестве протектора CsQuery является современной альтернативой HAP. Я настоятельно рекомендую вам попробовать, это спасло меня много времени. Что касается вашего фактического вопроса, можете ли вы, пожалуйста, изолировать проблему дальше? См. [Mcve] –

+3

Какая строка в вашем коде является исключением? – CathalMF

+0

Почему бы не использовать отношения словаря-словаря, а не отношения слова-словаря? Вы должны создать обертки для необходимых методов/индексаторов, но это более понятно с точки зрения моделирования бизнес-домена. [Эта ссылка] (http://stackoverflow.com/questions/21692193/why-not-inherit-from-listt) аналогична, хотя она касается списков; Ответ Эрика Липперта объясняет, о чем я говорю. Состав –

ответ

0

В то время как отладка помещает точку останова после вызова b-составляющего. Вы найдете FormElements property Null.

Вам необходимо сделать тактилизацию в браузере.

Смежные вопросы