WCF ~ メタデータのエクスポートとプロキシコードの生成

これまで WCF を用いて SOAP メッセージの受け渡しができることを見てきました。 しかし、そのインターフェイス定義が何らかの形で外部に公開され、それがクライアントから利用可能になって初めて、 オープンなプロトコルで通信している意味が深まるというものです。

WCF では WS-Metadata Exchange にて記述された方法でインターフェイス定義を公開します。Web サービスの定義 (型、メソッド等の定義) やエンドポイント (接続可能なデータポートとプロトコル等) を含め、それをメタデータといいます。

メタデータの公開

デフォルトでは、メタデータは外部に公開されません。メタデータを公開するには、以下のように ServiceMetadataBehavior や MetadataExchangeBindings を利用します。詳しくは MSDN をご覧ください。 ここでは実装例を示します。

HelloWCFReceiverApp.cs を以下のように書き換えます。

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;


sealed class HelloWCFReceiverApp {

     static void Main() {

          ServiceHost svc = new ServiceHost( typeof(HelloWCF) );

          // 基本のサービス

          Uri address = new Uri ( "http://localhost:4000/IHelloWCF" );
          BasicHttpBinding binding = new BasicHttpBinding();

          svc.AddServiceEndpoint( typeof(IHelloWCF), binding, address );


          // メタデータの公開

          ServiceMetadataBehavior md = new ServiceMetadataBehavior();

          svc.Description.Behaviors.Add(md);
          Binding meb = MetadataExchangeBindings.CreateMexTcpBinding();
          Uri mebaddr = new Uri ( "net.tcp://localhost:4001/IHelloWCF/Mex" );
          
          svc.AddServiceEndpoint( typeof(IMetadataExchange), meb, mebaddr );


          svc.Open();

          Console.WriteLine ( "HelloWCFReceiverApp: Wainting for messages..." );

          Console.ReadLine();

          svc.Close();

     }

}

ビルド方法等は以前と同様です。

プロキシコードの生成

プロキシコードは、svcutil コマンドで生成できます。

/out オプションに出力するファイル名を指定します。/target オプションについては、 プロキシコードを生成する場合は code を指定します。

> svcutil /out:HelloWCFProxy.cs /target:code 
net.tcp://localhost:4001/IHelloWCF/Mex
Microsoft (R) Service Model Metadata Tool
[Microsoft (R) Windows (R) Communication Foundation, Version 3.0.4506.648]
Copyright (c) Microsoft Corporation.  All rights reserved.

Attempting to download metadata from 
'net.tcp://localhost:4001/IHelloWCF/Mex' using WS-Metadata Exchange. 
This URL does not support DISCO.

Generating files...
C:\tmp\HelloWCFProxy.cs
C:\tmp\output.config

>

上記で、HelloWCFProxy.cs と output.config が生成されました。

一応、上で生成されたソースを確認します。HelloWCFProxy.cs です。

//------------------------------------------------------------------------------
// 
//     This code was generated by a tool.
//     Runtime Version:2.0.50727.3053
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// 
//------------------------------------------------------------------------------



[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="IHelloWCF")]
public interface IHelloWCF
{
     
     [System.ServiceModel.OperationContractAttribute(
	Action="http://tempuri.org/IHelloWCF/Say", 
	ReplyAction="http://tempuri.org/IHelloWCF/SayResponse")]
     void Say(string input);
}

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

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class HelloWCFClient : System.ServiceModel.ClientBase<IHelloWCF>, IHelloWCF
{
     
     public HelloWCFClient()
     {
     }
     
     public HelloWCFClient(string endpointConfigurationName) : 
             base(endpointConfigurationName)
     {
     }
     
     public HelloWCFClient(
	string endpointConfigurationName, 
	string remoteAddress) : 
             base(endpointConfigurationName, remoteAddress)
     {
     }
     
     public HelloWCFClient(
	string endpointConfigurationName, 
	System.ServiceModel.EndpointAddress remoteAddress) : 
             base(endpointConfigurationName, remoteAddress)
     {
     }
     
     public HelloWCFClient(
	System.ServiceModel.Channels.Binding binding, 
	System.ServiceModel.EndpointAddress remoteAddress) : 
             base(binding, remoteAddress)
     {
     }
     
     public void Say(string input)
     {
         base.Channel.Say(input);
     }
}

output.config は次の通り。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding 
			name="BasicHttpBinding_IHelloWCF" 
			closeTimeout="00:01:00"
			openTimeout="00:01:00" 
			receiveTimeout="00:10:00" 
			sendTimeout="00:01:00"
			allowCookies="false" 
			bypassProxyOnLocal="false" 
			hostNameComparisonMode="StrongWildcard"
			maxBufferSize="65536" 
			maxBufferPoolSize="524288" 
			maxReceivedMessageSize="65536"
			messageEncoding="Text" 
			textEncoding="utf-8" 
			transferMode="Buffered"
			useDefaultWebProxy="true">
                    <readerQuotas 
			maxDepth="32" 
			maxStringContentLength="8192" 
			maxArrayLength="16384"
                        maxBytesPerRead="4096" 
                        maxNameTableCharCount="16384" />
                    <security 
			mode="None">
                        <transport 
    			clientCredentialType="None" 
    			proxyCredentialType="None"
        			realm="" />
                        <message 
    			clientCredentialType="UserName" 
			algorithmSuite="Default" />
                    </security>
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:4000/IHelloWCF" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_IHelloWCF" contract="IHelloWCF"
                name="BasicHttpBinding_IHelloWCF" />
        </client>
    </system.serviceModel>
</configuration>

クライアントプログラムのリビルド

そこで、このプロキシコードと送信プログラムのソースから、新しく送信プログラムをビルドします。

 
> csc /out:SenderApp.exe HelloWCFProxy.cs HelloWCFSenderApp.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.

>

そこで送信プログラムを実行します。問題なくメッセージが送受信できました。

> SenderApp.exe

>

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Web/DB プログラミング徹底解説