連載:Windowsフォーム開発入門【Visual Studio 2010対応】

リモート・データ活用術〜ASP.NET Webサービス編〜

初音 玲
2011/03/09
Page1 Page2

プログラムからのASP.NET Webサービスの利用

 それでは、WebサービスのクライアントとなるWindowsフォームの画面を作成する。

ソリューションを構成する

 Windowsフォームの画面構成や画面遷移は前回作成したものをそのまま使うので、Windowsエクスプローラなどを使って、前回のWindowsフォーム・プロジェクトのフォルダを丸ごと、今回のソリューション・フォルダの直下にコピーしてほしい。

 フォルダのコピーが終わったら、そのフォルダをプロジェクトとしてソリューションに追加する。具体的には[ソリューション エクスプローラー]でASP.NET Webサービスのソリューション項目の右クリック・メニューから[追加]−[既存のプロジェクト]メニューを選択して、そこで表示される[既存プロジェクトの追加]ダイアログで、先ほどコピーしたフォルダの中にあるWindowsフォーム・プロジェクトのファイル(.csproj/.vbprojファイル)を指定する。

 スタートアップ・プロジェクトについても、Windowsフォーム・プロジェクトに切り替えておく(具体的には、[ソリューション エクスプローラー]でプロジェクト項目の右クリック・メニューから[スタートアップ プロジェクトに設定]をクリックする)。

サービス参照を追加する

 ソリューションにプロジェクトを追加できたら、[ソリューション エクスプローラー]でWindowsフォーム・プロジェクトの右クリック・メニューから[サービス参照の追加]を選択する。これにより、図4のような[サービス参照の追加]ダイアログが表示される。

図4 [サービス参照の追加]ダイアログ

 [サービス参照の追加]ダイアログの[探索]ボタンをクリックして、ソリューション内のWebサービスを検索すれば、ASP.NET Webサービスで定義した2つの.asmxファイルが表示される(図4の例では「Login.asmx」と「Titles.asmx」が表示されている)。

 1つの.asmxファイル(例えば「Login.asmx」)を選択して、[名前空間]欄にサービス参照名(例えば「LoginServiceReference」)を入力し、[OK]ボタンをクリックすれば、該当の.asmxファイルに実装したASP.NET Webサービスが呼び出せるようになる。後はWindowsフォーム・プロジェクトで使用するすべての.asmxファイル(例えば「Titles.asmx」)に対して、同じようにサービス参照を追加しておく。

ASP.NET Webサービスを使う ― ログイン認証

 本稿で示すWindowsフォームのサンプル・コードは、データ・アクセス部分をDataAccessクラス・ファイルとして分離したコードになっている。クラス・ファイルの代わりにASP.NET Webサービスを使うには、参照先をクラスからASP.NET Webサービスに切り替えればよい。具体的には下記のようなコードになる。

Private Sub OK_Click(ByVal sender As System.Object,
                     ByVal e As System.EventArgs) Handles OK.Click

  Using _webs As New LoginServiceReference.LoginSoapClient
    Try
      _webs.Endpoint.ListenUri =
        New Uri(My.Settings.Server & _webs.Endpoint.ListenUri.AbsolutePath)
      If _webs.Check(Me.UsernameTextBox.Text, Me.PasswordTextBox.Text) Then
        Me.UserID = Me.UsernameTextBox.Text
        Me.Password = Me.PasswordTextBox.Text
        Me.DialogResult = DialogResult.OK
      Else
        MessageBox.Show("ログイン失敗", Me.Text)
      End If
    Catch ex As Exception
      MessageBox.Show(ex.Message, Me.Text)
    End Try
  End Using

