C#SOAP服务方法接收空参数,而不是

C#SOAP服务方法接收空参数,而不是,c#,soap,wsdl,nullreferenceexception,C#,Soap,Wsdl,Nullreferenceexception,作为我工作的一部分,我将编写一个基于SOAP1.2的Web服务来接收和处理XML请求。然而,在使用远程客户端进行测试期间,我遇到了一个相当令人困惑且不一致的问题 这是服务的一个可调用方法的签名: [WebMethod] [ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Xml)] public XmlDocument PostOrders(XmlDocument request) 这里的问题是: 当从我编写的极

作为我工作的一部分,我将编写一个基于SOAP1.2的Web服务来接收和处理XML请求。然而,在使用远程客户端进行测试期间,我遇到了一个相当令人困惑且不一致的问题

这是服务的一个可调用方法的签名:

[WebMethod]
[ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Xml)]
public XmlDocument PostOrders(XmlDocument request)
这里的问题是:

  • 当从我编写的极简测试应用程序调用该方法时,它工作正常
  • 当我的客户机基于php的应用程序调用该方法时,该方法会被传递一个null
    请求
    ,并在应用程序尝试将其内容写入文件时相应地抛出一个
    NullReferenceException
    。客户端实际发送的内容无关紧要,将Visual Studio附加到IIS进程会显示该方法是通过null
    请求调用的,而客户端实际发送的内容在.NET级别的某个地方丢失了
我尝试的是:

  • 独立测试。产生相同的问题-但是正确接收粘贴到SoapUI中的相同请求。这就是为什么我在上面提到这个问题是不一致的:四分之二的应用程序,每一个都在不同的计算机上,复制了这个问题,另外两个没有
  • 显然,如果服务器期望SOAP1.2,但收到1.1,并且我能够通过在SoapUI中有意地将请求发布为1.1来复制它,则可能会发生这种情况。因此,我在
    web.config
    中禁用了1.1和基本HTTP(验证两者是否都从WSDL中消失,只剩下1.2),并让客户端显式地定义版本1.2。没有骰子
  • 修改服务后,该方法的客户端WSDL定义突然从
    XmlDocument
    切换到Linq
    XElement
    。由于发现WSDL抽象了多平台兼容性所需的数据类型,因此怀疑服务器端反序列化问题,我将该方法的参数从
    XmlDocument
    更改为
    XElement
    。没有骰子
web.config的内容

<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>


考虑到我能够在两个独立的应用程序中成功地从两台独立的计算机发送请求,而无需任何手动配置,但不能从另外两台计算机发送请求,这是服务器端问题还是客户端配置错误?

找到了解决方案,我正在发布它,以防其他人遇到此问题

这是一个服务器端错误。如果你看到我在上面发布的方法的签名:

public XmlDocument PostOrders(XmlDocument request)
问题是参数是
XmlDocument
。由于SOAP请求的有效负载已经封装在XML中,因此无法将其反序列化为
XmlDocument
,因为有效负载的根元素不是其来源的根元素,而是
xmlement
或Linq
XElement
。然而,即使更改参数类型也不起作用——这就是我研究WSDL的时候

事实证明,这两种.NET XML类型都不起作用,因为即使我选择了可序列化类(
xmlement
/
XElement
),生成WSDL的任何对象都无法识别它们,也无法找出方法所需的数据类型,因此WSDL没有声明参数的数据类型。由于WSDL中没有声明数据类型,客户端应用程序也不知道要发送什么,因此它切断了负载,只发送SOAP头。我不知道为什么php的SOAP类是这样工作的,但它们显然是这样的

我在测试期间没有注意到它,因为我的测试应用程序也是.NET,因此自动知道要发送什么,而SoapUI的请求是原始字符串,在发送之前没有任何序列化,因此它既不需要也不关心数据类型

解决方案是将参数类型更改为
string
,并禁用基本HTTP。虽然启用了基本HTTP,但当使用字符串参数调用方法时,反序列化总是引发异常,因此我没有尽早找到此解决方案


一句话:如果您不是专门为.NET客户端编写.NET Web服务,那么不要将.NET类用作输入参数,无论它们是否可序列化。使用字符串。你会省去很多麻烦。

找到了解决方案,我会发布它,以防其他人遇到这个问题

这是一个服务器端错误。如果你看到我在上面发布的方法的签名:

public XmlDocument PostOrders(XmlDocument request)
问题是参数是
XmlDocument
。由于SOAP请求的有效负载已经封装在XML中,因此无法将其反序列化为
XmlDocument
,因为有效负载的根元素不是其来源的根元素,而是
xmlement
或Linq
XElement
。然而,即使更改参数类型也不起作用——这就是我研究WSDL的时候

事实证明,这两种.NET XML类型都不起作用,因为即使我选择了可序列化类(
xmlement
/
XElement
),生成WSDL的任何对象都无法识别它们,也无法找出方法所需的数据类型,因此WSDL没有声明参数的数据类型。由于WSDL中没有声明数据类型,客户端应用程序也不知道要发送什么,因此它切断了负载,只发送SOAP头。我不知道为什么php的SOAP类是这样工作的,但它们显然是这样的

我在测试过程中没有注意到它,因为我的测试应用程序也是.NET,因此自动知道要发送什么,而SoapUI的请求是没有任何序列号的原始字符串