2010年10月23日土曜日

ServiceReferences.ClientConfigの配布

ServiceReferences.ClientConfigはxapファイルに格納されるので、
VisualStudioでのデバッグ環境と、配布する環境とでは記述を変える必要がある。

具体的には、
WCFクライアント設定のエンドポイントのアドレスを変えなければいけないのだが、、、
いちいちVisualStudioでサービス参照を書き換えるのは非常に面倒。

対策は簡単で、
ServiceReferences.ClientConfigを書き換えてビルドし直すだけで、
xapファイルに変更が反映される。

なので、以下のようにそれぞれの環境の設定をコメントアウトして残しておくと楽。

<client>
  <!--
  <endpoint address="http://localhost:1335/HogeService.svc" binding="customBinding" bindingConfiguration="CustomBinding_HogeService"
 contract="HogeService.HogeService" name="CustomBinding_HogeService" />
  -->
  <endpoint address="http://hoge.local/HogeService/HogeService.svc" binding="customBinding"
 bindingConfiguration="CustomBinding_HogeService" contract="HogeService.HogeService" name="CustomBinding_HogeService" />
</client>

2010年9月17日金曜日

ClientAccessPolicy.xmlの書式

WCFはクロスドメイン間での実行に制限をかけられるので、
不特定ドメインからの実行は許可すべきではない。

以下は、ドメインhoge.localとVisualStudioでのデバッグ用にlocalhostのみ許可する設定。

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="*">
        <domain uri="http://hoge.local" />
        <domain uri="http://localhost:1335" />
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true" />
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

2010年9月16日木曜日

TimeoutExceptionの回避

処理に時間のかかるWCFサービスを呼び出すと、TimeoutExceptionが返ってくる。

これはデフォルトでWCFサービスが1分間処理を返してこないと、タイムアウトするようになっているから。

これを回避するにはクライアント側の設定ファイルServiceReferences.ClientConfigのsendTimeoutの値を変更。以下の例では10分に設定。

<binding name="CustomBinding_Service" sendTimeout="00:10:00">
  <binarymessageencoding />
  <httptransport maxReceivedMessageSize="10485760" maxBufferSize="10485760" />
</binding>

DataContractの初期化

WCFでDataContractとして定義したクラスのメンバを初期化したい、ってことはよくあるけど、以下のようにコンストラクタを追加してみたってどうにもなりません。

[DataContract]
    public class Shop
    {
        [DataMember]
        public short ID { get; set; }
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public string Address { get; set; }
        [DataMember]
        public string Phone { get; set; }
        [DataMember]
        public string Fax { get; set; }
        [DataMember]
        public List<Employee> Employee { get; set; }

        public Shop()
        {
            Employee = new List<Employee>();
        }
    }

WCFでシリアライズされている型をいじるには、クライアント側でパーシャルクラスを定義すればよいだけ。

同じShopクラスならこんな具合。(WCFのコレクション型をObservableCollectionにシリアライズした場合)

public partial class Shop : IEditableObject
    {
        public Shop
        {
            Employee = new ObservableCollection<Employee>();
        }
    }

パーシャルクラスを使えば、IEditableObjectとかの実装もできるようになる。