How to parse MTOM soap response in c# - c#

I want to parse the web service response which is in soap MTOM format.
It is the response
--MIMEBoundary_437235bf25f089af96e3a1387b60bdfbd52e58e56b20f9b0
Content - Type: application / xop + xml; charset = utf - 8; type = "text/xml"
Content - Transfer - Encoding: binary
Content - ID: < 0.737235bf25f089af96e3a1387b60bdfbd52e58e56b20f9b0 #apache.org >
<? xml version = "1.0" encoding = "utf-8" ?>
< soapenv : Envelope xmlns: soapenv = "http://schemas.xmlsoap.org/soap/envelope/" >
< soapenv:Body >
< sendDataResponse xmlns: a = "http://www.w3.org/2005/05/xmlmime" xmlns = "http://org/emedny/fts/" >
< output >< fileName > ABC.x12 </ fileName ></ output >
</ sendDataResponse >
</ soapenv:Body >
</ soapenv:Envelope >
--MIMEBoundary_437235bf25f089af96e3a1387b60bdfbd52e58e56b20f9b0--
i have tried using XmlDictionaryReader but it is giving error
"The Message Transmission Optimization Mechanism (MTOM) message encoding is not supported on this platform."
string MTOM = response;
MemoryStream ms;
ItemOperations obj;
DataContractSerializer dcs = new DataContractSerializer(typeof(ItemOperations));
string fixedMtom = MTOM.Replace(
"Multipart/Related;boundary=437235bf25f089af96e3a1387b60bdfbd52e58e56b20f9b0;",
"Multipart/Related;boundary=\"437235bf25f089af96e3a1387b60bdfbd52e58e56b20f9b0?MTOM\";");
ms = new MemoryStream(Encoding.UTF8.GetBytes(fixedMtom));
XmlDictionaryReader reader = XmlDictionaryReader.CreateMtomReader(ms, Encoding.UTF8, XmlDictionaryReaderQuotas.Max);
I want to extract the file name from soap element.How can i get it?

I finally got it to work using Regex. Lost of issues with space in the xml :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
using System.Text.RegularExpressions;
namespace ConsoleApplication117
{
class Program
{
const string FILENAME = #"c:\temp\test.txt";
static void Main(string[] args)
{
string input = File.ReadAllText(FILENAME);
string pattern = #"(?'xml'\<\?.*)--MIMEBoundary";
Match match = Regex.Match(input,pattern,RegexOptions.Singleline);
string xml = match.Groups["xml"].Value.Trim();
string pattern1 = #"\<[?/]?((\s*\w+\s*:\s*\w+)|(\s*\w+))";
xml = Regex.Replace(xml, pattern1, ReplaceSpaces);
string pattern2 = #"\w+\s*:\s*\w+\s*=";
xml = Regex.Replace(xml, pattern2, ReplaceSpaces); //remove spaces in namespaces
XDocument doc = XDocument.Parse(xml);
string filename = (string)doc.Descendants().Where(x => x.Name.LocalName == "fileName").FirstOrDefault();
}
static string ReplaceSpaces(Match match)
{
string input = match.Value;
string pattern = #"\s*(?'name1'\w+)\s*(?'colon':)*\s*(?'name2'\w*)";
string output = Regex.Replace(input, pattern, "${name1}${colon}${name2}");
return output;
}
}
public class Player
{
}
}

