2017-03-09 11 views
0
の代わりにnullパラメータを受け取ります

私の仕事の一環として、XMLリクエストを受信して​​処理するSOAP 1.2ベースのWebサービスを作成します。しかし、リモートクライアントでのテストでは、わずらわしく矛盾した問題が発生しました。C#SOAPサービスメソッドは、

これは、サービスの呼び出し可能なメソッドの1の署名である:

[WebMethod] 
[ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Xml)] 
public XmlDocument PostOrders(XmlDocument request) 

ここでの問題はこれです:メソッドは、それが動作しますが、私が書いたミニマルなテストアプリケーションから呼び出されると

  • 正しく。
  • 私のクライアントのPHPベースのアプリケーションがメソッドを呼び出すと、メソッドはNULL requestを渡し、アプリケーションがその内容をファイルに書き込もうとしたときに、NullReferenceExceptionを下にスローします。 Visual StudioをIISプロセスに接続してクライアントが実際に送信した内容は問題ではありません。クライアントが実際に送信した内容が.NETレベルでどこかで失われていることが原因で、このメソッドがnull requestで呼び出されていることがわかります。

    • 独立テスト:私が試した何

    Thisでも同じ問題が発生しますが、SoapUIにコピーされた要求と同じものが正しく受信されます。上記の理由から、この問題は矛盾していると言われています.4つのアプリケーションのうち2つは、それぞれ異なるコンピュータにあり、問題を再現し、他の2つは発生しません。

  • これは、サーバーがSOAP 1.2を期待していても1.1を受け取った場合に発生する可能性があり、要求を意図的に1.1としてSoapUIに送信して再現できたようです。そこで、web.configで1.1と基本HTTPの両方を無効にしました(両方ともWSDLから消えて、1.2だけ残していることを確認しています)。サイコロはありません。
  • サービスを変更した後、メソッドのクライアント側WSDL定義が突然XmlDocumentからLinq XElementに切り替わりました。 WSDLがマルチプラットフォームとの互換性のために予想されるデータ型を抽象化することを発見したことによるサーバー側のデシリアライゼーションの問題を疑うと、メソッドのパラメータをXmlDocumentからXElementに変更しました。サイコロはありません。 web.config

内容:私は成功した任意の手動設定なしではなく、別の2から2つの別々のアプリケーションに2台の別個のコンピュータからの要求を送信することができたことを考えると

<configuration> 
    <system.web> 
    <compilation debug="true" targetFramework="4.5.2" /> 
    <httpRuntime /> 
    <webServices> 
     <protocols> 
     <remove name="HttpGet" /> 
     <remove name="HttpPost" /> 
     <remove name="HttpSoap"/>  <!-- disables SOAP 1.1 --> 
     </protocols> 
     <conformanceWarnings> 
     <remove name='BasicProfile1_1'/> 
     </conformanceWarnings> 
    </webServices> 
    <globalization uiCulture="en-US" /> 
    <customErrors mode="Off" /> 
    <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID" /> 
    <httpModules> 
     <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" /> 
    </httpModules> 
    </system.web> 
    <system.codedom> 
    <compilers> 
     <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"> 
      <providerOption name="CompilerVersion" value="v4.0" /> 
     </compiler> 
     <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" /> 
    </compilers> 
    </system.codedom> 
    <system.webServer> 
    <modules> 
     <remove name="ApplicationInsightsWebTracking" /> 
     <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" /> 
    </modules> 
    <handlers> 
     <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> 
     <remove name="OPTIONSVerbHandler" /> 
     <remove name="TRACEVerbHandler" /> 
     <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> 
    </handlers> 
    <validation validateIntegratedModeConfiguration="false" /> 
    </system.webServer> 
    <system.serviceModel> 
    <bindings /> 
    <client /> 
    </system.serviceModel> 
    <runtime> 
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <dependentAssembly> 
     <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> 
     <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" /> 
     </dependentAssembly> 
    </assemblyBinding> 
    </runtime> 
</configuration> 

、これはサーバ - ですクライアント側の問題またはクライアント側の設定ミス?

答えて

0

解決策を見つけて、他の人がこの問題に遭遇した場合に備えて転記しています。

これはサーバー側のエラーでした。あなたがメソッドのシグネチャを見れば私は上記の投稿:

public XmlDocument PostOrders(XmlDocument request) 

問題がXmlDocumentであるパラメータでした。 SOAPリクエストのペイロードはすでにXML内に格納されているため、XmlElementまたはLinq XElementとしてのみ、ペイロードのルート要素がルート要素ではないため、XmlDocumentとしてデシリアライズすることはできません。しかし、パラメータの型を変更してもうまくいきませんでした。それがWSDLを見たときです。

WSDLを生成するものが何であっても、シリアライズ可能なクラス(XmlElement/XElement)を選択しても、そのメソッドがどのような種類のデータであるかわからないためWSDLはパラメータのデータ型を宣言しませんでした。 WSDLに宣言されているデータ型がないため、クライアントサイドのアプリケーションは何を送信するかを知らなかったため、ペイロードを切り捨て、SOAPヘッダーのみを送信しました。私はなぜphpのSOAPクラスがうまくいくのかわかりませんが、明らかにそうしています。

私のテストアプリケーションも.NETであるため、送信するものを自動的に知っていました。SoapUIのリクエストはシリアル化されていない生の文字列であるため、送信する前にデータ型の必要も気にもなりません。

解決策は、パラメータタイプをstringに変更し、基本HTTPを無効にすることでした。基本的なHTTPが有効になっている間、デシリアライゼーションは、メソッドが文字列パラメータで呼び出されたときに例外を投げたので、なぜ私はこのソリューションを早く見つけられなかったのですか?

ボトムライン:.NETクライアント専用ではなく.NET Webサービスを作成する場合は、シリアル化可能かどうかに関係なく、.NETクラスを入力パラメータとして使用しないでください。文字列を使用します。あなたは頭痛の多くを救うでしょう。

関連する問題