Does RESTSharp have XML deserialization issues, including byte marking?

There is a public web service that I want to use in a short C # application: http://ws.parlament.ch/

The returned XML from this web service has a โ€œspecificationโ€ at first, which causes RESTSharp to complete XML deserialization with the following error message:

Error receiving response. Check internal data for more information. ---> System.Xml.XmlException: Data at the root level is not valid. Line 1, position 1. in System.Xml.XmlTextReaderImpl.Throw (exception e)
in System.Xml.XmlTextReaderImpl.Throw (String res, String arg) in System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace () at System.Xml.XmlTextReaderImpl.ParseDocumentContent () in System.Xml.XmlTextReaderImpl.Xml (). Linq.XDocument.Load (XmlReader reader, LoadOptions parameters) in System.Xml.Linq.XDocument.Parse (line text, LoadOptions parameters)
in System.Xml.Linq.XDocument.Parse (string text) in RestSharp.Deserializers.XmlDeserializer.Deserialize [T] (IRestResponse response) in RestSharp.RestClient.Deserialize [T] (IRestRequest request, IRestResponse raw)
--- End of internal exception stack trace ---

Here is a simple example using http://ws.parlament.ch/sessions?format=xml to get a list of "sessions":

public class Session { public int Id { get; set; } public DateTime? Updated { get; set; } public int? Code { get; set; } public DateTime? From { get; set; } public string Name { get; set; } public DateTime? To { get; set; } } static void Main(string[] args) { var request = new RestRequest(); request.RequestFormat = DataFormat.Xml; request.Resource = "sessions"; request.AddParameter("format", "xml"); var client = new RestClient("http://ws.parlament.ch/"); var response = client.Execute<List<Session>>(request); if (response.ErrorException != null) { const string message = "Error retrieving response. Check inner details for more info."; var ex = new ApplicationException(message, response.ErrorException); Console.WriteLine(ex); } List<Session> test = response.Data; Console.Read(); } 

When I first process the returned xml with Fiddler to remove the first 3 bits ("specification"), the above code works! Can someone please help me deal with this right in RESTSharp? What am I doing wrong? THANKS in advance!

+7
source share
4 answers

I found a solution - Thanks @arootbeer for the tips!

Instead of wrapping the XMLDeserializer, you can also use the "RestRequest.OnBeforeDeserialization" event from #RESTSharp. So you just need to insert something like this after the new RestRequest () (see the example of my source code), and then it works great!

 request.OnBeforeDeserialization = resp => { //remove the first ByteOrderMark //see: http://stackoverflow.com/questions/19663100/restsharp-has-problems-deserializing-xml-including-byte-order-mark string byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble()); if (resp.Content.StartsWith(byteOrderMarkUtf8)) resp.Content = resp.Content.Remove(0, byteOrderMarkUtf8.Length); }; 
+7
source

I had the same problem, but not specifically with RestSharp. Use this:

 var responseXml = new UTF8Encoding(false).GetString(bytes); 

Original discussion: XmlReader breaks into UTF-8 specification

Relevant quote from the answer:

The xml line should not contain (!) A specification, the specification is allowed only in byte data (for example, streams), which is encoded using UTF-8. This is because the string representation is not encoded, but rather a sequence of Unicode characters.

Edit: Looking through your documents, this looks like the easiest way to handle this (except for the issue with GitHub) - call the non-generic Execute() method and deserialize the response from this line. You can also create an IDeserializer that wraps the default XML deserializer.

+2
source

To make it work with RestSharp, you can manually analyze the contents of the response and delete all the "funny" characters that precede the "<".

 var firstChar = responseContent[0]; // removing any 'funny' characters coming before '<' while (firstChar != 60) { responseContent= responseContent.Remove(0, 1); firstChar = responseContent[0]; } XmlReader.Create(new StringReader(responseContent)); 
0
source

The solution posted by @dataCore doesn't quite work, but it should.

 request.OnBeforeDeserialization = resp => { if (resp.RawBytes.Length >= 3 && resp.RawBytes[0] == 0xEF && resp.RawBytes[1] == 0xBB && resp.RawBytes[2] == 0xBF) { // Copy the data but with the UTF-8 BOM removed. var newData = new byte[resp.RawBytes.Length - 3]; Buffer.BlockCopy(resp.RawBytes, 3, newData, 0, newData.Length); resp.RawBytes = newData; // Force re-conversion to string on next access resp.Content = null; } }; 

If resp.Content null resp.Content set to null resp.Content , then this is protective RawBytes , because RawBytes converted to a string only if Content is not already set.

0
source

Source: https://habr.com/ru/post/956958/


All Articles