Can't Processing the XML response of a WCF service using XDocument - c#

I'm new to restful services and need help with a concern. I will be very grateful for any help you can give me, thanks.
I'm trying to implement a service operation that returns me my data in xml format.
[OperationContract]
[WebGet(UriTemplate = "/ObtenerRuc/{ruc}", ResponseFormat = WebMessageFormat.Xml)]
EmpresaData ObtenerRuc(string ruc);
[DataContract]
public class EmpresaData
{
[DataMember]
public string AD_COMPANY;
[DataMember]
public string AD_STREET;
[DataMember]
public string AD_CITY;
[DataMember]
public string AD_COUNTY;
[DataMember]
public string AD_PHONE;
[DataMember]
public string AD_E_MAIL;
[DataMember]
public string AD_TAX_ADMIN_NUM;
}
In the treatment client application receiving the data into an XDocument
ruc = XDocument.Load(new MemoryStream(e.Result));
and I get a xml file like this
My problem, when processing the XDocument
string ciudad = ruc.Descendants("EmpresaData")
.ElementAt(0).Element("AD_CITY").Value.ToString();
The system displays the following error me
Data from the root level is invalid. Line 1, position 1.
Why reason can’t process the XDocument?
If anyone knows a solution that can implemented please, thanks.

I've seen this error a few times in my own work, as I work with XML and JSON data a lot. It's likely to be an issue with the result you're getting back. If you can provide the XML string we can find the issue for you, but before you do check that you have valid XML headers, that you've got opening and closing elements in the XML string and that you've got no duplicate tags.

Related

DataContractSerializer returns null for all the variables when I try to deserialize

I have a problem where DataContractSerializer returns null for all my variable. It's like it doesn't see them or something. I'm using it to deserialize a json file into an object. I had it working for another json file that was using another class with 3 string attributes. This one is composed of 40 attributes mostly string and a few bool. I have been working on it for hours and I just can't seem to find what I'm doing wrong. I even tried it with only 1 string attribute and it still returned null. Here is a simplified version with only 1 string attribute and 1 bool attribute. Any advice is more than appreciated.
Thank you
Json :
[{"Proposal_x0020_Type":"Lite Proposal","BI_x0020_Criteria_x0020_1":true}]
Function that tries to deserialize the string:
public Proposal[] Deserializer(string jsonFile)
{
MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonFile));
DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(Proposal[]));
Proposal[] projectArr = (Proposal[])deserializer.ReadObject(ms);
Console.WriteLine(jsonFile);
Console.ReadLine();
return projectArr;
}
Class of the object that the deserializer should create:
namespace PMIS
{
[DataContract]
public class Proposal
{
[DataMember(Order = 0)]
public string Proposal_x0020_Type { get; set; }
[DataMember(Order = 1)]
public bool BI_x0020_Criteria_x0020_1 { get; set; }
}
}
I managed to find the problem by comparing the code of this Deserialization to a previous one that I had. The only difference was the name of the variables inside the Json file. The fact that they contain the Unicode for space (x00200) causes some problem inside the DataContractDeserializer. I believe that it is seeing it as space, so instead of seeing "Proposal_x0020_Type", it is seeing "Proposal_ _Type", but I'm not sure about it. Anyway, the solution was to remove x0020 from all the variables inside the Json file. After that it worked perfectly fine.

XmlDeserialize cdata and its siblings

