C# + Querying XML with LINQ - c#

I'm learning to use LINQ. I have seen some videos online that have really impressed me. In an effort to learn LINQ myself, I decided to try to write a query to the NOAA web service. If you put "http://www.weather.gov/forecasts/xml/sample_products/browser_interface/ndfdBrowserClientByDay.php?zipCodeList=20001&format=24+hourly&startDate=2010-06-10&numDays=5" in your browser's address bar, you will see some XML. I have successfully retrieved that XML in a C# program. I am loading the XML into a LINQable entity by doing the following:
string xml = QueryWeatherService();
XDocument weather = XDocument.Parse(xml);
I have a class called DailyForecast defined as follows:
public class DailyForecast
{
public float HighTemperature { get; set; }
public float LowTemperature { get; set; }
public float PrecipitationPossibility { get; set; }
public string WeatherSummary { get; set; }
}
I'm trying write a LINQ query that adheres to the structure of my DailyForecast class. At this time, I've only gotten to this far:
var results = from day in response.Descendants("parameters")
select day;
Not very far I know. Because of the structure of the XML returned, I'm not sure it is possible to solely use a LINQ query. I think the only way to do this is via a loop and traverse the XML. I'm seeking someone to correct me if I'm wrong. Can someone please tell me if I can get results using purely LINQ that adhere to the structure of the DailyForecast class? If so, how?
Thank you!

Since your xml may return multiple records,
var results = from day in response.Descendants("parameters")
select new DailyForecast()
{
HighTemperature = day.Element("param name corresponding to high temp"),
};
return result.ToList(); //or any type of collection you want to return

Related

Converting JSON data into an object

