Read Elements from XML in c# - 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);
}

Related

How to parse MTOM soap response in 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;
}

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

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")
}));
}
}
}

Prefixes and Namespaces with C# Objects

I am attempting to create a POST function that serialises C# class objects into XML.
The part I am having great difficulty with is adding namespace prefixes to the sub-root element's children, so in this instance, contact children only.
The only way I seem to be able to get the prefix onto the child elements of contactis to add them through SerializerNamespace class, however I can only get this to attach to the root element, CreateContact.
How can I achieve this?
XML Currently Produced:
<?xml version=\"1.0\"?>
<CreateContact xmlns:a="http://foo.co.uk/Contact" xmlns="http://foo.co.uk">
<a:contact>
<a:Email>stest#gmail.com</a:Email>
<a:FirstName>Simon</a:FirstName>
<a:LastName>Test</a:LastName>
<a:Phone>09088408501</a:Phone>
<a:Title>Mr</a:Title>
</a:contact>
</CreateContact>
Serialisation function:
public static void CreateContact(Contact contact)
{
string tmp = url;
string xml = "";
string result = "";
XmlDocument xd = new XmlDocument();
var cc = new CreateContact();
cc.contact = contact;
var xs = new XmlSerializer(cc.GetType());
XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
xsn.Add("a", "http://foo.co.uk/Contact");
using (MemoryStream ms = new MemoryStream())
{
xs.Serialize(ms, cc, xsn);
ms.Position = 0;
xd.Load(ms);
xml = xd.InnerXml;
}
using (WebClient web = new WebClient())
{
web.Credentials = new NetworkCredential(username, password);
web.Headers.Add("Content-Type", "application/xml");
try
{
result = web.UploadString(tmp, "POST", xml);
}
catch (WebException ex)
{
}
}
}
XML Class Constructs:
[Serializable()]
[XmlRoot(ElementName = "CreateContact", Namespace = "http://foo.co.uk")]
public class CreateContact
{
[XmlElement(ElementName = "contact", Namespace = "http://foo.co.uk/Contact")]
public Contact contact { get; set; }
}
[DataContract(Name = "Contact", Namespace = "http://foo.co.uk/Contact")]
[XmlType("a")]
public class Contact
{
[XmlElement(ElementName = "Email", Namespace = "http://foo.co.uk/Contact")]
[DataMember(Name = "Email")]
public string Email { get; set; }
[XmlElement(ElementName = "FirstName", Namespace = "http://foo.co.uk/Contact")]
[DataMember(Name = "FirstName")]
public string Firstname { get; set; }
[XmlElement(ElementName = "LastName", Namespace = "http://foo.co.uk/Contact")]
[DataMember(Name = "LastName")]
public string Lastname { get; set; }
[XmlElement(ElementName = "Phone", Namespace = "http://foo.co.uk/Contact")]
[DataMember(Name = "Phone")]
public string Phone { get; set; }
[XmlElement(ElementName = "Title", Namespace = "http://foo.co.uk/Contact")]
[DataMember(Name = "Title")]
public string Title { get; set; }
}
XML Desired:
<?xml version=\"1.0\"?>
<CreateContact xmlns="http://foo.co.uk">
<contact xmlns:a="http://foo.co.uk/Contact">
<a:Email>stest#gmail.com</a:Email>
<a:FirstName>Simon</a:FirstName>
<a:LastName>Test</a:LastName>
<a:Phone>09088408501</a:Phone>
<a:Title>Mr</a:Title>
</contact>
</CreateContact>
As alluded in the comments, the reason for the difference is that contact should be in the namespace http://foo.co.uk, not http://foo.co.uk/Contact.
As an aside, a couple of further comments:
You probably don't need the DataMember attributes, unless you're using DataContractSerializer somewhere else.
Most of the Xml* attributes are superfluous here, and could be removed or consolidated by inheriting from XmlRoot.
If all you need is the XML string, you'd be better off serialising to something like a StringWriter rather than to a stream and then loading into the DOM just to get the text (see this question if you need the XML declaration to specify utf-8)
So, you'd get the XML as below:
var xsn = new XmlSerializerNamespaces();
xsn.Add("a", "http://foo.co.uk/Contact");
var xs = new XmlSerializer(typeof(CreateContact));
using (var stringWriter = new StringWriter())
{
xs.Serialize(stringWriter, cc, xsn);
xml = stringWriter.ToString();
}
With your classes defined as:
[XmlRoot(ElementName = "CreateContact", Namespace = "http://foo.co.uk")]
public class CreateContact
{
[XmlElement(ElementName = "contact")]
public Contact Contact { get; set; }
}
[XmlRoot("contact", Namespace = "http://foo.co.uk/Contact")]
public class Contact
{
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Title { get; set; }
}
See this fiddle for the complete example.

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