プログラマーな日々

プログラマーをやっています。好きなものは、C#, TaskChute Cloud, WorkFlowy, Backlog, AWSです。

構成ファイルを使用する(クライアント編)

前回(以下のエントリー)の続きです。
構成ファイルを使用する(サービス編) - プログラマーな日々
前回作成したWCFサービスの設定を構成ファイルに外出しします。 ...

今回はクライアントを作成し、前回作成したWCFサービスにアクセスします。

準備

  1. コンソールアプリケーションのプロジェクトを作成する。
  2. System.ServiceModelへの参照を追加する。

構成ファイルとプロキシクラスの作成

サービスへの参照を追加します。

アドレスを入力して「移動」をクリックします。

...エラーになってしまいました。サービスの検索に失敗している模様です。

トラブルシュート

「詳細」をクリックしてエラーメッセージを確認。

HTML ドキュメントに Web サービス探索情報が含まれていません。
メタデータに、解決できない参照が含まれています。'http://localhost:8000/HelloWorld'
コンテンツの種類 application/soap+xml; charset=utf-8 はサービス http://localhost:8000/HelloWorld でサポートされていませんでした。クライアントとサービスのバインドが整合していない可能性があります。
リモート サーバーがエラーを返しました: (415) Cannot process the message because the content type 'application/soap+xml; charset=utf-8' was not the expected type 'text/xml; charset=utf-8'.
サービスが現在のソリューションに定義されている場合は、ソリューションの構築とサービス参照の追加を再試行してください。

どうやらメタデータに問題があるようです。

試行錯誤しているうちにこんなページが表示されました。


どうやって表示したかは忘れました...
どうやらサービス側のapp.configに足りない要素があるようです。

サービス側のapp.configの修正

上のページに従って足りない要素を追加しました。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <services>
            <service
                name="HelloWorld.StockService"
                behaviorConfiguration="myServiceBehavior">  <!-- 追加 -->
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:8000/HelloWorld" />
                    </baseAddresses>
                </host>
                <endpoint
                    address=""
                    binding="basicHttpBinding"
                    contract="HelloWorld.IStockService" />
                <!-- 追加 -->
                <endpoint
                    address="mex"
                    binding="mexHttpBinding"
                    contract="IMetadataExchange" />
            </service>
        </services>

        <!-- 追加 -->
        <behaviors>
            <serviceBehaviors>
                <behavior name="myServiceBehavior">
                    <serviceMetadata httpGetEnabled="True"/>
                </behavior>
            </serviceBehaviors>
        </behaviors>
    </system.serviceModel>
</configuration>
再度サービスの参照追加を試みます。


今度はサービスが見つかりました!

サービス参照の結果


プロキシクラスとapp.conigが自動生成されました。

クライアントのソースコード

サービスエンドポイントの三大要素(アドレス、バインディング、コントラクト)に関する記述をapp.configに移動し、プロキシクラスを使用するようにしたので、かなりすっきりしました。

using System;
using HelloWorldClient.ServiceReference;

namespace HelloWorldClient {
     class Client {
        static void Main(string[] args) {
            StockServiceClient proxy = new StockServiceClient();
            double p = proxy.GetPrice("msft");
            Console.WriteLine("Price:{0}", p);
            proxy.Close();
        }
    }
}

アプリ実行

※先にサービスを実行し、待機状態にしておきます。

やっとサービスから値を取得できました! 疲れた...