You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C#输入对象生成SOAP请求并反序列化SOAP响应为C#对象

实现SOAP请求生成与响应反序列化(基于C#)

需求说明

需要完成两项核心任务:

  1. 基于C# CustomerRequest 对象动态生成符合指定格式的SOAP请求
  2. 将返回的SOAP响应解析并反序列化为C# CustomerResponse 对象

一、从CustomerRequest生成SOAP请求

输入的CustomerRequest类

public class CustomerRequest
{
    public int CustomerID { get; set; }
    public string CustomerName { get; set; }
    public string CustomerNum { get; set; }     
}

实现方式1:字符串模板替换(简单直接)

利用预定义的SOAP请求模板,把CustomerRequest的属性值替换到对应位置,适合结构固定的场景:

public string GenerateSoapRequest(CustomerRequest request)
{
    var soapTemplate = @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:bsvc=""urn:com.workday/bsvc"">
   <soapenv:Header>
      <bsvc:Workday_Common_Header>
         <bsvc:Include_Reference_Descriptors_In_Response>1</bsvc:Include_Reference_Descriptors_In_Response>
      </bsvc:Workday_Common_Header>
   </soapenv:Header>
   <soapenv:Body>
      <bsvc:Get_Customers_Request bsvc:version=""v42.0"">
         <bsvc:Request_References>
            <bsvc:Customer_Reference bsvc:Descriptor=""?"">
               <bsvc:ID bsvc:type=""Customer_ID"">{0}</bsvc:ID>
               <bsvc:Customer_Name>{1}</bsvc:Customer_Name>
               <bsvc:Customer_Num>{2}</bsvc:Customer_Num>
            </bsvc:Customer_Reference>
         </bsvc:Request_References>
         <bsvc:Response_Group>
            <bsvc:Include_Reference>1</bsvc:Include_Reference>
            <bsvc:Include_Customer_Data>1</bsvc:Include_Customer_Data>
            <bsvc:Include_Customer_Balance>1</bsvc:Include_Customer_Balance>
            <bsvc:Include_Customer_Activity_Detail>1</bsvc:Include_Customer_Activity_Detail>
         </bsvc:Response_Group>
      </bsvc:Get_Customers_Request>
   </soapenv:Body>
</soapenv:Envelope>";

    return string.Format(soapTemplate, request.CustomerID, request.CustomerName, request.CustomerNum);
}

实现方式2:XmlSerializer序列化SOAP实体类(规范可控)

先定义与SOAP请求结构完全对应的实体类,再通过XmlSerializer序列化生成请求,适合需要动态调整请求结构的场景:

// 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; }
}

public class SoapHeader
{
    [XmlElement(ElementName = "Workday_Common_Header", Namespace = "urn:com.workday/bsvc")]
    public WorkdayCommonHeader WorkdayCommonHeader { get; set; }
}

public class WorkdayCommonHeader
{
    [XmlElement(ElementName = "Include_Reference_Descriptors_In_Response", Namespace = "urn:com.workday/bsvc")]
    public string IncludeReferenceDescriptorsInResponse { get; set; } = "1";
}

public class SoapBody
{
    [XmlElement(ElementName = "Get_Customers_Request", Namespace = "urn:com.workday/bsvc")]
    public GetCustomersRequest GetCustomersRequest { get; set; }
}

public class GetCustomersRequest
{
    [XmlAttribute(AttributeName = "version", Namespace = "urn:com.workday/bsvc")]
    public string Version { get; set; } = "v42.0";

    [XmlElement(ElementName = "Request_References", Namespace = "urn:com.workday/bsvc")]
    public RequestReferences RequestReferences { get; set; }

    [XmlElement(ElementName = "Response_Group", Namespace = "urn:com.workday/bsvc")]
    public ResponseGroup ResponseGroup { get; set; }
}

public class RequestReferences
{
    [XmlElement(ElementName = "Customer_Reference", Namespace = "urn:com.workday/bsvc")]
    public CustomerReference CustomerReference { get; set; }
}