parse xml structure using VS (Edit/Paste as json or xml) or enter link description here
[XmlRoot(ElementName = "output", Namespace = "http://org/emedny/fts/")]
public class Output
{
[XmlElement(ElementName = "fileName", Namespace = "http://org/emedny/fts/")]
public string FileName { get; set; }
}
[XmlRoot(ElementName = "sendDataResponse", Namespace = "http://org/emedny/fts/")]
public class SendDataResponse
{
[XmlElement(ElementName = "output", Namespace = "http://org/emedny/fts/")]
public Output Output { get; set; }
[XmlAttribute(AttributeName = "a", Namespace = "http://www.w3.org/2000/xmlns/")]
public string A { get; set; }
[XmlAttribute(AttributeName = "xmlns")]
public string Xmlns { get; set; }
}
[XmlRoot(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Body
{
[XmlElement(ElementName = "sendDataResponse", Namespace = "http://org/emedny/fts/")]
public SendDataResponse SendDataResponse { get; set; }
}
[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; }
[XmlAttribute(AttributeName = "soapenv", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Soapenv { get; set; }
}
.....
using (var st = File.OpenRead(#"i_saved_your_request_here.xml"))
{
var data = new XmlSerializer(typeof(Envelope)).Deserialize(st) as Envelope;
var output = data.Body.SendDataResponse.Output.FileName;
}

Related

Need help in converting the XML to Objects

Hi i need help in converting the XML to Object class so whenever i convert that object back into the XML format i got the same output as expected in some API request.
For now i used online tool(https://json2csharp.com/code-converters/xml-to-csharp) that converts that model into XML but still it's not as expected.
like after convert the root attribute got missed i.e. xmlns:p also the <p: starting tag at name, so calling the API fails because of this as they expected me to send along
Example XML is here:
<p:EIDVBusinessSearch xmlns:p="example.com" xmlns:xsi="abc.com" xsi:schemaLocation="cde.com">
<PermissiblePurpose>
<GLB>{{GLB}}</GLB>
<DPPA>{{DPPA}}</DPPA>
<VOTER>{{VOTER}}</VOTER>
<PermissiblePurpose>
</p:EIDVBusinessSearch>.
I have created a desktop WinForm application using .NET 6 framework and write the following code.
I hope this code will help you in some way to fix your problem.
Note: you have to use XmlAttribute Namespace properly to fix your missing attribute issue.
However, the starting p: will stay remain missing.
EidBusinessSearch class:
[XmlRoot(ElementName = "EIDVBusinessSearch", Namespace = "example.com")]
public class EIDVBusinessSearch
{
[XmlElement(ElementName = "PermissiblePurpose", Namespace = "")]
public PermissiblePurpose? PermissiblePurpose { get; set; }
[XmlAttribute(AttributeName = "p", Namespace = "http://www.w3.org/2000/xmlns/")]
public string? P { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
public string? Xsi { get; set; }
[XmlAttribute(AttributeName = "schemaLocation", Namespace = "abc.com")]
public string? SchemaLocation { get; set; }
[XmlText]
public string? Text { get; set; }
}
PermissiblePurpose
[XmlRoot(ElementName = "PermissiblePurpose", Namespace = "")]
public class PermissiblePurpose
{
[XmlElement(ElementName = "GLB", Namespace = "")]
public string? GLB { get; set; }
[XmlElement(ElementName = "DPPA", Namespace = "")]
public string? DPPA { get; set; }
[XmlElement(ElementName = "VOTER", Namespace = "")]
public string? VOTER { get; set; }
}
Method to Convert XML to Object:
private void ConvertXMLtoObject()
{
try
{
string xml = "<p:EIDVBusinessSearch xmlns:p=\"example.com\" xmlns:xsi=\"abc.com\" xsi:schemaLocation=\"cde.com\">" +
"\r\n <PermissiblePurpose>" +
"\r\n <GLB>{{GLB}}</GLB>" +
"\r\n <DPPA>{{DPPA}}</DPPA>" +
"\r\n <VOTER>{{VOTER}}</VOTER>" +
"\r\n </PermissiblePurpose>" +
"\r\n</p:EIDVBusinessSearch>";
XmlSerializer serializer = new(typeof(EIDVBusinessSearch));
EIDVBusinessSearch obj = new();
using StringReader reader = new(xml);
obj = (EIDVBusinessSearch)serializer.Deserialize(reader);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
Application.Exit();
}
}
Convert Object to XML:
private void ConvertObjectToXML()
{
try
{
EIDVBusinessSearch obj = new()
{
P = "example.com",
PermissiblePurpose = new()
};
obj.PermissiblePurpose.GLB = "GLB";
obj.PermissiblePurpose.DPPA = "DPPA";
obj.PermissiblePurpose.VOTER = "VOTER";
XmlSerializer serializer = new(obj.GetType());
using StringWriter writer = new();
serializer.Serialize(writer, obj);
string xml = writer.ToString();
label1.Text = xml;
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
Application.Exit();
}
}
Output:

What will be the way to read xml here?

I have this below xml file:-
<?xml version="1.0" encoding="utf-8" ?>
<LoanProduct xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Program>
<ProgramID>6</ProgramID>
<Name>Primary Loan</Name>
<InterestRate>0.23</InterestRate>
<StartDate>2018-12-20</StartDate>
<EndDate>2019-03-31</EndDate>
</Program>
<Program>
<ProgramID>6</ProgramID>
<Name>Primary Loan</Name>
<InterestRate>0.25</InterestRate>
<StartDate>2019-04-1</StartDate>
<EndDate>2099-12-31</EndDate>
</Program>
</LoanProduct>
In my class file I have to read from xml file and run some query on it:-
String xml = Server.MapPath("/Resources/LoanProduct.xml");
DataSet dataSet = new DataSet();
dataSet.ReadXml(xml);
Suppose I want to retrieve where ProgramID= 6 and EndDate = '2099-12-31'
How can I achieve that?
You can achieve your desired result by using XDocument under the namespace System.Xml.Linq.
XDocument doc = XDocument.Load(#"Path to your xml file");
var ns = doc.Root.GetDefaultNamespace();
var result = (from program in doc.Descendants(ns + "Program")
where Convert.ToInt32(program.Element(ns + "ProgramID").Value) == 6 && program.Element(ns + "EndDate").Value == "2099-12-31"
select program).FirstOrDefault();
Output: (From Debugger)
You can use serialization. The date should be consistent otherwise you will get an error with this code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication3
{
class Program1
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(LoanProduct));
LoanProduct loanProduct = (LoanProduct)serializer.Deserialize(reader);
}
}
[XmlRoot(ElementName = "LoanProduct", Namespace = "")]
public class LoanProduct
{
[XmlElement("Program", Namespace = "")]
public List<Program> programs { get; set; }
}
[XmlRoot(ElementName = "Program", Namespace = "")]
public class Program
{
public int ProgramID { get; set; }
public string Name { get; set; }
public decimal InterestRate { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
}

Read Elements from XML in c#

I have response from web service and my code looks like following
using (WebResponse response2 = request.GetResponse())
{
using (StreamReader rd = new StreamReader(response2.GetResponseStream()))
{
string soapResult = rd.ReadToEnd();
}
}
Now I have my complete response to string soapResult.
My XML looks like following:
soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetResponse xmlns="http://ws.design.americaneagle.com">
<GetResult>
<Distance>0</Distance>
<ID>100</ID>
<Name>Wisconsin</Name>
<Code>WI</Code>
<Address1>202 Las COlinas</Address1>
</GetResult>
</GetResponse>
</soap:Body>
</soap:Envelope>
I want to read ID, Name, and Address1 from the above XML.
How to achieve this? I am new to XML in c#.
Any help? Thanks in advance.
Using xml linq. For testing I'm reading from a file (instead of a webresponse) so you have to make slight changes to go back to your original code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
using (StreamReader rd = new StreamReader(FILENAME))
{
XDocument doc = XDocument.Load(rd);
XElement response = doc.Descendants().Where(x => x.Name.LocalName == "GetResponse").FirstOrDefault();
XNamespace ns = response.GetDefaultNamespace();
var data = response.Descendants(ns + "GetResult").Select(x => new {
distance = (int)x.Element(ns + "Distance"),
id = (int)x.Element(ns + "ID"),
name = (string)x.Element(ns + "Name"),
code = (string)x.Element(ns + "Code"),
addresss = (string)x.Element(ns + "Address1")
}).FirstOrDefault();
}
}
}
}
Use the Xmldocument . With use root statement . It's very to use .. read about it .. or use XPath. Also read about it!
I pasted your XML in XML to Sharp and got this:
using System;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace Xml2CSharp
{
[XmlRoot(ElementName = "GetResult", Namespace = "http://ws.design.americaneagle.com")]
public class GetResult
{
[XmlElement(ElementName = "Distance", Namespace = "http://ws.design.americaneagle.com")]
public string Distance { get; set; }
[XmlElement(ElementName = "ID", Namespace = "http://ws.design.americaneagle.com")]
public string ID { get; set; }
[XmlElement(ElementName = "Name", Namespace = "http://ws.design.americaneagle.com")]
public string Name { get; set; }
[XmlElement(ElementName = "Code", Namespace = "http://ws.design.americaneagle.com")]
public string Code { get; set; }
[XmlElement(ElementName = "Address1", Namespace = "http://ws.design.americaneagle.com")]
public string Address1 { get; set; }
}
[XmlRoot(ElementName = "GetResponse", Namespace = "http://ws.design.americaneagle.com")]
public class GetResponse
{
[XmlElement(ElementName = "GetResult", Namespace = "http://ws.design.americaneagle.com")]
public GetResult GetResult { get; set; }
[XmlAttribute(AttributeName = "xmlns")]
public string Xmlns { get; set; }
}
[XmlRoot(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Body
{
[XmlElement(ElementName = "GetResponse", Namespace = "http://ws.design.americaneagle.com")]
public GetResponse GetResponse { get; set; }
}
[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; }
[XmlAttribute(AttributeName = "soap", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Soap { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsi { get; set; }
[XmlAttribute(AttributeName = "xsd", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsd { get; set; }
}
}
Then you have to deserialize it.
var serializer = new XmlSerializer(typeof(Envelope));
Envelope result;
using (TextReader reader = new StringReader(xml))
{
result = (Envelope)serializer.Deserialize(reader);
}

I couldn't create subnodes with different prefix in same parent node

I'm trying to create a XML something like this :
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
- <inventory_report:inventoryReportMessage xmlns:inventory_report="urn:gs1:ecom:inventory_report:xsd:3" xmlns:sh="http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader" xmlns:ecom_common="urn:gs1:ecom:ecom_common:xsd:3" xmlns:shared_common="urn:gs1:shared:shared_common:xsd:3">
- <sh:StandardBusinessDocumentHeader>
<sh:HeaderVersion>Standard Business Header version 1.3</sh:HeaderVersion>
- <sh:Sender>
<sh:Identifier Authority="GS1">0000</sh:Identifier>
- <sh:ContactInformation>
<sh:Contact>some one</sh:Contact>
<sh:EmailAddress>someone#example.com</sh:EmailAddress>
<sh:TelephoneNumber>00357</sh:TelephoneNumber>
<sh:ContactTypeIdentifier>IT Support</sh:ContactTypeIdentifier>
</sh:ContactInformation>
</sh:Sender>
I'm using the below code for creating the XML -->
var xelementNode = doc.CreateElement("inventory_report", "inventoryReportMessage","urn:gs1:ecom:inventory_report:xsd:3");
doc.AppendChild(xelementNode);
var xelementSubNode = doc.CreateElement("sh", xelementNode, "StandardBusinessDocumentHeades","");
xelementNode.AppendChild(xelementSubNode);
I'm getting this output for the above code -->
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes" ?>
- <inventory_report:inventoryReportMessage xmlns:inventory_report="urn:gs1:ecom:inventory_report:xsd:3">
- <StandartBusinessDocumentHeader>
<HeaderVersion>Standard Business Header Version 1.3</HeaderVersion>
- <Sender>
<Identifier>GS1</Identifier>
- <ContactInformation>
<Contact>Turkey IT Support</Contact>
<EmailAddress>someone#example.com</EmailAddress>
<TelephoneNumber>00 13</TelephoneNumber>
<ContactTypeIdentifier>IT Support</ContactTypeIdentifier>
</ContactInformation>
</Sender>
</StandartBusinessDocumentHeader>
</inventory_report:inventoryReportMessage>
The second prefix ("sh") doesn't work. Can someone help me???
For serialization approach, you can define classes:
public class ContactInformation
{
[XmlElement(ElementName = "Contact")]
public string Contact { get; set; }
[XmlElement(ElementName = "EmailAddress")]
public string EmailAddress { get; set; }
[XmlElement(ElementName = "TelephoneNumber")]
public string TelephoneNumber { get; set; }
[XmlElement(ElementName = "ContactTypeIdentifier")]
public string ContactTypeIdentifier { get; set; }
}
public class Identifier
{
[XmlAttribute("Authority")]
public string Authority { get; set; }
[XmlText]
public string Value { get; set; }
}
public class Sender
{
[XmlElement(ElementName = "Identifier")]
public Identifier Identifier { get; set; }
[XmlElement(ElementName = "ContactInformation")]
public ContactInformation ContactInformation { get; set; }
}
public class StandartBusinessDocumentHeader
{
[XmlElement(ElementName = "HeaderVersion")]
public string HeaderVersion { get; set; }
[XmlElement(ElementName = "Sender")]
public Sender Sender { get; set; }
}
[XmlRoot(ElementName = "inventoryReportMessage", Namespace = "urn:gs1:ecom:inventory_report:xsd:3")]
public class InventoryReportMessage
{
[XmlElement("StandardBusinessDocumentHeader", Namespace = "http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader")]
public StandartBusinessDocumentHeader Header { get; set; }
}
then serialize those as below:
var report = new InventoryReportMessage
{
Header = new StandartBusinessDocumentHeader {
HeaderVersion = "Standard Business Header version 1.3",
Sender = new Sender
{
Identifier = new Identifier
{
Authority = "GS1",
Value = "0000"
},
ContactInformation = new ContactInformation
{
Contact = "some one",
EmailAddress = "someone#example.com",
TelephoneNumber = "00357",
ContactTypeIdentifier = "IT Support"
}
}
}
};
using (var stream = new MemoryStream())
{
using (var writer = new StreamWriter(stream))
{
var settings = new XmlWriterSettings {
Indent = true
};
using (var xmlWriter = XmlWriter.Create(writer, settings))
{
xmlWriter.WriteStartDocument(false);
var serializer = new XmlSerializer(typeof(InventoryReportMessage));
var namespaces = new XmlSerializerNamespaces();
namespaces.Add("inventory_report", "urn:gs1:ecom:inventory_report:xsd:3");
namespaces.Add("sh", "http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader");
namespaces.Add("ecom_common", "urn:gs1:ecom:ecom_common:xsd:3");
namespaces.Add("shared_common", "urn:gs1:shared:shared_common:xsd:3");
serializer.Serialize(xmlWriter, report, namespaces);
}
stream.Position = 0;
using (var reader = new StreamReader(stream))
{
Console.WriteLine(reader.ReadToEnd());
}
}
}
Console.ReadLine();
Using xml linq. I like to create a string header and then add dynamic values in code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string header =
"<inventory_report:inventoryReportMessage xmlns:inventory_report=\"urn:gs1:ecom:inventory_report:xsd:3\" xmlns:sh=\"http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader\" xmlns:ecom_common=\"urn:gs1:ecom:ecom_common:xsd:3\" xmlns:shared_common=\"urn:gs1:shared:shared_common:xsd:3\">" +
"<sh:StandardBusinessDocumentHeader>" +
"<sh:HeaderVersion>Standard Business Header version 1.3</sh:HeaderVersion>" +
"<sh:Sender>" +
"</sh:Sender>" +
"</sh:StandardBusinessDocumentHeader>" +
"</inventory_report:inventoryReportMessage>";
XDocument doc = XDocument.Parse(header);
XElement sender = doc.Descendants().Where(x => x.Name.LocalName == "Sender").FirstOrDefault();
XNamespace shNs = sender.GetNamespaceOfPrefix("sh");
sender.Add(new XElement(shNs + "Identifier", new object[] {
new XAttribute("Authority", "GS1"),
"0000"
}));
sender.Add( new XElement(shNs + "ContactInformation", new object[] {
new XElement(shNs + "Contact", "some one"),
new XElement(shNs + "EmailAddress", "someone#example.com"),
new XElement(shNs + "TelephoneNumber", "00357"),
new XElement(shNs + "ContactTypeOdemtofier", "IT Support")
}));
}
}
}

There is an error in XML document (1,2) , System.InvalidOperationException: <AuthorizationResult xlms:""> was not expected

XML sent from API
<AuthenticationResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<PAPIErrorCode>0</PAPIErrorCode>
<ErrorMessage/>
<AccessToken>StringAccessToken</AccessToken>
<AccessSecret>StringAccessToken</AccessSecret>
<PolarisUserID>PolarisSampleUser</PolarisUserID>
<BranchID>7</BranchID>
<AuthExpDate>2013-05-27T16:57:46.323</AuthExpDate>
</AuthenticationResult>
Classes for Response
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
namespace PAPIAutomatedTestingTool
{
[XmlRoot(ElementName="AuthorizationResult")]
public class AuthorizationResult
{
public int PAPIErrorCode { get; set; }
public string ErrorMessage { get; set; }
public string AccessToken { get; set; }
public string AccessSecret { get; set; }
public int PolarisUserID { get; set; }
public int BranchID { get; set; }
public DateTime AuthExpDate { get; set; }
}
}
Code making request and deserializing
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net;
using System.Web;
using System.Web.Script.Serialization;
using System.Security.Cryptography;
using System.Xml;
using System.Xml.Serialization;
namespace PAPIAutomatedTestingTool
{
public class APICallMethods
{
public string URI { get; set; }
public string accSecret { get; set; }
public string accToken { get; set; }
public string authorizationString { get; set; }
public bool AuthenticateStaffUser()
{
try
{
//Initializing all variables
string authReqMethod = "POST";
string authAccessKey = "Sample Access Key";
string authAccessKeyID = "Sample Access ID";
string authPatronPassword = "";
DateTime authDateTime = DateTime.Now;
string httpAuthDateTime = authDateTime.ToUniversalTime().ToString("r");
string authURI = "Sample URI";
//Composing the papiHash from the given parameters
string papiHash = GetPAPIHash(authAccessKey, authReqMethod, authURI, httpAuthDateTime, authPatronPassword);
//Formating the authorization string
string authorizationString = String.Format("Authorization: PWS {0}:{1}", authAccessKeyID, papiHash);
//Creating and defining the WebRequest
WebRequest req = WebRequest.Create(authURI);
req.Method = "POST";
req.Headers.Add("PolarisDate", httpAuthDateTime);
req.Headers.Add(authorizationString);
req.ContentType = "application/xml";
string requestBody = "<AuthenticationData><Domain>SampleDomain</Domain><Username>SampleUsername</Username><Password>SamplePassword</Password></AuthenticationData>";
byte[] reqBodyBytes = System.Text.Encoding.UTF8.GetBytes(requestBody);
req.ContentLength = reqBodyBytes.Length;
using (Stream requestStream = req.GetRequestStream())
{
requestStream.Write(reqBodyBytes, 0, reqBodyBytes.Length);
}
//Receiving the WebResponse
using (WebResponse resp = req.GetResponse())
{
AuthorizationResult firstResponse = new AuthorizationResult();
Stream respStream = resp.GetResponseStream();
StreamReader sr = new StreamReader(respStream);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(AuthorizationResult));
firstResponse = (AuthorizationResult)xmlSerializer.Deserialize(respStream);
Console.WriteLine("Authorization: PWS" + firstResponse.AccessSecret + ":" + firstResponse.AccessToken);
return true;
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
return false;
}
}
public string GetPAPIHash(string strAccessKey, string strHTTPMethod, string strURI, string strHTTPDate, string strPatronPassword)
{
byte[] secretBytes = UTF8Encoding.UTF8.GetBytes(strAccessKey);
HMACSHA1 hmac = new HMACSHA1(secretBytes);
byte[] dataBytes = null;
if (strPatronPassword.Length > 0)
{
dataBytes = UTF8Encoding.UTF8.GetBytes(strHTTPMethod + strURI + strHTTPDate + strPatronPassword);
}
else
{
dataBytes = UTF8Encoding.UTF8.GetBytes(strHTTPMethod + strURI + strHTTPDate);
}
byte[] computedHash = hmac.ComputeHash(dataBytes);
string computedHashString = Convert.ToBase64String(computedHash);
return computedHashString;
}
}
}
I am making a POST request to the API with a body that contains AuthorizationData. The API is supposed to return the xml to deserialize into firstresponse. I have received the xml(confirmed by printing to console) but i am receiving the There is an error in the XML Document(1,2) and <AuthorizationData xmlns=""> was not expected. Thanks for the help in advance.
It appears to be complaining about an unexpected root element and there is some confusion surrounding that elsewhere in your question.
In the question title you have <AuthorizationResult>
In the example XML response you have <AuthenticationResult>
In the C# you have [XmlRoot(ElementName="AuthorizationResult")]
At the end of your question you mention <AuthorizationData>
That's quite a few subtle variations on a theme.
Assuming the XML sample response is correct, you should change the C# to expect the root element to be <AuthenticationResult>...
[XmlRoot(ElementName="AuthenticationResult")]
public class AuthenticationResult
{
...
If you want to write a single deserialize for both schema and non-schema custom XMLs, you can turn off namespaces to avoid getting the 'There is an error in the XML Document(1,2)' error. But since the XmlReader expects a XML Schema, you should read it with StringReader class then use XmlReader object to remove custom namespaces.
//Namespaces
using System.IO;
using System.Xml.Serialization;
//Field
private static XmlSurrogates.Root _xmlSurrogates = new();
//Method
private static void DeserializeXml(string xml)
{
try
{
XmlSerializer serializer = new XmlSerializer(_xmlSurrogates.GetType());
using (StringReader reader = new StringReader(xml))
{
var xmlTextReader = new System.Xml.XmlTextReader(reader);
xmlTextReader.Namespaces = false;
_xmlSurrogates = (XmlSurrogates.Root)(serializer.Deserialize(xmlTextReader));
}
}
catch (Exception ex)
{
Log.Error($"There is an error while deserialize. Error: {ex.Message}");
}
}
//Root Model Example
public class XmlSurrogates
{
[XmlRoot(ElementName = "XMLROOTELEMENTNAMEHERE FOR THIS ITS root")]
public class Root
{
[XmlElement(ElementName = "Boo")] public Boo Boo { get; set; }
[XmlElement(ElementName = "Control")] public ClassName DeclareName { get; set; }
[XmlAttribute(AttributeName = "MainCode")] public string MainCode { get; set; }
[XmlAttribute(AttributeName = "Caption")] public string Caption { get; set; }
}
[XmlRoot(ElementName = "Boo")]
public class ElementAsClassName
{
[XmlAttribute(AttributeName = "Foo")] public string PropertyName { get; set; }
}
}

Categories