我必须从C#.net核心应用程序调用Soap服务,并在一个我可以用来做一些逻辑的类中获取结果。我执行了soap请求,并且远程调用工作正常,但是现在我必须将xml soap响应反序列化为一个类。这是响应示例:
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://some_domain/soap/ApplicationServices">
<SOAP-ENV:Body>
<ns1:preparelabelsResponse xmlns:ns1="http://some_domain/soap/ApplicationServices">
<return xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="tns:PrepareReturn[1]">
<item xsi:type="tns:PrepareReturn">
<clientref xsi:type="xsd:string">2015/0418/001</clientref>
<pclid xsi:type="xsd:string"></pclid>
<error xsi:type="xsd:string">Invalid timestamp 20191018105727</error>
</item>
</return>
</ns1:preparelabelsResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
因为我使用的是Visual Studio 2017,所以我尝试使用WCF Web服务引用提供程序在.netcore应用程序中添加连接的服务,然后调用该方法。调用失败,并显示以下消息:错误的XML格式,可能是服务器生成的。在.net Framework应用程序中执行相同的步骤虽然效果很好,但我得到了正确的响应。因此,我怀疑.netcore wcf提供程序中的内容有所不同。 我的第二种方法是手动创建肥皂请求,然后解析肥皂响应。对于构造请求,我有一个优雅的解决方案,但是对于解析响应,我没有。我尝试使用wcf提供程序生成的类,但是xml反序列化无效。然后,我尝试更改属性以使其正确,但并没有帮助。我在这些类下面添加了
:[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.1")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName="preparelabelsResponse", WrapperNamespace="encoded", IsWrapped=true)]
public partial class preparelabelsResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="", Order=0)]
public PrepareReturn[] @return;
public preparelabelsResponse()
{
}
public preparelabelsResponse(PrepareReturn[] @return)
{
this.@return = @return;
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.1")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.SoapTypeAttribute(Namespace="http://some_domain/soap/ApplicationServices")]
public partial class PrepareReturn
{
private string clientrefField;
private string pclidField;
private string errorField;
/// <remarks/>
public string clientref
{
get
{
return this.clientrefField;
}
set
{
this.clientrefField = value;
}
}
/// <remarks/>
public string pclid
{
get
{
return this.pclidField;
}
set
{
this.pclidField = value;
}
}
/// <remarks/>
public string error
{
get
{
return this.errorField;
}
set
{
this.errorField = value;
}
}
}
和xml反序列化:
var soapResponse = XDocument.Load(sr);
XNamespace myns = "http://some_domain/soap/ApplicationServices";
var xml = soapResponse.Descendants(myns + "preparelabelsResponse").FirstOrDefault().ToString();
var result = Deserialize<preparelabelsResponse>(xml);
...
public static T Deserialize<T>(string xmlStr)
{
var serializer = new XmlSerializer(typeof(T));
T result;
using (TextReader reader = new StringReader(xmlStr))
{
result = (T)serializer.Deserialize(reader);
}
return result;
}
所以我能做的是从所有命名空间和属性中删除xml并将其反序列化为一个简单的类,但这并不是解决我的问题的理想方法。我想要的是能够以这样一种方式创建/装饰我的类,使得反序列化可以在不更改实际xml内容的情况下进行。