色々なものに触発されたので、WCFの超入門をしてみようと思う。
何に触発されたかは秘密です。
WCFって何?ということだけど、今まではASP.NET 2.0までのasmxのちょっと豪華版と思ってた。
もうちょっとちゃんというと下位の通信レイヤに依存しないプログラミングモデルを提供してくれるものらしい。
TCP/IPでもHTTPでも名前つきパイプでも何でも同じプログラムで動いちゃう。
そんな素敵なものがWCF。
ただし、現時点では色々出来るが故に、ちょっと難しい。
でもまぁ、Hello Worldくらいなら、asmxでWebサービス作るのと大差無い…?と思ってやってみようと思う。
とりあえず、プロジェクトの大枠を作る。
プロジェクトは、WcfHello.ServerとWcfHello.Clientという2つのコンソールアプリケーションを用意する。
双方に参照設定で、System.ServiceModelを追加する。
こいつが、WCF関連のクラスが詰まったアセンブリになる。
ここからは、プログラムをがしがし作っていく。
まず、WcfHello.ServerのProgram.csにコードを足していく。
コードを足す前に、今回作るものの最終目標を決めておく。
最終目標は、nameを渡すと、nameさんこんにちは!というサービスを作って、それを呼び出すクライアントを作るというものにしよう。
Program.csに以下のインターフェースを定義する。
public interface IGreeter
{
string SayHello(string name);
}
これがnameを受け取って nameさんこんにちは!という文字列を返すサービスの外っ面になる。
外っ面が出来たので、実装も作成する。インターフェースの定義の下に以下のような実装クラスを足す。
public class Greeter : IGreeter
{
public string SayHello(string name)
{
return name + "さんこんにちは!";
}
}
10人が書いたら9人くらい同じコードになりそうな実装だと思うので見ただけでわかると思う。
こいつに、WCFのお作法に従って属性をつけていく。
属性をつけるのは、インターフェース側になる。インターフェースにつける属性としては
- System.ServiceModel.ServiceContract
- System.ServiceModel.OperationContract
の2つになる。
前者が、サービスとして公開するインターフェースにつけて、後者が、メソッドにつける。
別に難しくないので、さくっとつけていこう。
[System.ServiceModel.ServiceContract]
public interface IGreeter
{
[System.ServiceModel.OperationContract]
string SayHello(string name);
}
これで半分準備完了。
とりあえず、こいつを公開するために、WCFのランタイムにお願いをするコードをMainに書いていく。
class Program
{
static void Main(string[] args)
{
// ServiceHostが、サービスをホストする(そのまんま)クラス。
// コンストラクタに、サービスとして公開する実装クラスの型を渡す。
using (var host = new System.ServiceModel.ServiceHost(typeof(Greeter)))
{
// Openでサービス起動
host.Open();
// Enterが押されるまで待つ
Console.WriteLine("WCFサービス起動したよ");
Console.ReadLine();
// 最後にきちんと閉じる
host.Close();
}
}
}
WCFのサービスとして公開するためのメソッドも凄く簡単に書ける。
コメントのほうが多いくらいだ。
ただし、悲しいことにこれを実行すると例外が出てしまう。
色々エラーメッセージで言われているが、要は構成ファイルがないよ?ということになる。
WCFのサービスは、このサービスを公開するためのアドレスと、どういうプロトコルを使うかと、どのインターフェースで公開するかという3つの情報を定義しないといけない。
.NETで定義といったらapp.config。
このWCFの構成を書くためのツールが、Visual Studioとは統合されてないけどWindows SDKの中に入っています。
とはいっても、Visual Studioから起動したいので、以下の手順でVisual Studioから起動できるようにします。
App.configを新規作成したら、右クリックしてファイルを開くアプリケーションの選択をクリックします。
色々出てきますが、追加をクリックします。
プログラム名に「C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SvcConfigEditor.exe」を入力して、表示名を適当にしてOKを押します。
そうすると、一覧に追加されます。
SvcConfigEditor.exeを選択した状態で開くと、以下のような便利な構成ファイルのエディタが開きます。
今回は、サービスを使うので、サービスの作成リンクをクリックします。
サービス型を選択します。ここで、選択するのはサービスの実装クラスになります。
参照ボタンを押してExeを読み込むと、自動で一覧に出してくれるので、そこから選択します。
次に、サービスコントラクトを設定します。これは、サービスのインターフェースを指定します。
次に、サービスで使用する通信モード(プロトコル?)を選択します。ここでは最初から入力されてるHTTPを選択します。
これで、普通のSOAP over HTTPでのサービスと、大体同じになるはず。
使用する相互運用もデフォルトのまま次へ。
次にアドレスを設定します。サービスの呼び出し時に指定したりします。
ここでは、http://localhost:8080/WcfHello.Server/Greeterを指定してます。
以上のウィザードを完了させると、なんとかサービスとして形が整ってきました。
この時点でも、一応サービスとしては起動します。
ただし!!注意点としては、Vistaを使ってる場合に、Visual Studio 2008を管理者権限で動かしてないとサービスの登録処理で権限が無いと例外が出てしまいます。
その部分にだけ気をつけて実行すると、以下のようにコンソールに味気ない文字列が表示されます。
ただ、これだと本当に必要最低限の機能しかありません。一応SOAP over HTTPの呼び出しに応じることは出来るけど、本当にそれしか出来ない。
例えば、WCFのクライアントを作るためのWSDLも提供されてない状態です。
WCFのサービスにWSDLの公開などといった付加的な機能を追加するのが、サービス動作(ServiceBehavior)です。
直訳の弊害がかもしれませんが、付加的な機能を追加するものと覚えておけば良さそう。
ServiceBehaviorを追加するには、App.configの編集ツールで 詳細設定/サービス動作という部分で右クリックして「新しいサービス動作の構成」を新規作成をします。
新規作成をしたら、NewBehaviorが作られます。こいつに追加する機能を定義していきます。
serviceMetadataというものがWSDLを公開するための機能なので、追加ボタンを押してserviceMetadataを追加します。
そうすると、画面左側のツリーにserviceMetadataが追加されるので、それを選択します。
そうすると、serviceMetadataのプロパティが下のように表示されます。
プロパティの中から、HttpGetEnabledをTrueに、HttpGetUrlを、http://localhost:8080/WcfHello.Server/Greeter/mexに指定します。
因みに、mexというのはMetadata Exchangeというものの略みたいです。
以上でBehaviorの設定が終わったので、サービスとの関連付けをやります。WcfHello.Server.Greeterを選択して、BehaviorConfigurationの値をNewBehaviorにします。
以上で、サービス側の設定は完了です。
Serverを起動してブラウザで、http://localhost:8080/WcfHello.Server/Greeter/mexにアクセスすると以下のような画面が表示されます。WSDLがきちんと表示されています。
次に、クライアント側を作っていきます。
クライアント側は、WCFのクライアントを作って呼び出しを行うだけなので非常に簡単です。
ということで、やってみます。
WcfHello.Clientプロジェクトを右クリックして、サービス参照の追加を選択します。
サーバーは起動した状態のまま、サービス参照の追加のダイアログに「http://localhost:8080/WcfHello.Server/Greeter/mex」を入力します。
URLを入力した後に移動ボタンを押下すると、下の画面のようにサービスが検出されるのでOKを押してサービス参照を追加します。
以上の作業でWCFのクライアントのProxyが作成されます。
Proxyは、サービス名Clientという名前のクラスで作られています。使い方は、Proxyのインスタンスをnewで作り、普通にメソッドを呼び出すだけです。
最後にCloseを呼ぶのを忘れなければ完璧です。
今回のGreeterというサービスのSayHelloを呼び出す処理は以下のようなコードになります。
WcfHello.ClientのProgram.cs
using System;
namespace WcfHello.Client
{
class Program
{
static void Main(string[] args)
{
// Proxyクラスを作成して
var proxy = new ServiceReference1.GreeterClient();
// SayHelloの呼び出し
var message = proxy.SayHello("かずき");
// 最後にCloseで閉じて
proxy.Close();
// メッセージ出力
Console.WriteLine(message);
}
}
}
サーバーを起動した状態で、WcfHello.ClientをスタートアッププロジェクトにしてCtrl + F5で起動させると、下のような実行結果になります。
うん。ちゃんとサービスが呼び出せている。
満足満足。
最後に、このBlogでWCFに少しでも興味が沸いた人は、マイクロソフトの赤間さんのBlogに濃い内容が書いてあるのでそちらを見てみると、凄くいいと思います!
というか、ここに書いたことは、下に書いてあることの超はしょった版です。
http://blogs.msdn.com/nakama/archive/2008/09/18/part-1-wcf.aspx
http://blogs.msdn.com/nakama/archive/2008/09/25/part-2-hello-world-wcf.aspx
http://blogs.msdn.com/nakama/archive/2008/10/02/part-3-hello-world-wcf.aspx