public class CustomerReference
{
    [XmlAttribute(AttributeName = "Descriptor", Namespace = "urn:com.workday/bsvc")]
    public string Descriptor { get; set; } = "?";

    [XmlElement(ElementName = "ID", Namespace = "urn:com.workday/bsvc")]
    public ID Id { get; set; }

    [XmlElement(ElementName = "Customer_Name", Namespace = "urn:com.workday/bsvc")]
    public string CustomerName { get; set; }

    [XmlElement(ElementName = "Customer_Num", Namespace = "urn:com.workday/bsvc")]
    public string CustomerNum { get; set; }
}

public class ID
{
    [XmlAttribute(AttributeName = "type", Namespace = "urn:com.workday/bsvc")]
    public string Type { get; set; } = "Customer_ID";

    [XmlText]
    public string Value { get; set; }
}

public class ResponseGroup
{
    [XmlElement(ElementName = "Include_Reference", Namespace = "urn:com.workday/bsvc")]
    public string IncludeReference { get; set; } = "1";

    [XmlElement(ElementName = "Include_Customer_Data", Namespace = "urn:com.workday/bsvc")]
    public string IncludeCustomerData { get; set; } = "1";

    [XmlElement(ElementName = "Include_Customer_Balance", Namespace = "urn:com.workday/bsvc")]
    public string IncludeCustomerBalance { get; set; } = "1";

    [XmlElement(ElementName = "Include_Customer_Activity_Detail", Namespace = "urn:com.workday/bsvc")]
    public string IncludeCustomerActivityDetail { get; set; } = "1";
}

// 生成SOAP请求的方法
public string GenerateSoapRequestWithSerializer(CustomerRequest request)
{
    var soapEnvelope = new SoapEnvelope
    {
        Header = new SoapHeader(),
        Body = new SoapBody
        {
            GetCustomersRequest = new GetCustomersRequest
            {
                RequestReferences = new RequestReferences
                {
                    CustomerReference = new CustomerReference
                    {
                        Id = new ID { Value = request.CustomerID.ToString() },
                        CustomerName = request.CustomerName,
                        CustomerNum = request.CustomerNum
                    }
                }
            }
        }
    };

    var serializer = new XmlSerializer(typeof(SoapEnvelope));
    using var stringWriter = new StringWriter();
    serializer.Serialize(stringWriter, soapEnvelope);
    return stringWriter.ToString();
}

二、将SOAP响应反序列化为CustomerResponse

目标CustomerResponse类

public class CustomerResponse
{
    public int CustomerID { get; set; }
    public string WID { get; set; }
    public string CustomerCategory { get; set; }
    public string PaymentType { get; set; }
    public decimal YTDSalesAmt { get; set; }
    public decimal TotalBalance { get; set; }
}

实现方式1:XPath提取字段(轻量高效)

直接解析SOAP响应XML,通过XPath定位需要的字段值,适合只需要提取部分字段的场景:

public CustomerResponse DeserializeSoapResponse(string soapResponse)
{
    var xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(soapResponse);
    var nsManager = new XmlNamespaceManager(xmlDoc.NameTable);
    nsManager.AddNamespace("env", "http://schemas.xmlsoap.org/soap/envelope/");
    nsManager.AddNamespace("wd", "urn:com.workday/bsvc");

    var response = new CustomerResponse();

    // 提取CustomerID
    var customerIdNode = xmlDoc.SelectSingleNode("//wd:ID[@wd:type='Customer_ID']", nsManager);
    if (customerIdNode != null)
        int.TryParse(customerIdNode.InnerText, out response.CustomerID);

    // 提取WID
    var widNode = xmlDoc.SelectSingleNode("//wd:ID[@wd:type='WID']", nsManager);
    if (widNode != null)
        response.WID = widNode.InnerText;

    // 提取YTD销售额
    var ytdSalesNode = xmlDoc.SelectSingleNode("//wd:YTD_Sales_Amount", nsManager);
    if (ytdSalesNode != null)
        decimal.TryParse(ytdSalesNode.InnerText, out response.YTDSalesAmt);

    // 提取总余额
    var totalBalanceNode = xmlDoc.SelectSingleNode("//wd:Total_Balance", nsManager);
    if (totalBalanceNode != null)
        decimal.TryParse(totalBalanceNode.InnerText, out response.TotalBalance);

    // 注:CustomerCategory和PaymentType在示例响应中未出现,需根据实际响应结构补充XPath
    return response;
}