I am very new to this.Pardon me if I make any mistakes.
I have data in JSON form.Can I read this data directly and use it in C# code ?
From what I understood from reading up on the internet,I think I have to convert it into an object form to use the data.Am I right ?
If yes,Then I saw this method to convert as below :
string data = JsonConvert.DeserializeObject<string>(getmyissue());
getmyissue is the function which returns a string which has data in json format.
This gives me an exception saying
"Error reading string.Unexpected Token."
Can someone guide me where am I going wrong ?
EDIT
MyIssue.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Example
{
public class MyIssue
{
public string name{get;set;}
public string description { get; set; }
public string created { get;set; }
public string updated{get;set;}
public string displayName { get; set; }
}
}
Program.cs
MyIssue obj=null;
try
{
obj = JsonConvert.DeserializeObject<MyIssue>(manager.getmyissue());
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
Console.WriteLine("Name: "+obj.name);
The easiest way to de-serialize Json in a C#/.NET program is to use the brilliant NewtonSoft JSON library.
There are numerous ways to do it, but I have to admit that the NS libs just get on with the task (and no I'm not a member of the team etc, just an Avid User :-) ).
To do what you want for example, if you had:
{'Name': 'A person', 'AllowAccess': true,'Areas': ['Sales','Admin']}
You would first build an object to represent it as follows:
public MyObject
{
public string Name { get; set; }
public bool AllowAccess { get; set; }
public List<string> Areas { get; set; }
}
Once you've done this, it's a simple case of just doing the following:
string jsonString = "// Your json formated string data goes here";
MyObject myObject = JsonConvert.DeserializeObject<MyObject>(jsonString);
The properties in your object should at that point, reflect the properties in the JSON data you sent to it.
You will of course need to add the NS JSON Libs to your project, either via NuGet or Manually, which ever is easier for you, everything you need to know about that is here:
How to install JSON.NET using NuGet?
The really good thing about NS JSON however is not the ease of use, but the fact that it can also do dynamic de-serialization.
This comes in handy if you've no idea what to expect in the JSON you receive, and so don't know ahead of time how to construct an object to hold the results.
Rather than repeat what others have said however, you can find more information of doing things dynamically in this stack overflow post:
Deserializing JSON using JSon.NET with dynamic data
Update
Looking at your JSON data you have way more fields/properties in there than your trying to parse, and none of the libraries in common use (To the best of my knowledge) will pick and choose the fields to copy, you either have an object that represents them all, or not at all, the later of which I believe is the problem your facing.
I have a rather neat "JSON" plug in for chrome, than when given a chunk of JSON data formats the output for me nicely and makes it easy to read, it also helps massively when defining objects, allowing you to see the full nested structure of your data, here are a series of images showing your JSON data formatted using this plugin:
I'm not going to paste anymore images in, but that goes on for another 4 pages!!
Now, some extra information that may help you.
I know from experience (I had to write a parser in PHP for these Jira webhooks) that within the Jira control panel, you can configure your webhooks to ONLY return the information your interested in.
Right now, it looks like you've just told the system to dump everything, for every event that you've hooked too (Which looks like - all of them), it's been a while since I did any work with these, but as well as a global webhook, you also have individual webhooks, which only fire on specific events and produce JSON data that's very much smaller than what your dealing with here.
I'd therefore advise you, to take a look in your Jira control panel (Or ask your Admin/Lead Dev/etc to take a look) and seriously trim down as much of that data as you can.
Further more, if memory serves me right, you can also make various web API calls to the Jira service to get this info too, and in that case you can tell the API exactly what your interested in, meaning it will only return the fields you need.
Right now, your main problem is the sheer volume of data your trying to deal with, if you tackle that problem, you'll find the issues surrounding the code your trying to get working will be very much easier to deal with.
Update 2
Just to make it clearer what I mean by using a "dynamic" type to get at your data, you would use something like the following code:
string jsonString = "// Your json formated string data goes here";
var result = JsonConvert.DeserializeObject<dynamic>(jsonString);
The difference here is that your using the C# dynamic type rather than a strongly typed object of your own design.
"dynamic" is useful, because it's kind of like having an empty object, and then having the properties added for you, without you having to define it.
What this essentially means is that, if you pass in the following JSON:
{'Name': 'A person', 'AllowAccess': true,'Areas': ['Sales','Admin']}
You'll end up with a dynamic object that looks like:
result = dynamic
{
public string Name { get; set; }
public bool AllowAccess { get; set; }
public List<string> Areas { get; set; }
}
thus:
result.Name
will get you access to the contents of the Name field and so on.
If your JSON was then changed to become:
{'Name': 'A person', 'AllowAccess': true,'Areas': ['Sales','Admin'], 'Location': 'The World' }
Your object would magically have a property called 'Location' containing the value 'The World' which you could access using:
result.Location
In your case, this would allow you to define your concrete object EG:
public MyObject
{
public string Name { get; set; }
public string Email { get; set; }
}
and then do something like the following (Assuming that your inbound JSON had properties in called Name & Email):
string jsonString = "// Your json formated string data goes here";
var result = JsonConvert.DeserializeObject<dynamic>(jsonString);
MyObject myObject = new MyObject
{
Name = result.Name,
Email = result.Email
}
You'd then discard the dynamic object as you'd not need it anymore.
The BIG problem your going to have with this approach is maintaining your models. Manual property assignment is all fine and dandy for a small handful of properties and objects, but it soon becomes a huge maintenance nightmare as your software grows.
I'm sure it doesn't take much to imagine what kind of task you'd be facing if you had to do this for 100 different JSON requests and 50 different types of objects.
For this reason, using this approach you should really consider using some kind of mapping technology such as "AutoMapper", however for now I'm going to advise you leave that until later before you start researching it, as it'll not help you to be clear about dealing with this dynamic approach.
The JSON you get is already a string, so converting it to string doesn't make much sense. You need to create classes that reflect the structure represented by the JSON string.
For example to convert the following JSON into objects, you'd have to create a class for the users:
{"user":{"name":"asdf","teamname":"b","email":"c","players":["1","2"]}}
public class User
{
public string name { get; set; }
public string teamname { get; set; }
public string email { get; set; }
public Array players { get; set; }
}
Then you should be able to use this:
JavaScriptSerializer jss= new JavaScriptSerializer();
List<User> users = jss.Deserialize<List<User>>(jsonResponse);

How to get SOQL inner query as strongly-typed object (C#)

I'm new to Salesforce development, and trying to figure out SOQL stuff. Long time listener, first time caller.
I am running a SOQL query on ActivityHistories, and attempting to get it as a custom object. I need to do this so I can bind the data to an ASP.Net datagrid. Unfortunately, the dynamic type won't work for me, because I can't bind that to the grid.
Here is my query:
var activities = await client.QueryAsync<Activity>(#"SELECT (SELECT ActivityDate, Description
FROM ActivityHistories
ORDER BY ActivityDate DESC NULLS LAST, LastModifiedDate DESC LIMIT 500)
FROM Account
WHERE Id = '" + SalesforceId + "' LIMIT 1");
And here's the custom data type I want to use
public class Activity
{
public DateTime ActivityDate { get; set; }
public string Description { get; set; }
}
When I run this request and bind the activities.records to the datagrid, I simply get no data. The headers for the columns appear, but I don't get any of the records that are supposed to be there. Even debugging doesn't provide any additional information, it just looks like I got a blank object back. However, when I run the same query and replace Activity with dynamic, I get a whole bunch of Json that does contain everything I'm looking for.
At first, I thought maybe the deserialization into my custom object was the problem, but I did a very similar thing with Opportunity, and it works just fine, automatically converting to that custom object. This leads me to believe I'm handling something with the inner query incorrectly, and I would greatly appreciate any direction.
Here's a short summary of stuff I have read and attempted:
http://www.salesforce.com/developer/docs/api/Content/sforce_api_objects_activityhistory.htm
https://salesforce.stackexchange.com/questions/48800/getting-object-type-not-accessible-error/56513#56513
Salesforce Apex - Populating an object from SOQL query
Tried filling out more fields in Activity to correspond with the stuff coming from the query
Tried adjusting field types to correspond or not correspond with Activity
Generalized Google searches of anything related to converting dynamic to strong types (that didn't end well)
Requesting different, varying fields in the query, but finally landed on these two since these are the fields in the Salesforce documentation (link 1 above)
Thank you in advance!
Under the hood, the Salesforce API is a collection of JSON services. The DeveloperForce toolkit (which you appear to be using) is not seeing a structure in your result object that matches the JSON object returned. This is because the nested query returns an object which has multiple levels of nested objects. Something like this:
Result of Query
Account
Result of Activity History Query
List of Activity History Records
The serialization library has taken care of the first and second levels for you. You now have to provide an object to de-serialize into which can accommodate the third and fourth levels.
I did some testing with similar code and found a hierarchy like this should work:
public class ActivityQueryContainer
{
public Dictionary<string, string> Attributes { get; set; }
public ActivityHistoryResult ActivityHistories { get; set; }
}
public class ActivityHistoryResult
{
public Activity[] Records { get; set; }
}
public class Activity
{
public DateTime ActivityDate { get; set; }
public string Description { get; set; }
}
You can then change your API call to look like this:
var activities = await client.QueryAsync<ActivityQueryContainer>(#"SELECT (SELECT
ActivityDate, Description FROM ActivityHistories ORDER BY ActivityDate DESC NULLS LAST,
LastModifiedDate DESC LIMIT 500) FROM Account WHERE Id = '" + SalesforceId + "' LIMIT 1");
You can always cast the result to a type "object" which will return the JSON string, use a tool such as http://json2csharp.com/ to create the model for you.

ResponstDTO with complex Property in ServiceStack

Havin a Response with a complex property, i want to to map to my responseDTO properly. For all basic types it works out flawlessly.
The ResponseDTO looks like this:
public class ResponseDto
{
public string Id {
get;
set;
}
public struct Refs
{
public Genre GenreDto {
get;
set;
}
public Location LocationDto {
get;
set;
}
}
public Refs References {
get;
set;
}
}
Genre and Location are both for now simple classes with simple properties (int/string)
public class GenreDto {
public string Id {
get;
set;
}
public string Name {
get;
set;
}
}
Question:
Is there any way, without changing/replacing the generic unserializer ( and more specific example) (in this example JSON ) to map such complex properties?
One specific difference to the GithubResponse example is, that i cant use a dictionry of one type, since i have different types under references. Thats why i use a struct, but this seems not to work. Maybe only IEnumerable are allowed?
Update
There is a way using lamda expressins to parse the json manually github.com/ServiceStack/ServiceStack.Text/blob/master/tests/ServiceStack.Text.Tests/UseCases/CentroidTests.cs#L136 but i would really like to avoid this, since the ResponseDTO becomes kinda useless this way - since when writing this kind of manual mapping i would no longer us Automapper to map from ResponseDto to DomainModel - i though like this abstraction and "seperation".
Thanks
I used lambda expressions to solve this issue, a more complex example would be
static public Func<JsonObject,Cart> fromJson = cart => new Cart(new CartDto {
Id = cart.Get<string>("id"),
SelectedDeliveryId = cart.Get<string>("selectedDeliveryId"),
SelectedPaymentId = cart.Get<string>("selectedPaymentId"),
Amount = cart.Get<float>("selectedPaymentId"),
AddressBilling = cart.Object("references").ArrayObjects("address_billing").FirstOrDefault().ConvertTo(AddressDto.fromJson),
AddressDelivery = cart.Object("references").ArrayObjects("address_delivery").FirstOrDefault().ConvertTo(AddressDto.fromJson),
AvailableShippingTypes = cart.Object("references").ArrayObjects("delivery").ConvertAll(ShippingTypeDto.fromJson),
AvailablePaypmentTypes = cart.Object("references").ArrayObjects("payment").ConvertAll(PaymentOptionDto.fromJson),
Tickets = cart.Object("references").ArrayObjects("ticket").ConvertAll(TicketDto.fromJson)
});
So this lamda exprpession is used to parse the JsonObject response of the request and map everything inside, even nested ressources. This works out very well and flexible
Some time ago i stumbled upon a similar problem. Actually ServiceStack works well with complex properties. The problem in my scenario was that i was fetching data from a database and was passing the objects returned from the DB provider directly to ServiceStack. The solution was to either create DTOs out of the models returned by the DB provider or invoke .ToList() on those same models.
I'm just sharing some experience with SS but may be you can specify what's not working for you. Is there an exception thrown or something else.

MVC API: Structuring XML Response with child elements

Very new to MVC. I am currently writing an API and have a strict format that I need the XML to be returned in.
At the moment, I am using my EntityModel to expose my SQL Stored procedure. I have then created an Complex Type for the SP.
I have a controller that is calling the SP and the results are returned in XML.
This is fine however, the output is currently (for example):
<product>
<productId>12345</productId>
<inStock>True</inStock>
<shelfLevel>10</shelfLevel>
<onOrder>0</onOrder>
<height>10</height>
<width>15</width>
<depth>12</depth>
<colour>green</colour>
</product>
However, it needs to be structured as:
<product>
<productId>12345</productId>
<availability>
<inStock>True</inStock>
<shelfLevel>10</shelfLevel>
<onOrder>0</onOrder>
</availability>
<dimensions>
<height>10</height>
<width>15</width>
<depth>12</depth>
</dimensions>
<colour>green</colour>
</product>
I can not see any way of including the 'availabilty' and 'dimensions' wrapper elements using my current approach of EntityModel and Complex Type combination.
Below is my code from the controller for the existing output:
// GET api/product/5
//ProductAvailability_Result is the Complex Type derived from the SP output columns
public IEnumerable<ProductAvailability_Result> Get(int id)
{
myDB_DevEntities db = new myDB_DevEntities();
//ProductAvailability is a SP consisting of a simple 'select' statement that returns the resultset
var Result = db.ProductAvailability(id);
return Result.ToList();
}
Can anyone give any pointers on how to achieve this? Am i approaching this on completly the wrong way by trying to use the above method i.e. should I be ditching EntityModel? It works great until I need to change the structure.
Any advice would be much appreciated.
You could create a DTO (data transfer object) that looks like way you'd like, but you'd have to do a little bit of data transformation. You'd start with defining the class structure that matches the structure of the expected XML:
[XmlRoot("product")]
public class ProductDto
{
[XmlElement("productId")]
public int ProductId { get; set; }
[XmlElement("availability")]
public AvailabilityDto Availability { get; set; }
...
}
[XmlRoot("availability")]
public class AvailabilityDto
{
[XmlElement("inStock")]
public bool InStock { get; set; }
...
}
And then in your API method you can transform your DAO (data access object) into your DTO before you return it to the client:
public ProductDto GetProductAvailability(id)
{
var result = db.ProductAvailability(id);
return new ProductDto
{
ProductId = result.productId,
Availability = new AvailabilityDto
{
InStock = result.inStock,
...
},
...
}
}
Obviously this could amount to a ton of work, so I too am curious what other answers to your question may pop up.

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