はじめに
ウェブアプリのクライアントとサーバの通信で主に使われる REST API は、「SOAP や RPC などを必要としない、簡易なウェブ上のインターフェイス」だと説明されることがあります。自分が関わっている業務システムのプログラムで、クライアントとサーバの通信に「SOAP を使っている」と聞いているものがあります。SOAP とは何か調べておきたいと思います。
SOAP とは
「SOAP (Simple Object Access Protocol) 」は、ネットワーク上でウェブサービスやサーバ・クライアントが連携するためのプロトコル(通信規約)の一つ。メッセージ記述は XML 、データ伝送に主に HTTP を用いる。XML-RPC から発展した。1999 年に Microsoft 社が仕様を発表した。
SOAPとは - IT用語辞典 e-Words
「XML-RPC」は、RPC の仕様の一つ。
XML-RPCとは - IT用語辞典 e-Words
「RPC (Remote Procedure Call) 」は、ネットワーク越に別のコンピュータ上にあるプログラム(手続)を実行する技術です。
RPC(リモートプロシージャコール)とは - IT用語辞典 e-Words
.NET アプリで SOAP を利用する
SOAP で通信するアプリを作ってみましょう。.NET で実装してみます。
.NET で SOAP サーバプログラムを実装する
まずサーバプログラムを用意しましょう。
C#でWebサービス(SOAP)を開発してIISへ公開する #ASP.NET - Qiita
IIS で稼動する ASP.NET アプリとして実装します。
①Visual Studio で「ASP.NET ウェブアプリケーション」を新規作成する
プロジェクト ServiceApp にします。
②プロジェクトに「ウェブサービス(ASMX)」を新規作成する
モジュール名を Hello.asmx にしました。
③メソッドを用意する
メソッド HelloWorld() を実装します。[WebMethod] 属性をつけます。
namespace ServiceApp
{
(中略)
public class Hello : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return "Hello, SOAP.";
}
}
}
④ビルドして IIS で公開する
IISへデプロイする方法について(ASP.NET) #VisualStudio - Qiita
例えば「フォルダに発行」すると以下のファイルが作成されます。
ServiceApp
Web.config
Hello.asmx
bin
ServerApp.dll
これを IIS にデプロイします。
ウェブブラウザでアクセスしてみます。
http://(サーバのアドレス)/Hello.asmx
WSDL を確認してみます。
http://(サーバのアドレス)/Hello.asmx?wsdl
「WSDL (Web services Description Language) 」は、XLM の記法で、ウェブサービスが持つ機能や、外部から利用するためのメッセージの形式や、通信手段などを記述できる。
WSDLとは - IT用語辞典 e-Words
.NET で SOAP クライアントプログラムを実装する
続いてクライアントプログラムを用意しましょう。
ASP.NETでWebサービスを作成する (後編) - 滴了庵日録
例えば .NET Framework の Windows デスクトップアプリにしましょう。
①Visual Studio でプロジェクトを新規作成する
プロジェクト ClientApp にします。
②「サービス参照の追加」する
ウェブサービスの URL を指定します。
http://(サーバのアドレス)/Hello.asmx
名前空間 Hello にしました。
サーバのメソッドをローカルのメソッドのように呼べるプロキシクラスが自動作成されます。
namespace ClientApp.Hello {
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="Hello.HelloSoap")]
public interface HelloSoap {
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/HelloWorld", ReplyAction="*")]
WinForms.Hello.HelloWorldResponse HelloWorld(WinForms.Hello.HelloWorldRequest request);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/HelloWorld", ReplyAction="*")]
System.Threading.Tasks.Task<WinForms.Hello.HelloWorldResponse> HelloWorldAsync(WinForms.Hello.HelloWorldRequest request);
}
(後略)
③ウェブサービスのメソッドを呼出するコードを追加する
using WinForms.Hello;
using System.ServiceModel;
(中略)
namespace ClientApp
{
public partial class Form1 : Form
{
(中略)
private void button1_Click(object sender, EventArgs e)
{
var client = new HelloSoapClient();
try
{
var result = client.HelloWorld();
textBox1.Text = result;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
client.Close();
}
}
④アプリをビルドする
接続先を指定する①
接続先はどう指定されるでしょうか。「サービス参照の追加」したとき App.config に設定が記録されます。
(前略)
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="HelloSoap" />
</basicHttpBinding>
</bindings>
<client>
<endpoint binding="basicHttpBinding"
bindingConfiguration="HelloSoap" contract="Hello.HelloSoap"
address="http://(サーバのアドレス)/Hello.asmx"
name="HelloSoap" />
</client>
</system.serviceModel>
(後略)
ビルドすると以下のファイルが作成されます。
ClientApp.exe
ClientApp.exe.config
参考 Settings.settings ファイルと App.config ファイルの違い|ことりと
ClientApp.exe.config ファイルなしで ClientApp.exe を実行すると、接続先が不明でエラー発生します。
ClientApp.exe.config ファイルの内容を修正した上で ClientApp.exe を実行し直すと、接続先が変更されます。
接続先を指定する②
あるいは、以下のようにコードで直接指定できます。
(前略)
private void button2_Click(object sender, EventArgs e)
{
var binding = new BasicHttpBinding();
var endpoint = new EndpointAddress("http://(サーバのアドレス)/Hello.asmx");
var client = new HelloSoapClient(binding, endpoint);
try
{
var result = client.HelloWorld();
(後略)
こうすると App.config の設定や ClientApp.exe.config ファイルは必要なくなります。
JavaScript プログラムで SOAP を利用する
SOAP は Microsoft や .NET に限定された技術ではないと書かれています。
JavaScript でも実装できるようです。試してみます。
JavaScript で SOAP サーバプログラムを実装する
JavaScript で SOAP サーバプログラムを書いてみましょう。Node.js で実装します。
node-soap ライブラリを使います。
GitHub - vpulim/node-soap: A SOAP client and server for node.js. · GitHub
コードを用意します。
const soap = require('soap');
const express = require('express');
const fs = require('fs');
const service = {
Hello: {
HelloSoap: {
HelloWorld: function() {
return {
HelloWorldResult: "Hello, SOAP."
};
}
}
}
};
const xml = fs.readFileSync("service.wsdl", 'utf8');
const app = express();
app.listen(80, function() {
soap.listen(app, "/Hello.asmx", service, xml, function() {
console.log('SOAP server is running.');
});
});
上記のコードで読込する service.wsdl を用意します。
<wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://tempuri.org/">
<wsdl:types>
<xs:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
<xs:element name="HelloWorld">
<xs:complexType />
</xs:element>
<xs:element name="HelloWorldResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="HelloWorldResult" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="HelloWorldSoapIn">
<wsdl:part name="parameters" element="tns:HelloWorld" />
</wsdl:message>
<wsdl:message name="HelloWorldSoapOut">
<wsdl:part name="parameters" element="tns:HelloWorldResponse" />
</wsdl:message>
<wsdl:portType name="HelloSoap">
<wsdl:operation name="HelloWorld">
<wsdl:input message="tns:HelloWorldSoapIn" />
<wsdl:output message="tns:HelloWorldSoapOut" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloSoap" type="tns:HelloSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="HelloWorld">
<soap:operation soapAction="http://tempuri.org/HelloWorld" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="Hello">
<wsdl:port name="HelloSoap" binding="tns:HelloSoap">
<soap:address location="http://localhost:8000/Hello.asmx" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
上記の内容は、ASP.NET アプリでは .NET ライブラリが生成してくれるものです。node-soap ライブラリはそこまでしてくれないので、XML の内容を予め用意してライブラリに渡します。↑
サーバを起動します。
$ node main.js
クライアントプログラムから接続します。.NET で作成したアプリから接続できます。
JavaScript で SOAP クライアントプログラムを実装する
JavaScript で SOAP クライアントプログラムを書いてみましょう。ブラウザの JavaScript で実装します。
browser-soap ライブラリを使います。
GitHub - johniak/browser-soap: soap client in pure javascript, runs in browser · GitHub
(前略)
<script src="https://cdn.jsdelivr.net/npm/browser-soap/browser-soap-min.js"></script>
(中略)
<button id="get">取得</button>
<div id="result"></div>
document.querySelector('#get').addEventListener('click', () => {
window['browser-soap'].createClient("/Hello.asmx?wsdl", (err, client) => {
if (err) {
console.log("createClient failed: ", err);
return;
}
client.HelloWorld({}, (err, result) => {
if (err) {
console.log("function call failed: ", err);
return;
}
document.querySelector('#result').textContent = JSON.stringify(result);
});
});
});
client.html および client.js は、サーバプログラムと同じウェブサーバで公開します。
この JavaScript プログラムは、ASP.NET と Node.js のどちらの SOAP サーバにも接続できます。