LoginSignup
0
0

More than 5 years have passed since last update.

SoapCoreを使って同一URLでsoap1.1とsoap1.2リクエストを処理する

Last updated at Posted at 2018-04-04

始めに

ASP.NET CoreにおけるSOAPリクエスト処理ミドルウェアのSoapCoreが、0.9.7よりsoap1.2リクエストの処理が可能になった。
しかし、同一URLでsoap1.1と1.2を受ける場合、そのままでは両方解析ということはできないので、やり方を書いておく。

SoapCore自体の解説は、以前書いた記事 "ASP.NET CoreでHTTP SOAPリクエストを処理する"を参照のこと。

やり方

SoapCoreでSOAP 1.2を処理する方法

UseSoapEndPointの第二引数で、どのような通信方式を使用するか等を指定するので、以下のようにする。

// using System.ServiceModel;
// using System.ServiceModel.Channels;
// using SoapCore;

// soap1.1を使いたい場合は、第二引数にBasicHttpBindingをnewすればOK
var transportBinding = new HttpTransportBindingElement();
var textEncodingBinding = new TextMessageEncodingBindingElement(MessageVersion.Soap12WSAddressing10, Encoding.UTF8);
var customBinding = new CustomBinding(transportBinding, textEncodingBinding);
app.UseSoapEndpoint<T>("/Service.svc", customBinding, SoapSerializer.DataContractSerializer);

それぞれHttpTransportBindingが、通信プロトコルの決定、TextMessageEncodingBindingElementが、メッセージフォーマットの決定となる。そして、この二つを合わせて、CustomBindingを作る。これ自体はWCFの話になるので、詳しく知りたければWCF公式ドキュメントを参照のこと。

問題点

ここで問題は、TextMessageEncodingBindingElementが一度に一種類しか設定できないことにある。
よって、素直にUseSoapEndpointを使用した場合は、soap1.1あるいはsoap1.2のどちらかしか受け取れないということになる。

解決策

Startup内で以下のようにする。

// using Microsoft.AspNetCore.Builder;
// using System.ServiceModel;
// using System.ServiceModel.Channels;
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseWhen(ctx => ctx.Request.Headers.ContainsKey("SOAPAction"), app2 =>
    {
        app2.UseSoapEndpoint<TestService>("/Service.svc", new BasicHttpBinding(), SoapSerializer.DataContractSerializer);
    });
    app.UseWhen(ctx => !ctx.Request.Headers.ContainsKey("SOAPAction"), app2 =>
    {
        var transportBinding = new HttpTransportBindingElement();
        var textEncodingBinding = new TextMessageEncodingBindingElement(MessageVersion.Soap12WSAddressing10, System.Text.Encoding.UTF8);
        app2.UseSoapEndpoint<TestService>("/Service.svc", new CustomBinding(transportBinding, textEncodingBinding), SoapSerializer.DataContractSerializer);
    });
}

要はUseWhen(Func<HttpContext, bool>, Action<IApplicationBuilder>)を使って、分岐すれば良い、という事になる。
判定部分にどのような基準を置くかという事になるが、HTTPヘッダを用いた方法はいくつかある。
ボディはミドルウェア内部で使用するので触ることはできないことに注意。

判定方法 1.1 1.2
SOAPActionの有無
Content-Typeのmedia type text/xml application/soap+xml
Content-Typeのaction要素の有無

この辺りはクライアントの動作仕様によるところが大きいので、唯一解は無い。

参考リンクは以下

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0