使用 SOAP 请求 C# 的 XML 序列化和反序列化

Posted

技术标签:

【中文标题】使用 SOAP 请求 C# 的 XML 序列化和反序列化【英文标题】:XML Serialization and DeSerialization using SOAP request C# 【发布时间】:2020-05-12 18:32:31 【问题描述】:

我需要你的帮助来解决我的问题,请给我一个解决方案

我正在尝试对 动态 XML 数据进行序列化和反序列化,但数据未反序列化

这些是我的方法,我正在使用。

  **Button Click Method**

    protected void btnCreateSession_Click(object sender, EventArgs e)
    
        //System.Threading.Thread.Sleep(2000);
        tbodyException.Visible = false;//changes 9/10/12
        try
        
            CreateSessionRequest request = new CreateSessionRequest();
            //ucClientInfo uc = 
            (ucClientInfo)LoadControl("~Shared/UserControls/ucClientInfo.ascx");
            request.applicationId = ucClientInfo1.txtApplicationID.Text;
            request.accountType = ddlAccountType.SelectedValue;
            request.salesOffice =
                ddlSalesoffice.SelectedItem.ToString();//txtSalesOffice.Text;
            request.salesAgentId = txtAgentId.Text;
            // Thiyagu 10/10/2012 added for deriving metrics by Agent and Outlet details 
            request.salesAgentName = txtAgentName.Text;
            request.outletLocationId = txtOutletID.Text;
            request.outletLocationName = txtOutletName.Text;
            // Thiyagu 10/10/2012 added for deriving metrics by Agent and Outlet details 

            Dictionary<string, string> agentDetails = new Dictionary<string, string>();

            agentDetails.Add("SubClientId", request.salesOffice);
            agentDetails.Add("SalesAgentId", request.salesAgentId);
            agentDetails.Add("SalesAgentName", request.salesAgentName);
            Session.Add("AgentDetails", agentDetails);

            ClientInfo clientinfo = new ClientInfo();
            // Thiyagu 10/04/12 populating dummy app server details in client else schema 
            clientinfo = PreOrderingHelper.mapClientInfoDetails(clientinfo);
            clientinfo.name = ucClientInfo1.txtClientName.Text;
            clientinfo.clientId = ucClientInfo1.ddlClientID.SelectedValue;
            GlobalVariable.ServiceClientID = ucClientInfo1.ddlClientID.SelectedValue;
            request.client = clientinfo;

            CreateSessionResponse response = new CreateSessionResponse();


            string url = (Page.Master as TestBed).COAServiceUrl;
            var token = (Page as BasePage).Token;
            var _url = (Page as BasePage).AppUrl;
            var _action = (Page as BasePage).Action + CurrentFlow.ToString();
            bool localDebug = Convert.ToBoolean(System.Configuration.ConfigurationManager.AppSettings["localDebug"]);
            if (!localDebug)
            
                //ServiceHelper<CreateSessionRequest, CreateSessionResponse> helper = new 
                ServiceHelper<CreateSessionRequest, CreateSessionResponse>(url);
                //response = helper.CallService(request, CurrentFlow.ToString(), TcId);
                var webRequest = (HttpWebRequest)CommonUtil.SendSOAPRequest(request, _url, CurrentFlow.ToString(), token, _action, false);
                string result;
                using (WebResponse resp = webRequest.GetResponse())
                
                    using (StreamReader rd = new StreamReader(resp.GetResponseStream()))
                    
                        result = rd.ReadToEnd();
                        response = CommonUtil.DeserializeInnerSoapObject < CreateSessionResponse(result);
                    
                
            
            else
            
                TextReader tr = new StreamReader(@"C:\SampleXmls\CreateSessionResp.xml");
                System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(CreateSessionResponse), "http://verizon.com/CoFEEAnywhere/CoAServices/v1");
                //response = xs.Deserialize(tr) as SoapResponse.CreateSessionResponse;
                response = xs.Deserialize(tr) as CreateSessionResponse;
            

            if (response != null && response.output != null &&
              !string.IsNullOrEmpty(response.output.sessionId))
            

                Session["sessionId"] = response.output.sessionId;  // Saving it in session - Can be used elsewehere in later flows
                (Page.Master.FindControl("lblGlobalSessionIDValue") as Label).Text = response.output.sessionId; // setting the bottom session area in Preordering.aspx                    
                var masterPage = Page.Master as TestBed;
                masterPage.SessionIdUpdatePanel.Update();
                (Page as BasePage).SessionID = response.output.sessionId;
                lblCreatedSession.Text = (Page as BasePage).SessionID;
                lblSalesProfileResult.Text = "SUCCESS";

                Session["ClientId"] = ucClientInfo1.ddlClientID.SelectedValue;
                Session["ClientName"] = ucClientInfo1.txtClientName.Text;
                Session["AppId"] = ucClientInfo1.txtApplicationID.Text;
                Session["OrderType"] = ddlOrderType.SelectedValue;
                Session["AccountType"] = ddlAccountType.SelectedValue;
            
        
        catch (Exception ex)
        
            tbodyException.Visible = true;
            aExcpetion.InnerText = ex.Message + "  |  " + ex.InnerException != null ?
           ex.InnerException.Message : string.Empty;//aExcpetion.Attributes.Add("onclick", 
            "OpenExceptionWindow('" + ex.InnerException + "');
         
        finally
        
            if (!string.IsNullOrEmpty(Session["ClientId"].ToString()) &&
            Session["ClientId"].ToString() == "CETC")
            
                var masterPage = Page.Master as TestBed;
                masterPage.NextFlow.CommandName = FlowType.Recommended.ToString();
                masterPage.NextFlow.Text = "Next";
                masterPage.NextFlow.Visible = true;
            
            else
            
                var masterPage = Page.Master as TestBed;
                masterPage.NextFlow.Visible = true;
            
        
    

