I got an Object from Facebook SDK
var responsePages = (JsonObject)FBClient_.Get(new { ids =
[123123123, 123123123, 12312213, etc]});
This query returns data (see image)
Now how do I convert this into a list of objects?
I have tried following but it does not work
var pe = (from dynamic page
in (IList<object>)(object)responsePages.Values
orderby page.name ascending
select new FBPage
{
Id = Convert.ToString(page.id),
}
).ToList();
So that failed, would appreciate any help because this dynamic stuff drives me seriously mad.
Thanks
You don't need to cast if you are using dynamic.
var fb = new FacebookClient();
dynamic result = fb.Get(new { ids = new[] { "...", "..." } });
var pages = new List<FBPage>();
foreach (var page in result.Values)
{
var fbPage = new FBPage {
Id = page.id,
Name = page.name
};
pages.Add(fbPage);
}
or if you want to use linq. (extension methods are not supported for dynamic, so you will need to do some casting, JsonObject => IDictionary<string, dyanmic>, JsonArray => IList<dynamic>)
var pages = ((IDictionary<string, dynamic>)result)
.Select(kpv => kpv.Value)
.Select(p => new FBPage { id = p.id, name = p.name })
.ToList();
Or you strongly typed classes.
var fbPages = fb.Get<IDictionary<string, FBPage>>(new {
ids = new[] { "...", "..." }
}).Values;
public class FBPage
{
public string id { get; set; }
public string name { get; set; }
}
'responsePages.Values' is an ICollection<JsonValue>
JsonValues can be serialized to Json strings, which can then be made the play things of a good Json deserializer such as Json.Net.
Using a simple loop this might look something like:
List<dynamic> dynamicList = new List<dynamic>();
List<FBPage> pe = new List<FBPage>();
foreach(var page in responsePages.Values)
{
//ToString is overridden in JsonValue to provide a string in Json format
string pageAsJsonString = page.ToString();
//Deserialize (parse) to a dynamic object using Json.Net's JObject.Parse static method
dynamic parsedPage = JObject.Parse(pageAsJsonString);
dynamicList.Add(parsedPage);
//Alternatively, if you have an appropriate object handy, deserialize directly:
FBPage deserializedPage = JsonConvert.DeserializeObject<FBPage>(pageAsJsonString);
pe.Add(deserializedPage);
}
foreach(dynamic page in dynamicList)
{
Console.WriteLine(page.name);
}
foreach(FBPage page in pe)
{
Console.WriteLine(page.Id);
}
Related
Say I have the following class structures
public class EmailActivity {
public IEnumerable<MemberActivity> Activity { get; set; }
public string EmailAddress { get; set; }
}
public class MemberActivity {
public EmailAction? Action { get; set; }
public string Type { get; set; }
}
public enum EmailAction {
None = 0,
Open = 1,
Click = 2,
Bounce = 3
}
I wish to filter a list of EmailActivity objects based on the presence of a MemberActivity with a non-null EmailAction matching a provided list of EmailAction matches. I want to return just the EmailAddress property as a List<string>.
This is as far as I've got
List<EmailAction> activityTypes; // [ EmailAction.Open, EmailAction.Bounce ]
List<string> activityEmailAddresses =
emailActivity.Where(
member => member.Activity.Where(
activity => activityTypes.Contains(activity.Action)
)
)
.Select(member => member.EmailAddress)
.ToList();
However I get an error message "CS1503 Argument 1: cannot convert from 'EmailAction?' to 'EmailAction'"
If then modify activityTypes to allow null values List<EmailAction?> I get the following "CS1662 Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type".
The issue is the nested .Where it's returning a list, but the parent .Where requires a bool result. How would I tackle this problem?
I realise I could do with with nested loops however I'm trying to brush up my C# skills!
Using List.Contains is not ideal in terms of performance, HashSet is a better option, also if you want to select the email address as soon as it contains one of the searched actions, you can use Any:
var activityTypes = new HashSet<EmailAction>() { EmailAction.Open, EmailAction.Bounce };
List<string> activityEmailAddresses =
emailActivity.Where(
member => member.Activity.Any(
activity => activity.Action.HasValue &&
activityTypes.Contains(activity.Action.Value)
)
)
.Select(activity => activity.EmailAddress)
.ToList();
You want to use All or Any depends if you want each or at least one match...
HashSet<EmailAction> activityTypes = new HashSet<EmailAction> { EmailAction.None };
var emailActivity = new List<EmailActivity>
{
new EmailActivity { Activity = new List<MemberActivity>{ new MemberActivity { Action = EmailAction.None } }, EmailAddress = "a" },
new EmailActivity { Activity = new List<MemberActivity>{ new MemberActivity { Action = EmailAction.Click } }, EmailAddress = "b" }
};
// Example with Any but All can be used as well
var activityEmailAddresses = emailActivity
.Where(x => x.Activity.Any(_ => _.Action.HasValue && activityTypes.Contains(_.Action.Value)))
.Select(x => x.EmailAddress)
.ToArray();
// Result is [ "a" ]
I am struggling to cast the INode results from the native Neo4j .Net driver to my own object.
public class User
{
public String UUID { get; set; }
public String firstname { get; set; }
}
My node as returned in Neo4j desktop browser:
{
"UUID": "e0bc991a-1018-4edb-83df-771b8cee4c88",
"firstname": "John"
}
C# code using Neo4jClient (this works):
var users = client.Cypher
.Match("(p:Person)")
.Return(p => p.As<User>())
.Results.ToList();
C# code using native Neo4j .Net driver (fails):
var users = new List<User>();
using (var session = _driver.Session())
{
session.ReadTransaction(tx =>
{
var result = tx.Run("MATCH (p:Person) RETURN p").ToList();
users = result.Select(p => p[0].As<User>()).ToList();
});
}
My error message is:
System.InvalidCastException: Unable to cast object of type Neo4j.Driver.Internal.Node to type sandbox_neotesting.Models.User.
Any pointers on how I can fix this? I was hoping to find a solution where I could directly cast the result to my internal model, not having to set each property specifically.
Thanks! :)
Very quiet here, but found a working solution. I simply serialize the node's properties, then deserialize into a User object. Feel free to suggest improvements!
var statementText = "MATCH (p:Person) RETURN p";
var users = new List<User>();
using (var session = _driver.Session())
{
session.ReadTransaction(tx =>
{
var result = tx.Run(statementText);
foreach(var record in result)
{
var nodeProps = JsonConvert.SerializeObject(record[0].As<INode>().Properties);
users.Add(JsonConvert.DeserializeObject<User>(nodeProps));
}
});
}
I want to achieve the following JSON data:
[
{
"name":"Deutschland",
"code":"de"
},
{
"name":"Frankreich",
"code":"fr"
},
{
"name":"Japan",
"code":"jpn"
}
]
Currently I'm getting this result of JSON data:
{
"groups":[
{
"name":"Deutschland",
"code":"de"
},
{
"name":"Frankreich",
"code":"fr"
},
{
"name":"Japan",
"code":"jpn"
}
]
}
Here is the code of the Controller:
public dynamic GetGroups()
{
JObject o = JObject.FromObject(new
{
groups = from g in db.QR_Groups
select new
{
name = g.name,
code = g.code
}
});
return o;
/*Here I've tried to get JSON data as array without the Property "groups"*/
//JArray a = new JArray(
// from g in db.QR_Groups
// select new JValue(g));
//return a;
}
Can anyone tell me how to retrieve the JSON data as per the first JSON example above?
And is the type "dynamic" good practice for the method?
First of all there is no need to do serialization manually. ASP.Net WebApi MediaFormatters are going to take care of it based on the Request Content-Type. So Create a class as shown below.
public class Group
{
public string name { get; set; }
public string code { get; set; }
}
Then your Web API endpoint should be -
[HttpGet]
public HttpResponseMessage GetCountries()
{
List<Group> groups = (from g in db.QR_Groups
select new Group
{
name = g.name,
code = g.code
}).ToList();
return Request.CreateResponse(HttpStatusCode.OK, groups);
}
And when I make a Fiddler request, I was able to get the output which you are interested -
Try this one:
var json = JsonConvert.SerializeObject(from g in db.QR_Groups
select new
{
name = g.name,
code = g.code
});
And is the type "dynamic" good practice for the method?
no, it's not best practise. Better one is to create new class
I want to select columns dynamically from List as following. So what could be the best way?
//a objects list
List<DashBoard> dashboardlist = (List<DashBoard>)objList;
string strColumns = "RecDate,ModifiedDate";
objList = (from obj in dashboardlist select new { strColumns }).ToList();
/////////////
Ok,Just forget Object List say I have database table which have number of column ID,Name,Age,sex,etc ..Then I have columnList to display and the columnList is change according to condition . SO I have List people; and List columnTemplate; so now I want to select the column based on the template .
Thanks for providing ideas to my question.Spending couple of hours in
Google I found solution .
public void Test() {
var data = new[] {
new TestData { X = 1, Y = 2, Z = 3 }
, new TestData { X = 2, Y = 4, Z = 6 }
};
var strColumns = "X,Z".Split(',');
foreach (var item in data.Select(a => Projection(a, strColumns))) {
Console.WriteLine("{0} {1}", item.X, item.Z);
}
}
private static dynamic Projection(object a, IEnumerable<string> props) {
if (a == null) {
return null;
}
IDictionary<string,object> res = new ExpandoObject();
var type = a.GetType();
foreach (var pair in props.Select(n => new {
Name = n
, Property = type.GetProperty(n)})) {
res[pair.Name] = pair.Property.GetValue(a, new object[0]);
}
return res;
}
class TestData {
public int X { get; set; }
public int Y { get; set; }
public int Z { get; set; }
}
I assume that the list of the columns may come from an external resource and change, I propose:
With reflection you could produce a list of FieldInfo that correspond to each Column, then loop over each item on the list and each FieldInfo and call GetValue on the data object.
Here is the solution:
Select a Column Dynamically using LINQ?
and look Dynamic Linq: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Let's supposed that you have only 2 templates. You can create a method for each template, that returns only the columns you need. Something like this:
// method for template 1 - returns only 3 columns/properties
private DashBoard CreateDashBoardXxxxxxx(DashBoard item)
{
return new DashBoard {
Property1 = item.Property1,
Property4 = item.Property2,
Property3 = item.Property3
};
}
// method for template 2 - returns N columns/properties
private DashBoard CreateDashBoardYyyyyyyy(DashBoard item)
{
return new DashBoard {
Property1 = item.Property1,
Property4 = item.Property2,
// Other properties
// .....
PropertyN = item.PropertyN
};
}
You can then use those methods like this:
List<DashBoard> dashboardlist = (List<DashBoard>)objList;
// using template 1
var list = dashboardlist.Select(CreateDashBoardXxxxxxx);
// using template 2
var list2 = dashboardlist.Select(CreateDashBoardYyyyyyyy);
You just need to do some code to decide which template should be used.
I hope this helps!!
I have a function that (via ajax) I pass a Guid and a comma delimited string of the types of objects I would like to return . I'm having trouble building a link statement that only returns the desired types. I'm struggling with how to build the query to check if string[] relatedTypes matches rw.GetType().Name. Or perhaps there's a better way.
Here's the Model...
public abstract class WebObject : IValidatableObject
{
public WebObject()
{
this.Id = Guid.NewGuid();
RelatedTags = new List<Tag>();
RelatedWebObjects = new List<WebObject>();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
public virtual ICollection<WebObject> RelatedWebObjects { get; set; }
public IList<Guid> RelatedWebObjectIds { get; set; }
}
And here's my function
public JsonResult GetRelatedWebObjectsByWebObject(Guid id, string relatedWebObjectTypes)
{
JsonResult result = new JsonResult();
Guid webSiteId = db.WebObjects.Find(id).WebSiteId;
string[] relatedTypes = relatedWebObjectTypes.Split(',');
var resultData = (from w in db.WebObjects
where w.Id == id
from rw in w.RelatedWebObjects
where rw.GetType().Name.Contains(relatedTypes)
select rw.Id).ToList();
result.Data = resultData;
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return result;
}
Are you looking for something like:
var relatedTypes = new HashSet<string>(relatedWebObjectTypes);
var resultData = (from w in db.WebObjects
where w.Id == id
&& relatedTypes.SetEquals
(w.RelatedWebObjects.Select(rwo => rwo.GetType().Name))
select w.RelatedWebObjectIds).ToList();
Although I would say that it isn't good practice to use a collection of simple type names in this manner. Are you sure you couldn't use a Type[] or similar here?
It's not clear from your question what exactly do you want, but I think it's this:
from w in db.WebObjects
where w.Id == id
from rw in w.RelatedWebObjects
where relatedWebObjectTypes.Contains(rw.GetType().Name)
select rw.Id
This selects all the items from WebObjects with the correct Id (I guess there should be only one, but it does not matter to the query). And for each of them, get the RelatedWebObjects whose type's name is in relatedWebObjectTypes. And for each of those, get their Id.
You would need to refactor a bit, instead of passing in the name of the types as string, you should pass the actual type then use the linq operator for OfType(Of relatedType)
The MSDN Article gives a simple example that should have you on your way.
A little late, but here's what I ended up going with...
public JsonResult GetRelatedWebObjectsByWebObject(Guid id, string relatedWebObjectTypes)
{
JsonResult result = new JsonResult();
Guid webSiteId = db.WebObjects.Find(id).WebSiteId;
List<string> relatedTypes = new List<string>(relatedWebObjectTypes.Split(','));
var resultData = (from w in db.WebObjects
where w.Id == id
from rw in w.RelatedWebObjects
select rw).ToList();
result.Data = resultData.Where(w => relatedTypes.Contains(w.GetType().BaseType.Name) == true).Select(w => new { Id = w.Id, Type = w.GetType().BaseType.Name }).ToList();//w.Id).Select(w => w.GetType().BaseType.Name).ToList();
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return result;
}