続・WCF最初の一歩

基本的なWCFサービスと呼び出しを作る6つのタスクと前回までの終了分

  • サービスコントラクトを定義する
  • サービス コントラクトを実装する
  • 基本的なサービスをホストおよび実行する
  • クライアントを作成する
  • クライアントを構成する
  • クライアントを使用する

そんなわけで、今回はクライアントを作っていきます。

クライアントを作成する

プロジェクト作成

前回サービスを作ったプロジェクトと同じソリューションにクライアントのプロジェクトを作成します。クライアントもコンソールアプリケーションで作るみたいです。
だいたいこんな感じになるはずです。

WCFTutrial.sln
Client/
  Client.proj
  Program.cs
Service/
  Service.proj
  ICalculator.cs
  Program.cs
参照追加

ClientプロジェクトにSystem.ServiceModelの参照を追加します。
次にClientプロジェクトの生成時にできたProgram.csにSystem.ServiceModel名前空間を追加します。

サービスを作動させる

前回作成したサービスを起動します。
今回はとりあえずbin/Debugの下にできているService.exeを起動させておきます。
一応ブラウザでhttp://localhost:8000/ServiceModelSample/Serviceを見てサービスが動いているか確認しておきます。

Service Model Metadata Utility Toolでクライアント用のサービスプロキシを作成する

手順(ほぼチュートリアルのまんま)
1. スタートすべてのプログラムMicrosoft Visual Studio 2008Visual Studio ToolsVisual Studio 2008 コマンド プロンプトを起動(チュートリアルではWindows SDKにあると記述してあるが無かったので)
2. 起動したコマンドプロンプトsvcutilにパスが通っているか確認。使い方が出てきたらOK

c:\Program Files\Microsoft Visual Studio 9.0\VC>svcutil

3. Clientプロジェクトまでコマンドプロンプトで移動
4. Clientプロジェクトにいる状態で以下のコマンドを発行

C:\WCFTutorial\Client>svcutil /language:cs /out:generatedProxy.cs /config:app.config http://localhost:8000/ServiceModelSample/Service

5. ClientプロジェクトにgeneratedProxy.csが生成されているのでプロジェクトに追加する。

■svcutilのオプションと引数
詳細な説明はMSDNServiceModel メタデータ ユーティリティ ツール (Svcutil.exe)を参照するといいかも。

オプション 説明 既定値 短縮形
/language: 生成するコードの言語を指定 c#、cs、csharp、vbvisualbasicc++、cpp csharp /l
/out: 生成されるコードのファイル名を指定 任意 WSDLの定義名・サービス名から派生。今回ならCalculatorService.csが既定 /o
/config: 生成される構成ファイルの名前を指定 任意 output.config 無し

引数は、今回はオンラインからのメタデータのダウンロードの方法を使っているのでサービスエンドポイントのurlを直接指定している。

svcutil実行結果

メタデータをダウンロードし、ファイルを生成しているようです。

C:\WCFTutorial\Client>svcutil /language:cs /out:generatedProxy.cs /config:app.config http://localhost:8000/ServiceModelSample/Service
Microsoft (R) Service Model Metadata Tool
[Microsoft(R) Windows(R) Communication Foundation、バージョン 3.0.4506.2152]
Copyright (c) Microsoft Corporation.  All rights reserved.

WS-Metadata Exchange または DISCO を使用して 'http://localhost:8000/ServiceModel
Sample/Service' からメタデータをダウンロードしようとしています。
ファイルを生成しています...
C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\WCFTuto
rial\Client\generatedProxy.cs
C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\WCFTuto
rial\Client\app.config

C:\WCFTutorial\Client>
生成ファイル

今回の生成ファイルを見る限りでは、それほど大掛かりな自動生成をしているわけではなさそう。型付けDataSetみたいのを予想してたので意外。これなら手書きでも書けそう、というか探してみると、書く手法も普通にあるみたい。

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://SuperlightBrothers.Samples", ConfigurationName="ICalculator")]
public interface ICalculator
{
    
    [System.ServiceModel.OperationContractAttribute(Action="http://SuperlightBrothers.Samples/ICalculator/Add", ReplyAction="http://SuperlightBrothers.Samples/ICalculator/AddResponse")]
    double Add(double n1, double n2);
    
    [System.ServiceModel.OperationContractAttribute(Action="http://SuperlightBrothers.Samples/ICalculator/Subtract", ReplyAction="http://SuperlightBrothers.Samples/ICalculator/SubtractResponse")]
    double Subtract(double n1, double n2);
    
    [System.ServiceModel.OperationContractAttribute(Action="http://SuperlightBrothers.Samples/ICalculator/Multiply", ReplyAction="http://SuperlightBrothers.Samples/ICalculator/MultiplyResponse")]
    double Multiply(double n1, double n2);
    
    [System.ServiceModel.OperationContractAttribute(Action="http://SuperlightBrothers.Samples/ICalculator/Divide", ReplyAction="http://SuperlightBrothers.Samples/ICalculator/DivideResponse")]
    double Divide(double n1, double n2);
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public interface ICalculatorChannel : ICalculator, System.ServiceModel.IClientChannel
{
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class CalculatorClient : System.ServiceModel.ClientBase<ICalculator>, ICalculator
{
    
    public CalculatorClient()
    {
    }
    
    public CalculatorClient(string endpointConfigurationName) : 
            base(endpointConfigurationName)
    {
    }
    
    public CalculatorClient(string endpointConfigurationName, string remoteAddress) : 
            base(endpointConfigurationName, remoteAddress)
    {
    }
    
    public CalculatorClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
            base(endpointConfigurationName, remoteAddress)
    {
    }
    
    public CalculatorClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
            base(binding, remoteAddress)
    {
    }
    
    public double Add(double n1, double n2)
    {
        return base.Channel.Add(n1, n2);
    }
    
    public double Subtract(double n1, double n2)
    {
        return base.Channel.Subtract(n1, n2);
    }
    
    public double Multiply(double n1, double n2)
    {
        return base.Channel.Multiply(n1, n2);
    }
    
    public double Divide(double n1, double n2)
    {
        return base.Channel.Divide(n1, n2);
    }
}

今回は一つしか進められませんでした0;)
続きは次回。