实现方式2:XmlSerializer序列化响应实体类(规范完整)

定义与SOAP响应结构对应的实体类,通过XmlSerializer反序列化后映射到CustomerResponse,适合需要完整解析响应的场景:

// SOAP响应信封实体类
[XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class SoapResponseEnvelope
{
    [XmlElement(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
    public SoapResponseBody Body { get; set; }
}

public class SoapResponseBody
{
    [XmlElement(ElementName = "Get_Customers_Response", Namespace = "urn:com.workday/bsvc")]
    public GetCustomersResponse GetCustomersResponse { get; set; }
}

public class GetCustomersResponse
{
    [XmlAttribute(AttributeName = "version", Namespace = "urn:com.workday/bsvc")]
    public string Version { get; set; }

    [XmlElement(ElementName = "Request_References", Namespace = "urn:com.workday/bsvc")]
    public ResponseRequestReferences RequestReferences { get; set; }

    [XmlElement(ElementName = "Response_Data", Namespace = "urn:com.workday/bsvc")]
    public ResponseData ResponseData { get; set; }
}

public class ResponseRequestReferences
{
    [XmlElement(ElementName = "Customer_Reference", Namespace = "urn:com.workday/bsvc")]
    public ResponseCustomerReference CustomerReference { get; set; }
}

public class ResponseCustomerReference
{
    [XmlElement(ElementName = "ID", Namespace = "urn:com.workday/bsvc")]
    public List<ResponseID> IDs { get; set; }
}

public class ResponseID
{
    [XmlAttribute(AttributeName = "type", Namespace = "urn:com.workday/bsvc")]
    public string Type { get; set; }

    [XmlText]
    public string Value { get; set; }
}

public class ResponseData
{
    [XmlElement(ElementName = "Customer", Namespace = "urn:com.workday/bsvc")]
    public Customer Customer { get; set; }
}

public class Customer
{
    [XmlElement(ElementName = "Customer_Balance_Data", Namespace = "urn:com.workday/bsvc")]
    public CustomerBalanceData CustomerBalanceData { get; set; }
}

public class CustomerBalanceData
{
    [XmlElement(ElementName = "YTD_Sales_Amount", Namespace = "urn:com.workday/bsvc")]
    public decimal YtdSalesAmount { get; set; }

    [XmlElement(ElementName = "Total_Balance", Namespace = "urn:com.workday/bsvc")]
    public decimal TotalBalance { get; set; }
}

// 反序列化方法
public CustomerResponse DeserializeSoapResponseWithSerializer(string soapResponse)
{
    var serializer = new XmlSerializer(typeof(SoapResponseEnvelope));
    using var stringReader = new StringReader(soapResponse);
    var envelope = (SoapResponseEnvelope)serializer.Deserialize(stringReader);

    var response = new CustomerResponse();

    // 提取CustomerID和WID
    var customerIds = envelope.Body.GetCustomersResponse.RequestReferences.CustomerReference.IDs;
    response.CustomerID = int.Parse(customerIds.First(id => id.Type == "Customer_ID").Value);
    response.WID = customerIds.First(id => id.Type == "WID").Value;

    // 提取余额数据
    var balanceData = envelope.Body.GetCustomersResponse.ResponseData.Customer.CustomerBalanceData;
    response.YTDSalesAmt = balanceData.YtdSalesAmount;
    response.TotalBalance = balanceData.TotalBalance;

    // 注:CustomerCategory和PaymentType需根据实际响应结构补充实体类属性
    return response;
}

内容的提问来源于stack exchange,提问作者Rita

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 09:07:03