** SOAP 请求**

    public static object SendSOAPRequest(object req, string _url, string methodName, string token, string _action, bool useSOAP12)
    
        ServicePointManager.ServerCertificateValidationCallback = new

          RemoteCertificateValidationCallback
                                                       (
                                                          delegate  return true; 
                                                       );
        // Create the SOAP envelope
        var formXml = new XmlDocument();
        string soapXml = "";
        soapXml = WsdlRequestToSOAP(req);
        if (methodName == "GetBroadbandAvailability")
        
            soapXml = soapXml.Remove(0, 21).Replace(methodName + "Request",
              "gbbRequest");
        
        else if (methodName == "GetQualifiedProducts")
        
            soapXml = soapXml.Remove(0, 21).Replace(methodName + "Request",
            "productsrequest");
        
        else
        
            soapXml = soapXml.Remove(0, 21).Replace(methodName + "Request", "req" +
         methodName);
        

        formXml.LoadXml(soapXml);

        var newXml = new XmlDocument();
        var rootTag = String.Format("<0></0>", methodName);
        newXml.LoadXml(rootTag);

        XmlNode rootNode = newXml.ImportNode(formXml.DocumentElement, true);
        newXml.DocumentElement.AppendChild(rootNode);

        var stringXml = @"<?xml version=""1.0"" encoding=""utf-8""?>
                            <soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"" 
                                xmlns=""http://some link""
                                xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" 
                       xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
                                <soap:Body>
                                   0
                                </soap:Body>
                            </soap:Envelope>";
        var s = String.Format(stringXml, newXml.InnerXml);
        formXml.LoadXml(s);
        // Create the web request
        HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(_url);
        webRequest.Headers.Add("SOAPAction", _action ?? _url);
        webRequest.ContentType = (useSOAP12) ? "application/soap+xml;charset=\"utf-8\"" :
          "text/xml; encoding=utf-8";
        webRequest.Accept = (useSOAP12) ? "application/soap+xml" : "text/xml";
        webRequest.Method = "POST";
        webRequest.Headers.Add("Authorization", "Bearer " + token);
        webRequest.Headers.Add("X-CLIENT-CERT-STATUS", "ok");
        webRequest.Headers.Add("X-SUBJECT-NAME", "C=US, ST=Florida, L=Temple Terrace, O =\"Verizon Data Services.LLC\", OU=GTSAP, CN=apigee.coasvcs.verizon.com");

        // Insert SOAP envelope
        using (Stream stream = webRequest.GetRequestStream())
        
            formXml.Save(stream);
        

        return webRequest;
    

** 授权请求**

    public static string AuthorizeRequest()
    
        string client_id = "t1ehVqcAGYmWC8yvPapwgdZOqOjQd5oO";
        string client_secret = "ICo3o8Da8BCpmXk0";
        var restClient = new RestClient("https://some link / oauth / client_credential / accesstoken ? grant_type = client_credentials");

        var restRequest = new RestRequest(Method.POST);
        restRequest.AddHeader("Cache-Control", "no-cache");
        restRequest.AddHeader("Content-Type", "application/json");
        restRequest.AddParameter("client_id", client_id);
        restRequest.AddParameter("client_secret", client_secret);
        IRestResponse restResponse = restClient.Execute(restRequest);
        var responseJson = restResponse.Content;
        var token = JsonConvert.DeserializeObject<Dictionary<string, object>>
         (responseJson)["access_token"].ToString();

        return token;
    

