Testing the Deserialization of RestSharp without proper REST-Api - c#

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)

Related

How can I loop through the JSON on Universal Windows Platform with C#

I am developing an app on UWP.
When I connect with a server api and I get the next response I don't have problems.
{"value":"Login successfull","sessionId":"a95077855b05ed0fec5d7fa3abafa126e15aba2a"}
I can get information in the following way:
JsonObject jsonObject = JsonObject.Parse(jsonString);
string token = jsonObject["sessionId"].GetString();
string value = jsonObject["value"].GetString();
but my problem is when i get the next response of the api:
[{"person":{"name":"name1","country":"Spain","city":"user_city","phone":null}},{"person":{"name":"name2","country":"Turkey","city":"user_city","phone":"1111111"}},{"person":{"name":"name3","country":"Argentina","city":"user_city","phone":"22222"}},{"person":{"name":"name4","country":"Argentina","city":"user_city","phone":"33333"}}]
How can I loop through the JSON and get all the people that match a condition?
I have to do with "Windows.Data.Json"
If interested in a solution using only Windows.Data.Json namespace, here it is:
var rootValue = JsonValue.Parse(jsonString);
foreach (var item in rootValue.GetArray())
{
var unamedObject = item.GetObject();
var personObject = unamedObject["person"].GetObject();
System.Diagnostics.Debug.WriteLine(personObject["name"].GetString());
System.Diagnostics.Debug.WriteLine(personObject["country"].GetString());
System.Diagnostics.Debug.WriteLine(personObject["city"].GetString());
System.Diagnostics.Debug.WriteLine(personObject["phone"].GetString());
}
Why would somebody pick Windows.Data.Json over Newtonsoft's Json.net?
If your JSON needs are simple, you can reduce the size of your app ~1 MB by choosing Windows.Data.Json because it is part of the operating system.
I would recommend you try out Json.net nuget package and deserialise the json payload to classes through that.
A good tutorial can be found here: http://windowsapptutorials.com/windows-phone/general/deserialize-json-data-using-newtonsoft-json-net-library/
But if you search you'll find more.
In short, you first copy paste your json and use Visual Studio > File > Paste Special > To paste to classes ( first open an empty cs file and set your cursor inside it ).
After that you use JsonConvert.DeserializeObject<RootObject>() to actually parse the json string.
Once parsed you'll have an array of items if your original json also defined an array.
Note RootObject is the first class object in the generated classes in Visual Studio
There are ways to do it without external libraries, if that is the real reason for the stipulation of Windows.Data.Json.
I'd likely do it something like this...
First I'd make some classes representing the returning JSON:
public class RootObject
{
public Person person { get; set; }
}
public class Person
{
public string name { get; set; }
public string country { get; set; }
public string city { get; set; }
public string phone { get; set; }
}
Then add a little method to deserialize:
public static T Deserialize<T>(string json)
{
var bytes = Encoding.Unicode.GetBytes(json);
using (var ms = new MemoryStream(bytes))
{
var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
return (T)serializer.ReadObject(ms);
}
}
And finally deserialize and query that result like so:
var persons = Json.Deserialize<List<RootObject>>(textBox.Text);
var peeps = (from p in persons
where p.person.name.StartsWith("name")
select p).ToList();

JSON Deserialization Type is not supported for deserialization of an array