End Sub
private void OK_Button_Click(object sender, EventArgs e)
{
  using (LoginServiceReference.LoginSoapClient _webs = new LoginServiceReference.LoginSoapClient())
  {
    try
    {
      _webs.Endpoint.ListenUri =
        new Uri(WinFormSQLCs.Properties.Settings.Default.Server +
                  _webs.Endpoint.ListenUri.AbsolutePath);
      if (_webs.Check(this.UsernameTextBox.Text, this.PasswordTextBox.Text))
      {
        UserID = this.UsernameTextBox.Text;
        Password = this.PasswordTextBox.Text;
        this.DialogResult = System.Windows.Forms.DialogResult.OK;
        this.Close();
      }else{
        MessageBox.Show("ログイン失敗", this.Text);
      }
    }
    catch (Exception ex)
    {
      MessageBox.Show(ex.Message, this.Text);
    }
  }
}
リスト5 Webサービス(Checkメソッド)経由でログインを行うコード例(上:VB、下:C#)
「LoginServiceReference」は先ほど指定したサービス参照名。「LoginSoapClient」はサービス参照により自動生成されたクライアント・クラス名で、ASP.NET Webサービスのメソッドを利用するためのものである。「LoginSoapClient」というクラス名は、そのメソッドが所属する「Login」クラスの名前の語尾に、「SoapClient」という語句が自動的に付加されている。「_webs」は、そのLoginSoapClientクラスのオブジェクトである。

 このコードでは、Webサービス(Checkメソッド)経由でログインを行っている。

 「_webs.Endpoint.ListenUri」というコードは、ASP.NET Webサービスを呼び出すためのURLになる。本稿のサンプル・プログラムでは、このプロパティに設定する(サーバ名とポート番号を含む)URLを(設定情報として)App.Configファイルに記述しており(参考:「.NET TIPS:アプリケーション設定を活用するには?」)、リスト5のコードではその設定情報を利用するようにしている。このため、実行環境のWebサーバが変わった場合も、App.Configファイルの記述を書き換えるだけで対応できる。

ASP.NET Webサービスを使う ― 一覧表示

 Webサービス(GetTitleDsメソッド)経由で全件のレコードを取得する場合のクライアント・コードは、リスト6のようになる。

Using _webs As New TitlesServiceReference.TitlesSoapClient
  _webs.Endpoint.ListenUri =
    New Uri(My.Settings.Server & _webs.Endpoint.ListenUri.AbsolutePath)
  Me.Result_DataGridView.DataSource =
    _webs.GetTitleDs(Me.UserID,
                     Me.Password,
                     Me.Search_TextBox.Text.Trim)
  Me.Result_DataGridView.DataMember = "TitleList"
End Using
using (TitlesServiceReference.TitlesSoapClient _webs = new TitlesServiceReference.TitlesSoapClient() )
{
  _webs.Endpoint.ListenUri =
    new Uri(WinFormSQLCs.Properties.Settings.Default.Server +
             _webs.Endpoint.ListenUri.AbsolutePath);
  this.Result_DataGridView.DataSource =
    _webs.GetTitleDs(this.UserID,
                     this.Password,
                     this.Search_TextBox.Text.Trim());
  this.Result_DataGridView.DataMember = @"TitleList";
}
リスト6 Webサービス(GetTitleDsメソッド)経由でデータセットを取得して一覧表示を行うコード例(上:VB、下:C#)

 前述したTitles.asmxファイルのGetTitleDsメソッドの記述内容を見ると分かるように、ASP.NET Webサービスのメソッドからの戻り値をデータセットにすることもできる。そのデータセットの戻り値をDataGridViewコントロールのDataSourceプロパティに設定すれば、一覧表示が簡単に実現できる。

ASP.NET Webサービスを使う ― 1レコード表示

 Webサービス(GetTitleDsItemメソッド)経由で1レコード分を取得する場合のクライアント・コードも、基本的には前述の手法と同じだ(リスト7参照)。

Using _webs As New TitlesServiceReference.TitlesSoapClient
  _webs.Endpoint.ListenUri =
    New Uri(My.Settings.Server & _webs.Endpoint.ListenUri.AbsolutePath)
  Me.EditDs = _webs.GetTitleDsItem(Me.EditUserID,
                                   Me.EditPassword,
                                   Me.EditTitleID)
  Me.Edit_BindingSource.DataSource = Me.EditDs.Tables("EditTitle")
  Me.TitleId_TextBox.DataBindings.Add(
    New Binding("Text",
                Me.Edit_BindingSource,
                "title_id",
                True,
                DataSourceUpdateMode.OnValidation,
                String.Empty))
                             
                             
                           (中略)
                             
                             
  If Me.EditDs.Tables("EditTitle").Rows.Count > 0 Then
     Me.OK_Button.Enabled = True
  Else
    Me.OK_Button.Enabled = False
  End If
  IsUpdate = False
End Using
using (TitlesServiceReference.TitlesSoapClient _webs = new TitlesServiceReference.TitlesSoapClient() )
{
  _webs.Endpoint.ListenUri =
    new Uri(WinFormSQLCs.Properties.Settings.Default.Server +
              _webs.Endpoint.ListenUri.AbsolutePath);
  this.EditDs = _webs.GetTitleDsItem(this.EditUserID,
                                     this.EditPassword,
                                     this.EditTitleID);
  this.Edit_BindingSource.DataSource = this.EditDs.Tables["EditTitle"];
  this.TitleId_TextBox.DataBindings.Add(
    new Binding("Text",
                this.Edit_BindingSource,
                "title_id",
                true,
                DataSourceUpdateMode.OnValidation,
                String.Empty));
                             
                             
                           (中略)
                             
                             
  if (this.EditDs.Tables["EditTitle"].Rows.Count > 0)
  {
     this.OK_Button.Enabled = true;
  }
  else
  {
    this.OK_Button.Enabled = false;
  }
  IsUpdate = false;
}
リスト7 Webサービス(GetTitleDsItemメソッド)経由で1レコードを取得するコード例(上:VB、下:C#)

 このサンプル・コードでは、ASP.NET Webサービス(のGetTitleDsItemメソッド)からデータセットを受け取ったら、それを更新時に使うために(「EditDs」という名前のDataSet型のフィールド変数)に保存し、さらにバインディングソース(BindingSource)経由で各コントロールに値を渡すことで(=データ連結することで)、1レコード分の画面表示を実現している。

ASP.NET Webサービスを使う ― 1レコード更新

 最後に、Webサービス(SetTitleDsItemメソッド)経由で1レコードを更新する場合のクライアント・コードをリスト8に示す。

Me.Edit_BindingSource.EndEdit()
Using _webs As New TitlesServiceReference.TitlesSoapClient
  _webs.Endpoint.ListenUri = New Uri(My.Settings.Server &
                   _webs.Endpoint.ListenUri.AbsolutePath)
  isOK = _webs.SetTitleDsItem(Me.EditUserID,
                              Me.EditPassword,
                              Me.EditTitleID,
                              Me.EditDs)
End Using
this.Edit_BindingSource.EndEdit();
using (TitlesServiceReference.TitlesSoapClient _webs =
   new TitlesServiceReference.TitlesSoapClient() )
{
  _webs.Endpoint.ListenUri =
    new Uri(WinFormSQLCs.Properties.Settings.Default.Server +
    _webs.Endpoint.ListenUri.AbsolutePath);
  isOK = _webs.SetTitleDsItem(this.EditUserID,
                              this.EditPassword,
                              this.EditTitleID,
                              this.EditDs);
}
リスト8 Webサービス(SetTitleDsItemメソッド)経由で1レコードを更新するコード例(上:VB、下:C#)

 本稿のサンプル・コードのように、バインディングソース(BindingSource)を使ってデータセットとコントロールをデータ連結した場合の利点は、エンド・ユーザーがWindowsフォーム上で変更した値をデータセットに簡単に反映できる点だ。

 リスト8では、バインディングソース(BindingSource)のEndEditメソッドによりデータセットに値を反映したうえで、ASP.NET WebサービスSetTitleDsItemメソッドにそのデータセットを渡して更新を実行している。

まとめ

 次の画面は、本稿のサンプル・アプリケーションを実行した結果だ。

図5 本稿のサンプル・アプリケーションの実行結果

 今回のリモート・データ・アクセスの手法は、「WindowsフォームというGUI部分」と「データ・アクセスというロジック部分」を分離するという(よく推奨される)設計指針と、同じ考え方の上に成り立っている。このように、Windowsフォームのアセンブリ(=.EXEファイル)の中からデータ・アクセス処理を抜き出してASP.NET Webサービス化することに、どのような意味があるのだろうか。

 簡単にいえば、その方が運用が楽になる、という意味がある。Windowsフォームは各エンド・ユーザーのクライアントPCに配布して実行することになるが、ASP.NET Webサービスはサーバ・コーナーやサーバ室に設置したサーバ群で稼働する。このため、ロジック部分をASP.NET Webサービス化しておくことで、ロジック部分の変更だけであれば(サーバ群に対してのみ再配布すればよいので、クライアントPCすべてに配布する場合に比べて)圧倒的に配布先が少なくて済む。そして「ロジック部分だけの変更」というケースは、業務アプリケーションを作成していると意外に多い。結果として、Windowsフォーム・アプリケーションの運用面での不便さである「配布」という問題に対して現実的な解決策の1つになり得る。

 また、RDBMSを直接使わないことにより、Windowsフォーム側で必要なデータだけをネットワーク経由でやり取りすることになるので、全体的なレスポンスの向上も見込める。この手法は、過去の事例でいうところの「ストアド・プロシージャを多く採用して、ネットワーク経由で発行するSQL文を減らすことで、レスポンス向上を図る手法」とコンセプトは一緒である。

 そして、Visual Studioでは、WindowsフォームとASP.NET Webサービスを1つのソリューションとして一括管理でき、両者のやり取りをシームレスにステップ実行できるため、効率よく構築・テストが行える点も見逃せない。end of article


 INDEX
  [連載]Windowsフォーム開発入門【Visual Studio 2010対応】
  リモート・データ活用術〜ASP.NET Webサービス編〜
    1.SQL ServerにアクセスするASP.NET Webサービスの作成
  2.プログラムからのASP.NET Webサービスの利用

インデックス・ページヘ  「Windowsフォーム開発入門」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH