ASP.NET Core Web API中JSON转指定SOAP XML格式实现咨询
解决ASP.NET Core中JSON转特定SOAP XML的问题
嘿,作为刚接触Web API的新手,遇到这种JSON转固定格式SOAP XML的需求确实有点挠头,不过别担心,ASP.NET Core里有挺成熟且简便的方案,我来一步步给你拆解:
最推荐的方案:基于XML序列化的模型映射
因为目标SOAP XML的结构是固定的,先定义对应C#模型并添加XML序列化特性,是最易维护、出错最少的方式。
步骤1:定义接收JSON的模型
首先处理你收到的JSON请求,ASP.NET Core会自动将JSON绑定到这个模型:
public class BookRequestJson { public string Credential { get; set; } // 格式:"用户名:密码" public int BookId { get; set; } public string BookName { get; set; } public string BookAuthor { get; set; } public decimal BookPrice { get; set; } }
步骤2:定义SOAP XML对应的模型(带命名空间特性)
重点在这里,通过XmlRoot、XmlElement、XmlType等特性,直接指定每个元素的命名空间和别名映射,解决tns:前缀的问题:
// SOAP信封根节点 [XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] public class SoapEnvelope { [XmlElement(ElementName = "Header", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] public SoapHeader Header { get; set; } [XmlElement(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")] public SoapBody Body { get; set; } } // SOAP头部 public class SoapHeader { [XmlElement(ElementName = "Credential", Namespace = "http://kkr.eu/")] public CredentialPro Credential { get; set; } } // 凭证类型(对应xsi:type="tns:CredentialPro") [XmlType(TypeName = "CredentialPro", Namespace = "http://kkr.eu/")] public class CredentialPro { [XmlElement(ElementName = "UserName", Namespace = "http://kkr.eu/")] public string UserName { get; set; } [XmlElement(ElementName = "Password", Namespace = "http://kkr.eu/")] public string Password { get; set; } [XmlElement(ElementName = "UserID", Namespace = "http://kkr.eu/")] public int UserID { get; set; } // 注意你给的XML里是固定值4,按需调整 } // SOAP主体 public class SoapBody { [XmlElement(ElementName = "AddBookDetails", Namespace = "http://kkr.eu/")] public AddBookDetails AddBookDetails { get; set; } } // 书籍详情(注意BookPrice对应XML里的<tns:Price>) public class AddBookDetails { [XmlElement(ElementName = "BookId", Namespace = "http://kkr.eu/")] public int BookId { get; set; } [XmlElement(ElementName = "BookName", Namespace = "http://kkr.eu/")] public string BookName { get; set; } [XmlElement(ElementName = "BookAuthor", Namespace = "http://kkr.eu/")] public string BookAuthor { get; set; } [XmlElement(ElementName = "Price", Namespace = "http://kkr.eu/")] public decimal Price { get; set; } }
步骤3:JSON数据映射到SOAP模型并序列化
接下来把JSON模型的数据转成SOAP模型,再序列化为XML:
// 1. 拆分Credential为用户名和密码(ASP.NET Core已自动绑定JSON到bookRequest) var credParts = bookRequest.Credential.Split(':'); var userName = credParts[0]; var password = credParts[1]; // 2. 构建SOAP模型 var soapEnvelope = new SoapEnvelope { Header = new SoapHeader { Credential = new CredentialPro { UserName = userName, Password = password, UserID = 4 // 固定值,按需修改 } }, Body = new SoapBody { AddBookDetails = new AddBookDetails { BookId = bookRequest.BookId, BookName = bookRequest.BookName, BookAuthor = bookRequest.BookAuthor, Price = bookRequest.BookPrice } } }; // 3. 序列化XML并指定命名空间前缀(tns、soap等) var serializer = new XmlSerializer(typeof(SoapEnvelope)); var namespaces = new XmlSerializerNamespaces(); // 映射前缀和命名空间,和目标XML完全一致 namespaces.Add("soap", "http://schemas.xmlsoap.org/soap/envelope/"); namespaces.Add("tns", "http://kkr.eu/"); namespaces.Add("s", "http://www.w3.org/2001/XMLSchema"); namespaces.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance"); using var stringWriter = new StringWriter(); serializer.Serialize(stringWriter, soapEnvelope, namespaces); // 添加XML声明(可选,根据外部API要求) var finalXml = $"<?xml version=\"1.0\" encoding=\"UTF-8\"?>{stringWriter.ToString()}";
关于命名空间和tns:前缀的疑问解答
你困惑的tns:这类前缀,本质是命名空间的别名:
tns是我们自定义的别名,对应真实命名空间http://kkr.eu/,通过XmlSerializerNamespaces.Add("tns", "...")完成映射soap前缀对应SOAP标准信封的命名空间http://schemas.xmlsoap.org/soap/envelope/- 模型中每个
XmlElement特性的Namespace属性,指定了该元素所属的真实命名空间,序列化时会自动用你设置的前缀显示
备选方案:手动构建XML(LINQ to XML)
如果不想定义模型,也可以用LINQ to XML直接拼接XML结构,适合简单场景:
var credParts = bookRequest.Credential.Split(':'); var xDoc = new XDocument( new XDeclaration("1.0", "UTF-8", null), new XElement(XName.Get("Envelope", "http://schemas.xmlsoap.org/soap/envelope/"), new XAttribute(XNamespace.Xmlns + "soap", "http://schemas.xmlsoap.org/soap/envelope/"), new XAttribute(XNamespace.Xmlns + "tns", "http://kkr.eu/"), new XAttribute(XNamespace.Xmlns + "s", "http://www.w3.org/2001/XMLSchema"), new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"), // 头部 new XElement(XName.Get("Header", "http://schemas.xmlsoap.org/soap/envelope/"), new XElement(XName.Get("Credential", "http://kkr.eu/"), new XAttribute(XName.Get("type", "http://www.w3.org/2001/XMLSchema-instance"), "tns:CredentialPro"), new XElement(XName.Get("UserName", "http://kkr.eu/"), credParts[0]), new XElement(XName.Get("Password", "http://kkr.eu/"), credParts[1]), new XElement(XName.Get("UserID", "http://kkr.eu/"), 4) ) ), // 主体 new XElement(XName.Get("Body", "http://schemas.xmlsoap.org/soap/envelope/"), new XElement(XName.Get("AddBookDetails", "http://kkr.eu/"), new XElement(XName.Get("BookId", "http://kkr.eu/"), bookRequest.BookId), new XElement(XName.Get("BookName", "http://kkr.eu/"), bookRequest.BookName), new XElement(XName.Get("BookAuthor", "http://kkr.eu/"), bookRequest.BookAuthor), new XElement(XName.Get("Price", "http://kkr.eu/"), bookRequest.BookPrice) ) ) ) ); var finalXml = xDoc.ToString();
不过这种方式维护性较差,结构变更时需要修改大量代码,更推荐模型序列化的方式。
内容的提问来源于stack exchange,提问作者Sabi007
相关产品推荐
相关产品推荐