I've read two other posts regarding the deserialization error, but I've not gotten anywhere so I'm posting my own question.
I have a WCF service that's returning JSON. Upon deserialization of a specific type, it fails.
In an effort to allow you to easily replicate the error, I've hardcoded the JSON below along with the call.
Essentially you should be able to copy/paste the code below and see it fail.
The consumer needs to deserialize this into a working object. s.Deserialize fails with the error message noted in the Title.
NOTE: I realize there are slashes in my JSON. Those are there for convenience to escape the quotes. Thanks.
Example code:
var s = new JavaScriptSerializer();
var jstr =
"[{\"UserId\":1,\"WorkoutId\":1,\"WorkoutInfo\":[\"Step 1\",\"Step 2\"]},{\"UserId\":2,\"WorkoutId\":2,\"WorkoutInfo\":[\"Step 1a\",\"Step 2a\"]},{\"UserId\":5,\"WorkoutId\":0,\"WorkoutInfo\":[\"new work1\",\"new work 1\",\"new work 1\"]}]";
Workout blah = s.Deserialize<Workout>(jstr);
var response = ServicePOST<Workout>("AddUserWorkout", workout);
and Workout class:
public class Workout
{
public int UserId { get; set; }
public List<string> WorkoutInfo { get; set; }
}
The problem is that you're telling the serializer that it's just a single Workout, not a list/array of them. This works:
var blah = s.Deserialize<List<Workout>>(jstr);
This isn't directly related to your question, but if at all possible, I'd recommend that you use Json.NET instead of JavaScriptSerializer.

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

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.

RestSharp Deserialize returns empty properties but xml.deserialize test works

EDIT : the moment I asked the question I thougt of trying something..
I've set XmlNamespace property on the request and that did the trick..
request.XmlNamespace = "http://musicbrainz.org/ns/mmd-2.0#";
But I don't really understand as to why...
Next problem is getting RestSharp to recognize xml atributes as object properties
I've been going over this for the most of the weekend and I just don't get it to work.
I'm trying to write a wrapper round a RestFul webservice (MusicBrainz). I'm testing with a simple example : get details of one artist and put it in a custom Artist object.
When I do a Execute on the RestClient it ends ok but my object properties are null..
But when I test the deserialization with the XmlDeserializer the objectproperties are filled (But not for properties that correspond to an attribute, but I'll tackle that later)
What happens between deserialization of the response and putting the object in response.data ?
Quite possible it is a "newbie" error I'm making as this are my first steps with RestSharp..
Help would be much appreciated..
Returnded xml :
<metadata>
<artist type="Group" id="f1548c5b-329e-4036-921c-02213a04b525">
<name>Uriah Heep</name>
<sort-name>Uriah Heep</sort-name>
<country>GB</country>
<life-span>
<begin>1970</begin>
</life-span>
</artist>
</metadata>
My class :
public class Artist
{
public int Id { get; set; }
public string Type { get; set; }
public string Name { get; set; }
public string SortName { get; set; }
public string Country { get; set; }
}
In the following code output properties are filled
var output = xml.Deserialize<Artist>(response);
But the same response does not fill properties when calling
var response = client.Execute<T>(request);
Complete code (I've put the test code in the generic method for sake of simplicity) :
public T Execute<T>(RestRequest request) where T : new()
{
var client = new RestClient();
client.BaseUrl = BaseUrl;
client.Authenticator = null;
//does not fill properties
var response = client.Execute<T>(request);
if (response.ErrorException != null)
{
throw response.ErrorException;
}
var xml = new XmlDeserializer();
//fills properties
var output = xml.Deserialize<Artist>(response);
return response.Data;
}
This happens because Execute method, after receiving response, tries to negotiate it based on the request's RootElement and XmlNamespace properties and copies them to the XmlDeserializer.
Here's a code from RestClient:
handler.RootElement = request.RootElement;
handler.DateFormat = request.DateFormat;
handler.Namespace = request.XmlNamespace;
response.Data = handler.Deserialize<T>(raw);
If you pass a RestRequest with a mismatching XmlNamespace, RestSharp's XmlDeserializer (that uses XDocument behind the scenes) won't be able to map response XML to an object properties and you will get default/null values instead.
Now for default implementation (when you create XmlDeserializer manually), if you don't set a XmlNamespace, deserializer will do an auto-detection that basically ignores all namespaces in the response and maps all properties only by their names.
See source code from XmlDeserializer:
// autodetect xml namespace
if (!Namespace.HasValue())
{
RemoveNamespace(doc);
}
Taking all above into account, it's clear why it started working after you explicitly set XmlNamespace property to a matching namespace in your request object with this line:
request.XmlNamespace = "http://musicbrainz.org/ns/mmd-2.0#";
Execute method copied namespace into deserializer and it mapped XML to object appropriately.

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/

Categories

Resources