codeproject上のAngelSharpの記事「Submitting Forms with AngleSharp」の日本語訳です。
ログインし、データを取得し、ログアウトします。AngleSharpには、私たちは、フォ-ムを提出して、私たちが、望むデータを取得する必要がある、すべてを送信する必要がある、すべてがあります。
概要
Introduction
時々、私たちは、次の問題に直面します:私たちは、いくつかのWebページを介してのみ公開される、いくつかのデータにアクセスする必要があります。残念ながら、ページは、ログイン・フォームを送信した後にのみアクセスできます。私たちは、何ができるのでしょうか?ほとんどの人は、非常に重く、強力なプラットフォームに限定されている、PhantomJSのようなソリューションを即座に選択します。たとえば、一般的なスマートフォンで、PhantomJSを使用しているアプリを展開することはできません。
しかしながら、私たちは幸運です。この問題を解決しようとする、多くのC#プロジェクトが、存在します。また、私たちは、まさに、標準的なHttpClientを選ぶことができ、それを最先端のHTML5パーサで結合します。しかし、それを正しく行うことは面倒であり、W3Cの仕様は膨大です。単純な問題のため、私たちは、それだけで動作する自分で作った解決法を考え出すことができるかもしれません。しかし、ページとそれに伴う問題が変化した時、私たちは、再考する必要があるかもしれません。
最後に、私たちは、すべての私たちの問題を解決する最先端の解決法に興味を持っているかもしれません。この記事では、AngleSharpライブラリについて説明します。それは、完全に管理されたコードで記述された(ヘッドレス)ブラウザの基準を形成します。
背景
Background
既に2年以上前(記事の日付は、2015.8.15)、私は、AngleSharpプロジェクトを開始しました。最初は、まさに、小さなHTML5パーサ・コンポーネントとして企画されました。プロジェクトは、C#でブラウザの基盤を形成するため、かなり早く変化しました。コア・プロジェクトには、HTML5パーサ、CSS3パーサ、単純な(しかし、大部分は十分な)HTTPリクエスタなど、多くのユーティリティが含まれています。スクリプト作成(JavaScriptエンジンの接続など)やレンダリングなどを気にかける(利用可能な、あるいは、リリース予定の)他のライブラリがあります。
AngleSharpの最初のリリースは、CodeProjectにも記載されています。最初の記事では、実装の一部の詳細について説明します。いくつかのものは、内部的に変更され、APIは、成熟しました。現在、私たちは、AngleSharp v0.9のリリースの観察を終了しています。これは、本物の取扱い(AngleSharp v1)の前に、とても短期間です。AngleSharpは、何らかの重大な変更が生じた場合、バージョン番号に、急激な上昇を引き起こす、semverバージョン管理を使用しています。(http://semver.org参照)したがって、v1の前に、できるだけ、APIと拡張機能を安定にする必要があります。
JavaScriptエンジンの接続についても説明しました。AngleSharpに関する2つ目の記事は、内部ライブラリの進歩と今後のロードマップについて概説します。それは、むしろ、外部にある(特に.NETのための)JavaScriptエンジンの技術的な文書でそして、なぜ、私たちが、代わりにJintを選ぶのかを説明します。また、いくつかのJavaScriptエンジンについて学ぶべきことがあります。
この記事は、むしろ、ユーザーに焦点を当てています。私たちは、AngleSharpの(多少の)標準的なデモを説明し、そのAPIを学びます。最も興味深いことは、私たちは、AngleSharpが、Webサイトの閲覧/操作の概念をどのように扱うかを見ていきます。
コードを使用する
Using the code
提供されるコードには、2つのプロジェクトが含まれています:
- とても単純なASP.NET MVC Webページ。
- 基本的なWPFのデスクトップ・アプリケーション。
前者は、私たちが、アクセスしたいと思っているwebサイトを表示するために使用されます。私たちが、興味を持っていた特定のデータは、認証されたユーザーだけが、アクセスできます。後者は、webサイトから、ログインする、データを取得する、そして、ログアウト動作を起動するボタンが含まれている、デスクトップ・アプリケーションです。
webサイトは、次のように見えます。次のスクリーン・ショットは、ランディング・ページを示しています。
機密情報を持つページは、小さなパネルだけが含まれています。それは、次のように見えます。
WPFのクライアントは、実際には、1つのボタンだけから構成されています。アプリケーションのスクリーン・ショット(データを受信した後):
それにもかかわらず、WPFクライアントは、MVVMパターンを使用して、見栄えのよいコードを提供します。VMを見てみましょう:
sealed class MainViewModel : BaseViewModel
{
State _state;
String _content;
RelayCommand _submit;
public MainViewModel()
{
_state = State.Idle;
_content = String.Empty;
_submit = new RelayCommand(async () =>
{
ChangeState(State.Loading);
// To be discussed in "Give Me the Code"
// "Give Me the Code"で説明するために、
ChangeState(State.Finished);
});
}
public Boolean IsIdle
{
get { return _state == State.Idle; }
}
public Boolean IsLoading
{
get { return _state == State.Loading; }
}
public Boolean IsFinished
{
get { return _state == State.Finished; }
}
void ChangeState(State state)
{
_state = state;
TriggerChanged("IsIdle");
TriggerChanged("IsLoading");
TriggerChanged("IsFinished");
}
public RelayCommand Submit
{
get { return _submit; }
}
public String Content
{
get { return _content; }
set
{
_content = value;
TriggerChanged();
}
}
enum State
{
Idle,
Loading,
Finished
}
}
UIには、あまり進んでいないので、実際には、XAMLについて話す必要はありません。基本的に、 私たちが持っているのはボタンとテキストボックスだけです。一旦、ボタンの動作が引き起こされると、状態は、アイドル状態から読み込み状態に変わります。最後に、一度、私たちは、望むデータを受け取り、状態を終了に変更します。
機械の状態は、以下のようになります。:アイドル状態では、利用可能なボタンだけが表示されます。 読み込み状態では、コンテンツとして、"Loading ..."というテキストボックスが表示され、ボタンを無効にします。最後に、完成した状態で、私たちは、テキストボックスだけを見ます。テキストボックスのコンテンツは、私たちが興味を持っている隠れたページのコンテンツです。
AngleSharp API
AngleSharp API
AngleSharpは、完全に機能するDOMをユーザーに公開します。これには、多くのコンポーネントの相互作用が必要です。ライブラリ自体に、これらのコンポーネントのすべて含まれているわけではありません。その代わりに、AngleSharpは、ユーザーが、望む機能を提供することができる、拡張機能点を持っています。提供された(そして、特定の)機能の設定は、IConfigurationインターフェイスのインスタンスに集約されています。
コア・ライブラリには、Configurationと呼ばれて、IConfigurationの標準実装が付属しています。標準的な実装は、、デフォルトの(通常、空の)構成を与える、static Defaultプロパティを提供します。 デフォルトの構成を設定することができます。設定が提供されていない場合、内部で使用されます。そして、その結果、本当に、役に立ちます。
AngleSharpで、HTMLを解析する方法は、たくさんあります。しかし、最も良い方法は、専用のIBrowsingContextを開くことです。ブラウジング・コンテキストは、一般的なブラウザのタブとして見ることができます。それは、独自のセキュリティ設定、構成、および履歴を持つ独立したユニットです。また、それは、文書を読み込むための最も効率のよい習慣に従っています。そして、その結果、 それは、与えられたHTTPリクエスタと、どのように、話すかを知っています。また、それは、ページへの移動やフォームの送信にも便利です。後者は、特に興味深いです。
私たちは、BrowsingContextクラスによってアクセス可能な標準実装を使用する必要があります。新しいインスタンスの作成は、新しい演算子を使用することで、あるいは、静的な新しいメソッドを使用することで、古典的に行うことができます。後者は、連結されたシナリオで、より優れたように見えます。そこで、明示的に、デフォルト構成を使用して新しいコンテキストを作成しましょう。
var context = BrowsingContext.New(Configuration.Default);
構成に機能を追加するには、拡張メソッドを使用します。AngleSharpのプラグインは、同じパターンに従います。ここで、最も重要な概念は、IConfigurationインターフェイスは、gettersを定義するだけです。したがって、不変とみなされています。プラグインに、(構成のような)特定の実装が使用されることを期待できないため、現在の状態を変更することは不可能です。その結果、私たちは、常に、新しい機能による前の構成の集合体になる、新しいIConfigurationインスタンスを受け取ります。
私たちは、新しいもの、IConfigurationオブジェクトのインスタンスを作成するためにWith...()拡張機能メソッドを使用して、拡張しました。私たちの特別な場合では、私たちは、HTTPリクエスタを気にします。AngleSharpには、デフォルトで1つが付属していますが、それは、Configuration.Defaultのデフォルト設定には含まれていません。私たちは、それを含める必要があります。
var configuration = Configuration.Default.WithDefaultRequester();
他の方法として、私たちは、完全に新しい構成から開始するかもしれません。Configuration.Defaultから取得されるものには、すでに、不必要な機能が含まれているかもしれません。他のコードに依存しています。ここでは、私たちは、書き込みます。:
var configuration = new Configuration().WithDefaultRequester();
Configurationをインスタンス化するためのもう1つの利点は、それは、既にサービスを含んでいません。私たちは、ロケール情報を設定できます。これは数字などの扱いに影響を与えません(これらはすべて不変です)。しかし、仕様の一部のカルチャに依存した部分に影響を与える可能性があります。 例えば、デフォルトのエンコーディングサービスは、デフォルトのエンコーディング・サービスを決定するためにカルチャを使用します。また、私たちは、常に、UTF-8を使用するような、行いたい独自のエンコーディング・サービスを統合することもできます。しかし、AngleSharpのデフォルトのサービスの多くは、標準に正確に従うように作成されていることに注意してください。私たちが、独自のコンポーネントで、これらのサービスを置き換える場合、私たちは、標準ではない結果を得るかもしれません。
現在、私たちは、調べるページを読み込むかもしれない、今後のタスクに必要なすべてのサービスが含まれている、IConfigurationで、新しいIBrowsingContextをうまく作成しました。IBrowsingContextのメソッドは、拡張メソッドの形で再び提供されます。これは、具体的な実装から独立しています。IBrowsingContextで定義されている基本的なプロパティの設定の実装だけが必要です。
すべてのメソッドは、非同期です。AngleSharpは、TPLをすべて使用しようとします。(おそらく外部的な)ストリームを使用する、あるいは、なんとかして、キューに入れる必要があるものは何でも、タスクに変換されます。読み込みの仕組みもこれに当てはまります。
私たちが、「空」のページを開く場合、OpenNewAsyncを使用できます。必要に応じて、私たちは、この空のリソースのアドレスを指定することができます。これは、新しい文書のbaseURIになります。 基準となるURLは、フォーム提出と他のものから、ナビゲーションのためだけに興味深いものですが、 私たちが、空の文書を操作する予定がある場合、便利かもしれません。
私たちが、既存のストリーム(おそらくディスクから)、あるいは、既存の文字列インスタンスのどちらかから、"local"ページを開く場合、私たちは、OpenAsyncメソッドのオーバーロードのActionの形で公開される仮想応答インターフェイスを使用することができます。仮想応答は、私たちが、何かの応答を要求します。私たちは、仮定的なサーバから見ることを望みます。
一例として、私たちが、sourceCodeと呼ばれる文字列変数に、Googleのホームページの(固定された)ソースを持っている場合、私たちは、次の命令を使うことができます。:
var document = await context.OpenAsync(res => res.
Address("http://www.google.com").
Status(200).
Header("Content-Language", "en").
Content(sourceCode));
連鎖は、多くのセマンティックを単一のコード行に簡単に移すことができます。読みやすくするため、ステートメントは、複数の行に分割されています。文書の読み込みが完了した後、Task
オープニング・メソッドは、すべて同じように動作します。それらは、(必要に応じて)要求を送信します。応答を取得して、新しい文書を構築するために、応答を使用します。文書は、続いて、非同期で応答のボディから、DOMを構築する、HTMLパーサによって満たされます。
現在のドキュメントは、コンテキスト自体から取得することもできます。コンテクストは、Activeと呼ばれるプロパティを持っています。プロパティは、現在、アクティブなIDocumentを参照します。 それは、疑問に対する答えです:"ブラウジング・タブは、どのような文書を表示していますか?"
現在、私たちは、次の疑問の文書を持っています。-私たちは、それをどうしたらいいでしょうか? 私たちは、QuerySelectorAllを使用する、あるいは、QuerySelectorの最初の要素だけを使用して要素を取得できます。
var anchors = document.QuerySelectorAll("a");
var firstAnchor = anchors.FirstOrDefault();
// Alternatively
var firstAnchorDirect = document.QuerySelector("a");
それは、微妙です。しかし、おそらく、QuerySelectorとQuerySelectorAllとFirstOrDefault LINQ拡張メソッドの組み合わせを使用する場合の重要な違いは次のとおりです。:前者は、最初の一致で停止します。2番目の要素は、すべての要素を繰り返し処理します。理由は、簡単です。: QuerySelectorAllは、既に、完全に評価された設定を返します。それは、遅延評価は使用しません。 それにもかかわらず、大きなメッセージは、戻り値型が、IEnumerable<IElement>を実装するということです。そして、その結果、結果に、LINQステートメントを使用できます。
一つの要素は、基準となるインターフェイスIElementによって表示されます。しかし、IElementは、プロパティやメソッドを公開していないかもしれません。私たちは、アンカー要素(IHtmlAnchorElement)が必要です。私たちは、LINQを使用して、キャストを実行できます。あるいは、私たちは、いくつかの便利なメソッドのためのAngleSharp.Extensionsが含まれています。:
var anchorsWithLinq = document.QuerySelectorAll("a").OfType<IHtmlAnchorElement>();
var anchorsConvinient = document.QuerySelectorAll<IHtmlAnchorElement>("a");
型変換は、JavaScriptを使用するより、DOMの操作が楽しくなる、腹立たしい事の1つです。しかし、 それは、また、はるかに信頼性が高く、安定したDOMでの作業になります。
また、アンカー要素は、IUrlUtilitiesを実装しています。これは、URLを要素に関連付けます。もちろん、私たちは、このURLに移動することもできます。しかし、私たちは、URLを取得する必要はありません。ブラウジング・コンテキストと接続して、ナビゲーションを開始します。その代わりに、私たちは、拡張機能で設定されたものからNavigateメソッドだけを呼び出します。
var anchor = document.QuerySelector<IHtmlAnchorElement>("a");
if (anchor != null)
document = await anchor.Navigate();
nullの確認は、冗長かもしれませんが、それを使うことは、より優れています。このような要素が見つからない場合、QuerySelectorメソッドは、nullを返します。ナビゲーション・メソッドは、期待されるように、非同期です。それは、ナビゲーションの目標の文書を返します。理論的には、私たちは、利便性のために、context.Activeを使用することができますが、私たちは、ドキュメント変数を再割り当てするだけです。
文書の操作も簡単に行えます。私たちは、公式のDOMメソッドや便利なラッパーを使用できます。 これらのラッパーは、jQueryによく似ています。通常、それらは、Tが、IElementを実装する必要があるIEnumerable<T>として与えられる、一連の要素で動作します。
var anchors = document.QuerySelectorAll<IHtmlAnchorElement>("a");
anchors.AddClass("my-anchor-class").Attr(new { foo = "bar" });
document.QuerySelector("body").ClassList.Add("cs-body-element");
通常のDOM操作のための便利な拡張機能もあります。最も重要なことに、IDocumentのCreateElementメソッドは、C#のための素晴らしい追加を取得しました。通常、このファクトリ・メソッドは、単に、例えば、要求された要素名に合わせたIElementインスタンスを返します。
var div = document.CreateElement("div");
しかし、この方法を使用することは、追加のキャストを必要とするかもしれません。私たちが、より特殊なプロパティやメソッドにアクセスしたい場合、また、そこに、私たちは、後になって、DOMインターフェイスを実装する単一のクラスだけです。それで、たとえば、次のように記述して、新しいHTMLアンカー要素を作成することができます。:
var newAnchor = document.CreateElement<IHtmlAnchorElement>();
ここには、文字列は必要ありません。全体として、この方法は、C#で優先されるべきですが、(通常、より特殊化されたインタフェースの場合)実装するクラスが1つしかない場合、そして、その結果、名前が、インターフェイスに1:1にマッピングされる場合に限ります。この場合、タグ名aは、IHtmlAnchorElementに、1:1でマッピングします。
新しい要素の作成は、ストーリーのわずか半分です。要素が、ツリーに付けられていない限り、それは、クエリやあらゆる種類のレンダリングに統合されることはありません。AppendNodeメソッドは、連鎖できますが、INodeインスタンスのみを返します。私たちのために幸いなことに、AppendElement<T>メソッドがあります。追加された要素を対応する型とともに返します。
これにより、以下のようなコードを動作させることができます。
document.Body.AppendElement(document.CreateElement<IHtmlAnchorElement>()).Href = "http://www.google.com";
フォーム要素は、AngleSharpで構築、操作、使用することができます。ブラウザと同様、最も重要な要素は、HtmlFormElementそのものです。次に、IHtmlInputElement、IHtmlButtonElement、IHtmLTextareaElementの要素が混在しています。 もちろん、IHtmlInputElementは、最も使用されているものかもしれません。それは、それ自身、Typeプロパティを変更して設定する多くの状態へのホストです。
var input = document.CreateElement<IHtmlInputElement>();
input.Type = "hidden";
既定では、Typeを、テキストに設定します。型は、同じ(特に検証)メソッドの動作に影響します。AngleSharpは、制約検証モデルを含む、HTML5入力型の完全なスイートを実装しています。これにより、ブラウザのようにフォームの検証が可能になります。
これらの原則から、私たちの例のコードがどのように見えるかを見てみましょう。
コードを教えてください
Give Me the Code
私たちは、NuGetを通して、AngleSharpをインストールすることによって、開始します。私たちは、プロジェクトを右クリックし、 "Manage NuGet Packages ..."を選択します。続いて、オンラインでAngleSharpを検索し、インストールをクリックします。また、パッケージは、NuGet webサイトで、見つけることができます。
次に、私たちは、いくつかの重要な名前空間を追加する必要があります。最も重要なことは、これには、BrowsingContext、ConfigurationとIConfigurationのための拡張機能が含まれているため、私たちには、AngleSharp名前空間が必要です。私たちは、AngleSharp APIの動作に役立つヘルパーが含まれているため、AngleSharp.Extensionsも必要です。最後に、私たちは、AngleSharp.Dom、あるいは、さらに専門化されたものや、AngleSharp.Dom.Htmlを追加することも必要です。この簡単な例では、後者だけが必要です。
using AngleSharp;
using AngleSharp.Dom.Html;
using AngleSharp.Extensions;
次に、Webサーバーを決定しましょう。これは、アプリケーションのユーザーによって、入力できます。あるいは、いくつかの設定ファイルに与えられています。私たちは、global static readonlyフィールドの形で、それをハードコードします。
static readonly String WebsiteUrl = "http://localhost:54361";
最終的な手順として、私たちのViewModelの定義で、私たちは、空の部分を記入する必要があります。 私たちは、Submit RelayCommandのアクションを指定したかったのです。
私たちは、コードを詳細に調べる前に、私たちは、それを一目で把握する必要があります。コードは、長くありませんが、それは、たくさんあります。
_submit = new RelayCommand(async () =>
{
ChangeState(State.Loading);
var configuration = Configuration.Default.WithDefaultLoader().WithCookies();
var context = BrowsingContext.New(configuration);
await context.OpenAsync(WebsiteUrl);
await context.Active.QuerySelector<IHtmlAnchorElement>("a.log-in").Navigate();
await context.Active.QuerySelector<IHtmlFormElement>("form").Submit(new
{
User = "User",
Password = "secret"
});
await context.Active.QuerySelector<IHtmlAnchorElement>("a.secret-link").Navigate();
Content = context.Active.QuerySelector("p").Text();
ChangeState(State.Finished);
});
上記のコードの要点を要約しましょう。実際には、いくつかのステップがあります。そして、事実、私たちは、実際に、非常に短時間で、それらをすべて行うことができること(ローカル接続の場合は、1秒をはるかに下回り、例えば、私のマシンでは、デバッグビルドに200msかかります。)は、注目に値します。さらに驚くべきことには、開発のスピードがあります。このソリューションの実装には、5分未満で行えます。
- ランディング・ページを読み込みます。
- クラスlog-inを持つ、アンカー要素のURL(href)に移動します。
- ログイン・ページが、読み込まれるまで待ちます。
- 匿名オブジェクトで提供されるキーと値のペアを使用して、フォーム(ページの最初/唯一のフォーム)を送信します。
- フォームが、提出されるのを待ち、応答を受け取ります。
- クラスsecret-linkを持つアンカー要素のURL(href)に移動します。
- 内容のページが、読み込まれるまで待ちます。
- ページ上の最初/唯一の段落の(テキストの)内容を読み込み込む
コードの中で最も重要な部分は、何でしょうか?適切な設定は、間違いなく重要です。ローダーなしで、私たちは、HTTPリクエスタを持っていません。私たちは、ネジ止めするでしょう。クッキーなしでは、私たちは、あるページから、次のページへ認証を転送することはできません。また、私たちは、検証トークンを検証することもできません(詳細は後で説明します)。 このため、クッキーは、検証されるログイン・フォームやフォームの必須アイテムです。
var configuration = Configuration.Default.WithDefaultLoader().WithCookies();
ナビゲーション・プロセスは、以前に、かなり説明されていましたが、私たちは、フォーム提出の多くの詳細には入っていません。AngleSharpでフォ-ム提出を行うための、多くの方法があります。 おそらく最も一般的な2つの方法は、次のとおりです。:
- IHtmlInputElementやIHtmlTextareaElementのような、含まれている入力要素を反復処理します。そして、Nameが一致する場合、Valueを記入します。
- ヘルパー・メソッドを使用して、対応する名前-値-対を伝える、キーと値のペアのIEnumerableを配信します。あるいは、そのようなディクショナリに変換される、匿名オブジェクトを提供するヘルパーを使用します。
私たちの例では、私たちは、後者を使用します。私たちの入力名は、匿名オブジェクトの方法を使用するために、適しています。それらが、風変わりである場合、私たちは、有効なC#識別子を使用できない可能性があります。私たちは、かなり短いコード行になります。それは、(うまくいけば、正しい!)フォームの選択から、それを記入して提出するまでのすべてを行います。
context.Active.QuerySelector<IHtmlFormElement>("form").Submit(new
{
User = "User",
Password = "secret"
});
これらの手順は、すべてを行います。私たちは、ホームページからデータを収集する必要があります。 ログインの正確なURLを知らなくても、私たちは、適切な要素だけを選択するためのセレクタを知る必要があります。そして、それらのURLに移動します。また、私たちは、入力領域(名前とこの場合の要求された値)を知っている必要があります。すべてを段階的に調査することができます。
webサイトに関する限り、何も特別なものはありません。私たちは、標準フォーム認証モデルを使用しています。次のコード・スニペットは、HomeControllerクラスの最も重要な動作を示しています。 これは、単純なデモであるため、私たちは、データベースや高度な認証メカニズムは使用していません。提供された証明書が期待さするもの(1つだけがあります)と一致する場合、私たちは、確認だけを行います。
最も重要なことは、Secret動作の背後にある情報が保護されていることです。私たちは、標準のAuthorizeAttributeを使用して、認証チェックの責任をフレームワークに渡します。
[HttpGet]
public ViewResult LogIn()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogIn(LogInModel model)
{
if (model.User == "User" && model.Password == "secret")
{
FormsAuthentication.SetAuthCookie(model.User, false);
return RedirectToAction("Index");
}
return View(model);
}
[HttpGet]
public RedirectToRouteResult LogOut()
{
FormsAuthentication.SignOut();
return RedirectToAction("LogIn");
}
[HttpGet]
[Authorize]
public ViewResult Secret()
{
return View();
}
理解するために重要なもう一つのことは、ログイン動作を評価するための偽造防止トークンの使用です。言うまでもなく、明示的に、ログイン・ページを読み込む必要があります。私たちが、直接、フォーム・データをサーバーに送信する場合、私たちは、作成された偽造防止トークンを見逃すでしょう。それゆえに、ValidateAntiForgeryTokenAttributeは、評価時に否定的な結果になります。 結果として、私たちは、ログインすることができません。これは、もちろん、望ましくないものです。 もう一つは、AngleSharpを使用するために、有効なBrowsingContextから開始することを、判断します。
関心のポイント
私は、いくつかの会議やユーザーグループの会議で、このデモのより完全な変種を紹介しました。最初の講演は、Developer Week 2015で行われました。あなたは、GitHub上に、最初のサンプルを見つけることができます。あなたが、プレゼンテーションに興味がある場合、私のページのスライドを見てください。
聴衆の反応は、極めて、熱狂的できです。私が、デモを実現していますが、JavaScriptエンジンへの接続を示すことは、更に人気があります。私は、正しいフォーム提出とHTTP処理は、どのHTMLツールにとっても不可欠だと考えています。結局は、HTMLコードのほとんどは、私たちは、サーバからやってくるものに興味を持っています。これらのサーバーとの通信が、他のライブラリをインストールするか、カスタム実装を提供することなく、できる必要があります。
なぜ、AngleSharpコア・ライブラリから、HTTPリクエスタは、制限されていますか?個人的には 私は、この機能を強化したいと思います。しかし、AngleSharpが、PCL(プロファイル259)として配布されているため、私たちは、プラットホームの特定の機能に、アクセスすることができません。幸いなことに、使用されたPCLプロファイルには、HTTPリクエスタ(WebRequestとHttpWebRequestの派生)が付属しています。この機能により、コア・ライブラリからの基本的なHTTP要求ができます。それにもかかわらず、提供されたリクエスターには、プラットフォームに依存するいくつかの問題点やプラットフォームに依存しない欠陥があります。例えば、私たちは、いくつかのHTTP接続のための証明書を受け入れることができません。
将来は、(AngleSharp.Ioと呼ばれる)ライブラリが、あるでしょう。それは、より優れた解決法を提供します。しかしながら、これは当然、PCLと比べて、より強い依存関係を持っています。これらのライブラリは、すべてAngleSharp GitHub体系の一部です。