jQuery ajaxでSOAP1.1する

# jQuery ajaxでSOAP1.1する
仕事で利用する機会があったので備忘録的なメモ。
RESTの時代である今、SOAP通信って…という所はありますが、
実際に需要があったのでメモしておきます。

## 1.目的
ASP.NETサーバと__jQuery ajax__でSOAP通信する。

## 2.環境
* ASP.NET Server（Visual Studio 2015で作成）
* JavaScript(ECMAScript 5)
* jQuery(jquery-2.2.3)

## 3.手順

### 3.1.ASP.NET側の準備
WSDLファイルを確認する
SOAPサーバとajax通信を通信をするためには
__Webサービス全体のWSDLファイル__と、__利用するサービス（メソッド）のWSDLファイル__
上記２つが必須となります。WSDLファイルはそれぞれ

    http://xx.xx.xx.xx/Webサービス名.asmx?WSDL（Webサービス全体）
    http://xx.xx.xx.xx/Webサービス名.asmx?op=メソッド名(利用するメソッド)

にWebサービス作成時に自動生成されています。

WSDLファイルは、WEBサービスを外部から利用するためのインターフェース定義であり
・そのWebサービスはどこにあるのか
・そのWebサービスは、どんなフォーマットのメッセージを使って利用するのか
・そのWebサービスは、どんな通信プロトコルを使ってメッセージをやり取りするのか
といったことが書かれています。

WSDLファイルが生成されていることを確認したら、
生成されたWSDLファイルに合わせたXmlStringをJavaScript側で作成します

### 3.2.SOAP通信用XMLデータの作成
作成するXMLの形式は、SOAPサーバ側のWSDLで指定されているので、
それと全く同じ文字列をjavaScript側で生成していきます。

    http://xx.xx.xx.xx/Webサービス名.asmx?op=メソッド名(利用するメソッド)

上記URLに利用形式が指定されているので、それに合わせて書いていきます。
今回は__SOAP1.1__を利用しました。

~~~xml
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetTestData xmlns="http://tempuri.org/">
      <User>string</User>
    </GetTestData>
  </soap:Body>
</soap:Envelope>
~~~

このxmlには、「GetTestData」というサービスに「User」という引数を渡して起動する
という指示が書いてあり、これをHTTPのヘッダに埋めて送信することで、指定したサービスを
サーバ側で起動することが出来ます。

~~~js
/**
 * xml文字列を生成する
 */
createXmlString: function (user) {
    //soap通信用文字列を作成
    var sr = '<?xml version="1.0" encoding="utf-8"?>' +
        '<soap:Envelope ' +
        'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
        'xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' +
        'xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' +
        '<soap:Body>' +
        '<GetTestData xmlns="http://tempuri.org/">' +
        '<User>' + user + '</User>' +
        '</GetTestData>' +
        '</soap:Body>' +
        '</soap:Envelope>';
    //文字列を返却
    return sr;
}
~~~

こんな感じでさらさらっとjs側で作ってあげればOKでしょう。
あとはこれを材料にajax通信してあげます。

### 3.3.ajaxを利用してSOAP通信する
後は、作成したxmlStringをヘッダに埋め込んでajax通信すれば完了です。

~~~js
/**
 * ajaxでsoap通信する
 */
connect: function (service, xmlString) {
    var result = $.ajax({
        //POST通信
        type: 'POST',
        //URL指定
        url: 'http://xx.xx.xx.xx/TestWebService.asmx',
        //header付与
        headers: {
            //SOAP通信を実行するメソッドを指定
            'SOAPAction': 'http://tempuri.org/GetTestData',
            //タイプをxmlに指定する
            'Content-Type': 'text/xml',
        },
        //SOAPリクエスト用xmlを添付
        data: xmlString,
        //同期処理の有無
        async: false,
        //エラー時表示
        error: function (xhr, status, error) {
            window.alert(error);
        },
        //タイムアウト時間
        timeout: 10000
    }).responseText;
    //結果を返却
    return result;
}
~~~

resultには通信した結果の__xml__が入っているので、それをパースするなり、
文字列として切り出しするなりごにょごにょするなりして利用してください。

今回の業務では__async:false__を利用しましたが、
非同期通信でやりたい人はtrueにしてもいいんじゃないでしょうか。

## 今回作成したソース

~~~js:xmlTest.js
/**
 * ajax soap通信を行う
 */
var connector = {
    /**
     * xml文字列を生成する
     */
    createXmlString: function (user) {
        //soap通信用文字列を作成
        var sr = '<?xml version="1.0" encoding="utf-8"?>' +
            '<soap:Envelope ' +
            'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
            'xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' +
            'xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' +
            '<soap:Body>' +
            '<GetTestData xmlns="http://tempuri.org/">' +
            '<User>' + user + '</User>' +
            '</GetTestData>' +
            '</soap:Body>' +
            '</soap:Envelope>';
        //文字列を返却
        return sr;
    },
    /**
     * ajaxでsoap通信する
     */
    connect: function (service, xmlString) {
        var result = $.ajax({
            //POST通信
            type: 'POST',
            //URL指定
            url: 'http://xx.xx.xx.xx/TestWebService.asmx',
            //header付与
            headers: {
                //SOAP通信を実行するメソッドを指定
                'SOAPAction': 'http://tempuri.org/GetTestData',
                //タイプをxmlに指定する
                'Content-Type': 'text/xml',
            },
            //SOAPリクエスト用xmlを添付
            data: xmlString,
            //同期処理の有無
            async: false,
            //エラー時表示
            error: function (xhr, status, error) {
                window.alert(error);
            },
            //タイムアウト時間
            timeout: 10000
        }).responseText;
        //結果を返却
        return result;
    }
}
~~~

## 感想
* jQuery ajaxは非同期処理だけではなく、データ取得用の同期処理としても利用できる。
  SPA(Single Page Application)が主流になってきている時代に、ページリフレッシュをせず
  クライアントからサーバへデータの取得要求を送れるのはやはり便利。

* 設計当初はxmlHttpRequestを利用して通信していたが、やはりjQuery ajaxの方が
  通信箇所の切り分けなど様々な面で優れており、利用しやすかった。

* Visual Studio Code書きやすくてステキ。かっこいい。

## 参考
WSDLについて
<http://j-caw.co.jp/blog/?p=1477>

ASP.NETのWebサービスについて
<http://www.sangyo-rock.com/tech/index.php?ASP.NET%A4%C7%A4%CEWeb%A5%B5%A1%BC%A5%D3%A5%B9%B3%AB%C8%AF%A4%CB%B4%D8%A4%B9%A4%EB%A5%E1%A5%E2>