始めに
SOAPとは、簡単に言うとXMLベースのRPCプロトコルフォーマットの事である。
SOAP自体はもっと大きい枠組みであるWeb services protocol stackの一部らしいが、単体でも利用可能なものになっている。
本来ならば、様々な通信に乗せて使用することもできるらしいが、現在の所主に使用されているのはHTTP上である。
(主に、とは書いてあるが、現在のところ各所でほぼレガシー扱いされていると思うので今後増えるかどうかは不明)
以後、特に断りが無い限り、HTTP上で利用されるSOAP通信の事を書く。
.NET Frameworkあるいはmonoでの利用
.NET Frameworkは、サーバー、クライアント双方のライブラリが用意されている。monoでも、ドキュメントを見る限り、基本的な部分は使用する分には問題なく使えそう(WCFは未検証、ASMXは機能的にはほぼ使える)
- monoのWCFについて: http://www.mono-project.com/docs/web/wcf/
サーバー側
C#でSOAPリクエストのサービスを提供する場合、ASP.NET XML Web Service(ASMX)を使用するか、WCFを使用することになる。どちらかというと、ASMXの方が古い。
クライアント側
クライアントの場合は、WCFのクライアントライブラリを使用するか、WSDL.exeコマンドでクライアントを生成することで、SOAP通信を利用することができる。
どちらもWindows SDKに入っているはず。
何が問題か
上で記述したのは.NET Frameworkの話である。では、.NET Coreはどうなのか、というと、クライアントは問題ない。
厳密に検証したわけではないが、WCFのnugetパッケージを利用すれば、クライアント部分はほぼ問題なく使える模様。
しかし、サーバー部分の提供は無い。SOAP自体がほぼレガシーになっている現在、ASP.NET Coreの方で正式サポートしないのは仕方ない話である。しようと思うとどうしても重厚長大になるだろうし。
では現状維持のままでいいかというと、ASP.NET Coreには既存のASP.NETにはない新機能や、パフォーマンスアップ等が推し進められており、サーバーサイドとしてはどうしても移行したい。
全体は新しいやり方に移行するにしても、古いクライアントを対象に互換レイヤーを提供しなければならない場合もあるので、どうしてもここが移行の障害となる。
解決策
元々SOAP自体は単なるプロトコルなので、そのアクセスを受け付けるようにすればいいという話となる。
そして、正式サポートされていないならば、自分で作るか、あるいはサードパーティーのライブラリを使えば良い。
ということで紹介するのが SoapCoreである。
サービス実装方法
一から作る場合
asp.net coreプロジェクト自体の用意は ASP.NET Coreのドキュメントを参考にして、予め構築しているものとする。
-
System.ServiceModel.ServiceContractAttribute
を追加したインターフェイスを作成する - メソッドに
System.ServiceModel.OperationContractAttribute
を追加する- refやoutも使用可能
- インターフェイスの実装クラスを作成する
- StartupクラスのConfigureServicesで、実装クラスを
TryAddSingleton
で追加する - StartupクラスのConfigureで、
UseSoapEndpoint
で、エントリポイントを追加する- サンプルでは拡張子を変えているが、特にその辺りは好きに設定しても問題ない
- 3番目の引数に関して、WCFクライアントからの接続の場合は
DataContractSerializer
で問題ないが、他のクライアントからアクセスする場合は、要素が前後する可能性を考慮して、XmlSerializer
を使用した方が良い
WCFからの移行
定義等はほとんどそのままで移行可能。async Taskメソッドも使える。ただし、IAsyncResultを利用した非同期メソッドは使えない。基本的にWCFの機能はほとんど移行されていないため、どちらにしろ検証は必要。
ASMXからの移行
ASMXから移行する場合は少々面倒な手順が必要。まず、System.Web
に大きく依存しているため、WCFのように定義をそのまま移行というわけにはいかない。
メソッドの定義等は、WSDLからsvcutil.exe
でスケルトンを作ることは可能。(Windows SDKに入っている)
また、WSDL.exeからサーバーインターフェイスコードを生成し、そこから属性の付け替えを行うという手もある。
既にインターフェイスとして分離しているならば、そこから属性の付け替えでも移行が可能。(WebServiceBindingAttribute
からServiceContractAttribute
、SoapDocuemntMethodAttribute
とWebMethodAttribute
からOperationContractAttribute
)
なお、HttpContextは使えないので、実装クラスでは注意すること。
注意点
XML名前空間について
SOAPではXML名前空間を使用しているので、ここはクライアントとサーバー間で合わせる必要がある。具体的には ServiceContractAttribute
のNamespace
と、また、OperationContractAttribute
のNamespace
がそれになる。
SOAPバージョンについて
現在使われているSOAPは1.1と1.2の2系統がある。1.1は問題なく処理可能だが、SoapCoreの0.9.6では、まだSOAP1.2メッセージは処理できないので注意。masterには修正がマージされているので、次のバージョンでは処理できるようになるかもしれない。
0.9.7よりパースできるようになりました。
SOAPバージョンについての参考URL: https://www.ibm.com/support/knowledgecenter/ja/SSAW57_8.5.5/com.ibm.websphere.nd.doc/ae/cwbs_soapverdiffs.html
終りに
SOAPリクエストを処理できるようになるというだけなので、WCFやASMXのコードがそのまま移行できるわけではないということに注意。あくまでも移行のための互換レイヤーとみて、過度な期待はしない方がいい。フォーマットにXMLを使用している以上、grpc等に処理速度では勝てないだろうし。
非機能面は厳密には計測していない。中身を見ると、リクエストの振り分け時にリフレクションを使用しているので、もしかしたら劣る可能性もなくはない。この辺りの計測は今後の宿題となりそう。