サーバーとデータを交換する機能を備えたASP.NET AJAXコントロールを作成する

こんにちは、Habr!



問題を解決した経験を共有したいのですが、その答えはインターネットではほとんど見つけることができません(ロシア語-確かに)。



最近、サーバー側のASP.NET AJAXコントロールを記述するように指示されたという事実に遭遇しました。 これは、デザイナー(ツールボックス)でASP.NETページを編集するときに使用できるコントロールであり、そのロジックの一部はサーバー上にあり、クライアント上の一部は相互作用がajaxです。 私のコントロールの本質は単純なComboBoxであり、サーバーから動的にデータを受け取り(一度に読み込むことができないほど多くのデータがあると想定されます)、テキストフィールドに入力された文字に基づいてリストをフィルター処理します。 AJAX Control Toolkitでほぼ実装されており、リスト全体がそこにロードされます。

インターネット上には、独自のコントロールの作成に関するトピックに関するかなり多くの異なる記事とブログがありますが、奇妙なことに、それらはすべて単純な例に限定されており、クライアントとサーバー間の相互作用のメカニズムの説明が完全に欠けています。 ほとんどのソースは、標準のMicrosoft教科書から引用しています。ajaxは、ボタンの上にマウスを置くと、画像(幼稚園)が変更されるというものです。 サーバーに保存されているリストからクライアントのリストにデータを取得する必要がありました(リスト、何らかのORM、および一般的に発生するすべてのIEnumerableである可能性があります)。



ドキュメントのこの部分に十分な情報があるので、ここでは、最初から独自のコントロールを作成するためのマニュアルは見つかりません。 クライアント部分とそのサーバーが非同期モードで自由に情報を交換できるようにする方法を説明します。



私はポイントに渡します。 ASP.NETには、クライアントがサーバーから非同期にデータを要求できる方法がいくつかあります。 最も便利なのは、Webサービスを介した対話です。 このアプローチにより、ラインから始めて、本格的なオブジェクト(複合オブジェクトを含む)で終わる、ユーザーにとって都合の良い任意の形式でデータをやり取りできます。 ASP.NETがすべてのシリアル化を行います。 ただし、その魅力のために、このアプローチは私のタスクに適用できませんでした。「すぐに使える」というすべての機能を備えた制御が必要だったからです。 つまり、彼はそれをページに追加し、データソースを示しました。それだけです-彼はあなたのために残りを行います。 Webサービスをコンポーネントアセンブリに含めることはできません。したがって、Webサービスを使用する後続のページに含めることはできません。 このため、私のコントロールのプログラマーユーザーは、追加のサービスを追加する必要があります。



2番目の方法は、 ICallbackEventHandlerインターフェイスを実装することです 。 このインターフェイスは、それを実装するコントロールがクライアント側コールバックイベント(MSDN)のターゲットになり得ることを示すのに役立ちます。 このインターフェイスには、ブラウザから文字列パラメーターでイベントデータを受け取るRaiseCallbackEventと、結果を返す責任を持つGetCallbackResultの 2つのメソッドがあります。

Ajax機能はどこにいても常に制御されるため、このアプローチは私にとって最も受け入れられました。 次に、サーバー側とクライアント側のコードを提供して、状況を明確にします。



サーバー側:

  1. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  2. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  3. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  4. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  5. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  6. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  7. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  8. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  9. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  10. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  11. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  12. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  13. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  14. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  15. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  16. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  17. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  18. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  19. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  20. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion



  21. #region ICallbackEventHandler implementation public void RaiseCallbackEvent( string eventArg) { m_callbackEventArg = eventArg; } public string GetCallbackResult() { string result = "" ; if (DataSource != null ) foreach ( object o in DataSource) { string item = o.ToString(); if (item.StartsWith(m_callbackEventArg)) result += item + "||" ; } if (result.Length > 2) return result.Substring(0, result.Length - 2); else return "" ; } #endregion





RaiseCallbackEventメソッドは、クライアントから送信された文字列のみを記憶します。 ユーザーがサイトで入力したテキストをコントロールの入力フィールドに保存します。 サンプル結果は、この値でフィルタリングされます。

GetCallbackResultメソッドに 、もう少しロジックがあります。 ここでは、リスト(データソースに格納されている)の要素ごとのトラバーサルが実行され、リスト内の各行がフィルター値と比較され、問題がなければ結果に入力されます。 はい。このアプローチの欠点は、クエリと結果の両方が文字列でなければならないことです。 つまり、データをシリアル化する方法が私たちの関心事です。 私の場合、サブストリング||で異なる行を分離するだけで十分でしたが、より深刻なプロジェクトの場合は混乱する必要があります。



それでは、クライアントコードを見てみましょう。

  1. _populateListBegin: function (){
  2. ifthis .get_loadDynamically()== false ){
  3. this ._filterList( this ._textFilter);
  4. this ._displayList();
  5. }
  6. その他 {
  7. WebForm_DoCallback( this .get_element()。Id、 this ._textFilter、 this ._onPopulateListComplete、 this .get_element()。Id、 nulltrue );
  8. }
  9. }、
  10. _onPopulateListComplete: 関数 (結果、コンテキスト){
  11. var rscb = $ find(コンテキスト);
  12. rscb._processCallbackResult(結果);
  13. }


このコードは、クライアントのJavaScriptで実装されたプロトタイプリストオブジェクトの一部です。 最初の関数は、ユーザーがリストの「展開」ボタンをクリックすると呼び出されます(別のトピックに関連するため、イベント登録とボタンコードは省略されます)。 興味深い点は、サーバー側にアクセスするプロセスを開始するWebForm_DoCallback関数の呼び出しです。 パラメーターとして、コールバック要求の原因となったオブジェクトのID、要求パラメーター(文字列)、応答ハンドラー関数へのデリゲート、応答の処理に使用できるコンテキスト、エラーハンドラー関数へのデリゲート(ここでは必要ありません)を受け取ります制御の簡素化)、および非同期で送信するかどうかを意味するブールパラメータ。 実際、これはajaxリクエストのすべての魔法です。

_onPopulateListComplete関数は、サーバーから応答を受信すると呼び出されます。 オブジェクトのコンテキストでは実行されないため、これにアクセスすると間違った結果になる可能性があることに注意してください。 そのため、オブジェクトのIDのコンテキストを渡しました。



完全なAJAX交換を使用してサーバーコントロールを実装する場合に実行する必要があることはほとんどありません。 ハードヒットしないでください、これは私の最初の投稿です。 内容について質問がある場合(きっとそうなると思います)-コメントで喜んでお答えします。



All Articles