I'm in the process of deserializing into C# objects a custom inflexible XML schema to traverse and migrate the data within.
A brief example:
<Source>
...
<Provider>
<![CDATA[read 1]]>
<Identifier><![CDATA[read 2]]></Identifier>
<IdentificationScheme><![CDATA[read 3]]></IdentificationScheme>
</Provider>
...
</Source>
I'm looking the deserialize the Provider element with the first CDATA element value, read 1, and it's sibling element values too, read 2 and read 3.
Using http://xmltocsharp.azurewebsites.net/ it produces the following objects:
[XmlRoot(ElementName = "Provider")]
public class Provider
{
[XmlElement(ElementName = "Identifier")]
public string Identifier { get; set; }
[XmlElement(ElementName = "IdentificationScheme")]
public string IdentificationScheme { get; set; }
}
[XmlRoot(ElementName = "Source")]
public class Source
{
[XmlElement(ElementName = "Provider")]
public Provider Provider { get; set; }
}
But it fails to account for the the CDATA value, in fact I think deserializing it like this the value would not be reachable.
I think this maybe also be related to the XmlDeserializer to use, I was planning on RestSpharp's (as it's a library to the website already) or System.Xml.Link.XDocument, but I'm not sure whether either can handle this scenario?
In my searches I couldn't find an example either, but stack did suggest this <!{CDATA[]]> and <ELEMENT> in a xml element that is precisely the same schema option.
Thanks so much for any help in advance,
EDIT 1
As far as I can tell the [XmlText] is the solution required, as pointed out in Marc Gravell's answer below, but it does not work/is implemented on RestSharp's XmlDeserializer, but further testing would be required to ascertain that for sure.
The CDATA is essentially just escaping syntax and is handled by most readers. What you are looking for is:
[XmlText]
public string WhateverThisIs { get; set; }
on the object that has raw content. By adding that to Provider, WhateverThisIs gets the value of "read 1". The other 2 properties already deserialize correctly as "read 2" and "read 3" without you having to do anything.
For reference, everything here would behave almost the same without the CDATA (there are some whitespace issues):
<Provider>
read 1
<Identifier>read 2</Identifier>
<IdentificationScheme>read 3</IdentificationScheme>
</Provider>

Deserialize XML Array Where Root is Array and Elements Dont Follow Conventions

The XML I am getting is provided by an outside source so I don't have the ability to easily reformat it. I would like to use xml attributes on my entities instead of having to write a linq query that knows how the XML and entity is formatted. Here is an example:
<?xml version="1.0"?>
<TERMS>
<TERM>
<ID>2013-2</ID>
<DESC>Spring 2013</DESC>
</TERM>
<TERM>
<ID>2013-3</ID>
<DESC>Summer 2013 Jun&Jul</DESC>
</TERM>
</TERMS>
I know the the XMLSerializer expects ArrayOfTerm instead of TERMS for example, but that I can tweak my entity to use a different element name with the xml attributes such as this:
public class TermData
{
[XmlArray("TERMS")]
[XmlArrayItem("TERM")]
public List<Term> terms;
}
public class Term
{
[XmlElement("ID")]
public string id;
[XmlElement("DESC")]
public string desc;
}
and I am deserializing the data like so:
TermData data;
XmlSerializer serializer = new XmlSerializer(typeof(TermData));
using (StringReader reader = new StringReader(xml))
{
data = (TermData)serializer.Deserialize(reader);
}
return View(data.terms);
The problem I am facing is that TERMS is the root and the array itself. If the XML were to have a root element that was not the array, I could edit my TermData class like so and it would deserialize correctly (already tested).
[XmlRoot("ROOT")]
public class TermData
{
[XmlArray("TERMS")]
[XmlArrayItem("TERM")]
public List<Term> terms;
}
Note that using TERMS as the XMLRoot does not work. Right now, my code is throwing
InvalidOperationException: There is an error in XML document (2,2).
InnerException: "<TERMS xmlns=" was not expected.
This would lead me to believe that the XML is not formatted correctly, but from my understanding the example I gave is perfectly valid XML.
This would all be trivial if I could edit the source xml, but there could be tons of other responses like this and I need to be able to flex for whatever I might get. What I'm trying to confirm is whether or not the XMLSerializer can support this type of XML structure. I've tested just about everything and can't get it deserialize without editing the XML. It would also be convenient if I didn't have to define a wrapper class (TermData) to hold the list, but this seems to only work if the xml follows the naming conventions for the serializer (ArrayOfTerm, etc).
Maybe you can try :
[XmlRoot("TERMS")]
public class TermData
{
public TermData()
{
terms = new List<Term>();
}
[XmlElement("TERM")]
public List<Term> terms{get;set;}
}
public class Term
{
[XmlElement("ID")]
public string id{get;set;}
[XmlElement("DESC")]
public string desc{get;set;}
}
Hope this will help,