** WsdlRequestToSOAP**

    public static string WsdlRequestToSOAP(object Object)
    
        if (Object == null)
        
            throw new ArgumentException("Object can not be null");
        
        try
        
            var serxml = new System.Xml.Serialization.XmlSerializer(Object.GetType());
            var ms = new MemoryStream();
            serxml.Serialize(ms, Object);
            return Encoding.UTF8.GetString(ms.ToArray());
        
        catch  throw; 
    

** IndentXMLString**

    public static string IndentXMLString(string xml)
    
        string outXml = string.Empty;
        MemoryStream ms = new MemoryStream();
        // Create a XMLTextWriter that will send its output to a memory stream (file)
        XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.Unicode);
        XmlDocument doc = new XmlDocument();
        StreamReader sr = null;`enter code here`
         try
        
            // Load the unformatted XML text string into an instance 
            // of the XML Document Object Model (DOM)
            doc.LoadXml(xml);

            // Set the formatting property of the XML Text Writer to indented
            // the text writer is where the indenting will be performed
            xtw.Formatting = System.Xml.Formatting.Indented;

            // write dom xml to the xmltextwriter
            doc.WriteContentTo(xtw);
            // Flush the contents of the text writer
            // to the memory stream, which is simply a memory file
            xtw.Flush();

            // set to start of the memory stream (file)
            ms.Seek(0, SeekOrigin.Begin);
            // create a reader to read the contents of 
            // the memory stream (file)
            sr = new StreamReader(ms);
            // return the formatted string to caller                
        
        catch (Exception ex)
        

        
        return sr.ReadToEnd();
    

** 最后这是 DeserializeInnerSoapObject 方法**

    public static T DeserializeInnerSoapObject<T>(string soapResponse)
    
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.LoadXml(soapResponse);

        var soapBody = xmlDocument.GetElementsByTagName("s:Body")[0];
        string innerObject = IndentXMLString(soapBody.InnerXml); //soapBody.InnerXml;

        XmlSerializer deserializer = new XmlSerializer(typeof(T), "http://some link");


        using (TextReader reader = new StringReader(innerObject))
        
            return (T)deserializer.Deserialize(reader);
        
    

【问题讨论】:

先尝试序列化数据并将格式与实际的soap响应进行比较。在序列化之前,您可能需要创建测试数据来归档类。 你能不能通过这些方法 这不是我们使用 SOAP 生成动态 xml 数据的静态数据 【参考方案1】:

尝试以下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1

    class Program
    
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        
            string soap = File.ReadAllText(FILENAME);
            StringReader sReader = new StringReader(soap);
            XmlReader reader = XmlReader.Create(sReader);

            XmlSerializer serializer = new XmlSerializer(typeof(Envelope));

            Envelope envelope = (Envelope)serializer.Deserialize(reader);

        
    
    [XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
    public class Envelope
    
        [XmlElement(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
        public Body body  get; set; 
    
    public class Body
    
        [XmlElement(ElementName = "CreateSessionResponse", Namespace = "http://some link")]
        public CreateSessionResponse CreateSessionResponse  get; set; 
    
    public class CreateSessionResponse
    
        [XmlElement(ElementName = "CreateSessionResult", Namespace = "http://some link")]
        public CreateSessionResult CreateSessionResult  get; set; 
    
    public class CreateSessionResult
    
        [XmlElement(ElementName = "output", Namespace = "http://some link")]
        public Output Output  get; set; 
    
    public class Output
    
        [XmlElement]
        public string sessionId  get; set; 
    


【讨论】:

好的,我会试试并告诉你【参考方案2】:

其实这不是答案

我在这里分享了我的输出,请检查一下并给我这个问题的解决方案

我收到了这样的 Soap 响应

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CreateSessionResponse xmlns="http://some link">
      <CreateSessionResult>
        <output>
          <sessionId>some id</sessionId>
        </output>
      </CreateSessionResult>
    </CreateSessionResponse>
  </soap:Body>
</soap:Envelope>

【讨论】:

以上是关于使用 SOAP 请求 C# 的 XML 序列化和反序列化的主要内容,如果未能解决你的问题,请参考以下文章

C# XML序列化和反序列化(XmlSerializer)

在C#中序列化和反序列化之间保留xml元素的顺序

C#关于序列化和反序列化

在 C# 中,如何使用大量精美的标记将 POCO 序列化为 XML?

C# XML和实体类之间相互转换(序列化和反序列化)

如何使用 c# 为 paypal CreateInvoice api 创建 SOAP XML 请求消息