【发布时间】:2021-11-15 00:41:55
【问题描述】:
要使用 SOAP 服务,我需要以 XML 格式发送消息,如下所示:
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:bus="http://ws.praxedo.com/v6/businessEvent">
<soap:Header/>
<soap:Body>
<bus:listAttachments>
<businessEventId>00044</businessEventId>
</bus:listAttachments>
</soap:Body>
</soap:Envelope>
显然,最简单的方法是创建一个字符串并在其中插入一些变量(例如businessEventId),例如:
$"<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\""
+ " xmlns:bus=\"http://ws.praxedo.com/v6/businessEvent\">"
+ "<soap:Header/><soap:Body>"
+ "<bus:listAttachments><businessEventId>{businessEventId}</businessEventId>"
+ "</bus:listAttachments></soap:Body></soap:Envelope>"
但我宁愿实例化一些 POPO 集合,例如:
public class Envelope {
public Header Header {get; init;}
public Body Body {get; init;}
}
public class Header {
}
public class Body {
public ListAttachments Attachments {get; init;}
}
public class ListAttachments {
public string BusinessEventId {get; init;}
}
我需要声明哪些属性?
假设我已经有一个填充实例,那么我需要做什么来序列化它?
--
根据@DavidBrowne 的评论,我尝试了以下不起作用的方法:
private string CreateBody(string businessEventId)
{
BusinessEventAttachmentListRequestEnvelope envelope = BusinessEventAttachmentListRequestEnvelope.From(businessEventId);
MemoryStream memorystream = new();
DataContractSerializer serializer = new(typeof(BusinessEventAttachmentListRequestEnvelope));
serializer.WriteObject(memorystream, envelope);
memorystream.Seek(0, SeekOrigin.Begin);
using StreamReader streamReader = new(memorystream);
return streamReader.ReadToEnd();
}
[DataContract(Name = "Envelope", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public class BusinessEventAttachmentListRequestEnvelope
{
[DataMember]
EmptySoapHeader Header = new();
[DataMember]
BusinessEventAttachmentListRequestBody Body { get; init; }
public static BusinessEventAttachmentListRequestEnvelope From(string businessEventId) =>
new()
{
Body = new()
{
Request = new()
{
BusinessEventId = businessEventId
}
}
};
}
[DataContract(Name = "Header", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public class EmptySoapHeader
{
}
[DataContract(Name = "Body", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public class BusinessEventAttachmentListRequestBody
{
[DataMember(Name = "listAttachments")]
public BusinessEventAttachmentListRequest Request { get; init; }
}
[DataContract(Name = "listAttachments", Namespace = "http://ws.praxedo.com/v6/businessEvent")]
public class BusinessEventAttachmentListRequest
{
[DataMember(Name = "businessEventId")]
public string BusinessEventId { get; init; }
}
生成的 XML 似乎大不相同:
<Envelope xmlns=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">
<Body>
<listAttachments xmlns:a=\"http://ws.praxedo.com/v6/businessEvent\">
<a:businessEventId>00044</a:businessEventId>
</listAttachments>
</Body>
<Header/>
</Envelope>
远程服务器返回错误 500。
【问题讨论】:
-
这取决于您使用的序列化程序。这是 DataContractSerializer:docs.microsoft.com/en-us/dotnet/framework/wcf/samples/…
-
@DavidBrowne-Microsoft,感谢您的快速响应。假设我不在乎我使用什么序列化程序,只要它适用于 .Net 5.0 并正确完成工作。但我真正关心的是,我可以获得所有那些花哨的元素名称,包括冒号和根上的那些属性。
-
您只需为每个元素配置命名空间。序列化程序将添加命名空间声明,它们的别名并不重要。
-
@DavidBrowne-Microsoft,再次感谢您的回复。我不是 100% 清楚你的意思......我也不会对任何与接收此消息的服务器无关的事情有任何高度的信心......即使有些事情不重要,也不能保证他们的实施是正确的或可能会被纠正。
-
命名空间别名无关紧要是基本的 XML。只要服务器使用真正的 XML 解析器,它就可以正常工作。但是一些序列化程序可以让您控制这一点。较旧的 XmlSerializer 更复杂,但提供了更多控制。参见例如:stackoverflow.com/questions/2339782/…
标签: c# xml serialization soap namespaces