Best way to consume xml feed in asp.net MVC (c#)

I have an MVC website that, when you click a button, will use Get method to grab xml data from another website. I need to then display part of this XML in my webpage.
My current approach is to deserialize the XML into objects, and pass the objects into the View, which will then grab the appropriate data.
My problem is that my classes don't match the XML data entirely (it doesn't have every element/attribute/etc). The data is too long, with too many elements and attributes, so I don't want to write everything to the classes. And I couldn't create classes from the XML data using XSD.exe because of some error in the data (though the xml data works fine when my webpage is reading it).
Is there a more efficient way of doing this?
Read in this link that IXmlSerializable might be away, although the comments also noted some problems with it. And it seems like it might be quite complicated.
How to deserialize only part of an XML document in C#
Your help is much appreciated. Thanks!
Use framework to consume Atom feeds. See the following: System.ServiceModel.Syndication namespace - msdn.microsoft.com/en-us/library/system.servicemodel.syndication.aspx
Instead of directly deserializing the atom feed xml into objects first load the xml into the XDocument object and then query the XDocument object using XLinq and create the necessary ViewModel that need to be passed to the view.
For ex.
View Model
public class FeedViewModel
{
..
public FeedItem[] FeedItems { get; set; }
}
public class FeedItem
{
public string Title { get; set; }
public string Description { get; set; }
public DateTime Date { get; set; }
}
In your action
var feedDocument = XDocument.Load(feedUrl);
var feedItems = feedDocument.Descendants("item")
orderby DateTime.Parse(feed.Element("pubDate").Value) descending
select new FeedItem
{
Title = feed.Element("title").Value,
Description = feed.Element("description").Value,
Date = DateTime.Parse(feed.Element("pubDate").Value)
}.ToArray();
return View(new FeedViewModel{ FeedItems = feedItems });
http://deepumi.wordpress.com/2010/02/21/how-to-consume-an-atom-rss-feed-using-asp-net-c-with-linq/

Testing the Deserialization of RestSharp without proper REST-Api

EDIT: The solution to the question can be found in the first comment by John Sheehan!
i would like to use Restsharp as Rest-Client for my Project. Since the REST server is not running yet, I would like to test the client without the Server. My main focus is on the deserialization of the returning XML-Response. Is it possible to deserialize XML using RestSharp without a proper RestSharp.RestResponse?
I tried it like this:
public void testDeserialization()
{
XmlDeserializer d = new XmlDeserializer();
RestSharp.RestResponse response = new RestSharp.RestResponse();
string XML = #"<Response><Item1>Some text</Item1><Item2>Another text</Item2><Item3>Even more text</Item3></Response>";
response.Content = XML;
d.RootElement = "Response";
Response r = d.Deserialize<Response>(response);
}
public class Response
{
public string Item1 { get; set; }
public string Item2 { get; set; }
public string Item3 { get; set; }
}
The deserializations creates an Object of the Response-Class, where every field is null. Is there a way to test if (and how) any given xml would be deserialized by RestSharp?
Edit: For better readability - this is the XML i'm using:
<Response>
<Item1>Some text</Item1>
<Item2>Another text</Item2>
<Item3>Even more text</Item3>
</Response>
I hope I'm doing this right - but to make clear this question is solved, i'm copying the solutions (from the comments by John Sheehan):
You shouldn't have to specify RootElement. That's only for when the
root isn't at the top level. Try that and let me know if it works.
Here's how we test the deserializer for the project:
https://github.com/restsharp/RestSharp/blob/master/RestSharp.Tests/XmlDeserializerTests.cs
(EDIT: Updated link to correct file)

Categories

Resources