Facebook C# SDKv6 How to Parse results of Multi Query FQL - json

I can successfully execute a multi query fql using the facebook c# sdk v 6.14 thanks to Prabir's blog, but need help in parsing the results. I've searched and tried many ways to no avail. I know it is a simple syntax issue, but I'm fairly new to c# and JSON.
Any help is much appreciated!
Thanks,
Chad
My Code:
var fb = new FacebookClient(this.FacebookAccessToken);
dynamic resultsMQFQL = fb.Get("fql",
new
{
q = new
{
friendsMovies = "SELECT page_id, uid FROM page_fan WHERE type='MOVIE' AND uid IN (SELECT uid2 FROM friend WHERE uid1=me()) ORDER BY page_id",
movieDetails = "SELECT page_id, name, pic, fan_count, categories, genre, starring, release_date FROM page WHERE page_id IN (SELECT page_id FROM #friendsMovies) ORDER BY fan_count DESC",
}
});
Results:
{"data":[
{"name":"friendsMovies",
"fql_result_set":
[{"page_id":105638652803531,"uid":796419451},
{"page_id":113271808686307,"uid":796419451}]},
{"name":"movieDetails",
"fql_result_set":[
{"page_id":105638652803531,"name":"Fear and Loathing in Las Vegas"},
{"page_id":113271808686307,"name":"Fletch"}
]
}
]}
Attempt at parsing:
foreach (dynamic row in resultsMQFQL.data.fql_result_set)
Error:
'Facebook.JsonArray' does not contain a definition for 'fql_result_set'

Ok, figured it out...forgot I could try various combinations quickly while debugging in the immediate window...did I say I am fairly new at coding? :)
public void FBMQFQL()
{
var fb = new FacebookClient(this.FacebookAccessToken);
dynamic resultsMQFQL = fb.Get("fql",
new
{
q = new
{
friendsMovies = "SELECT page_id, uid FROM page_fan WHERE type='MOVIE' AND uid IN (SELECT uid2 FROM friend WHERE uid1=me()) ORDER BY page_id",
movieDetails = "SELECT page_id, name, pic, fan_count, categories, genre, starring, release_date FROM page WHERE page_id IN (SELECT page_id FROM #friendsMovies) ORDER BY fan_count DESC",
}
});
//To access a direct value: resultsMQFQL.data[0].fql_result_set[0].page_id
var friendsMovies = resultsMQFQL.data[0].fql_result_set;
var movieDetails = resultsMQFQL.data[1].fql_result_set;
if (resultsMQFQL == null)
{
//return null;
}
else
{
//Construct the new, formated, merged datatable to store the results the way we want them
DataTable dtMyFriendsMovies = new DataTable();
dtMyFriendsMovies.Columns.Add("MovieID");
dtMyFriendsMovies.Columns.Add("FriendUserID");
foreach (dynamic row in friendsMovies)
{
//Add New DataRow to new DataTable
DataRow drRow = dtMyFriendsMovies.NewRow();
//Get various values from original JSON Friend List returned
drRow["MovieID"] = row.page_id;
drRow["FriendUserID"] = row.uid;
//Add New Row to New Resulting Data Table
dtMyFriendsMovies.Rows.Add(drRow);
}
//MovieDetails
DataTable dtMovies = new DataTable();
dtMovies.Columns.Add("movieID");
dtMovies.Columns.Add("name");
dtMovies.Columns.Add("pic");
dtMovies.Columns.Add("fan_count");
dtMovies.Columns.Add("genre");
dtMovies.Columns.Add("starring");
dtMovies.Columns.Add("release_date");
foreach (dynamic row in movieDetails)
{
//Add New DataRow to new DataTable
DataRow drRow = dtMovies.NewRow();
//Get various values from original JSON Friend List returned
drRow["movieID"] = row.page_id;
drRow["name"] = row.name;
drRow["pic"] = row.pic;
drRow["fan_count"] = row.fan_count;
drRow["genre"] = row.genre;
drRow["starring"] = row.starring;
drRow["release_date"] = row.release_date;
//Add New Row to New Resulting Data Table
dtMovies.Rows.Add(drRow);
}
//return dtMyFriendsMovies;
}
} //FB FQL

Related

ASP.NET C# Multiple Value Json Serialize

I try to return user informations json value at my web page' load method. My code looks like this.
DataSet dsX = ReadSql("select top 14 * from fuyeler where inStatus = 1 and inUye = 1");
if (dsX.Tables.Count > 0)
{
OYUNCU oyuncular = new OYUNCU();
for (int i = 0; i < dsX.Tables[0].Rows.Count; i++)
{
oyuncular.oyuncuID = Convert.ToInt32(dsX.Tables[0].Rows[i]["inID"]);
oyuncular.oyuncuMail = dsX.Tables[0].Rows[i]["stMail"].ToString();
oyuncular.oyuncuPass = dsX.Tables[0].Rows[i]["stPass"].ToString();
oyuncular.oyuncuToken = dsX.Tables[0].Rows[i]["stToken"].ToString();
}
string json = JsonConvert.SerializeObject(oyuncular);
Response.Clear();
Response.ContentType = "application/json; charset=utf-8";
Response.Write(json);
Response.End();
}`
At the end it returns only 1 value of course. I have tried Arrays and lists but JsonConvert.SerializeObject(array or list) doesnt return as json value. It returns every values on 1 row. I want 1 row for 1 value. What should i do about it?
For this code below Json result looks like this,
{"oyuncuMail":"x#gmail.com","oyuncuPass":"x2008","oyuncuToken":"290620153513","oyuncuID":14}
This output is correct and should dispaly last record of the selected rows from your sql query because in your for loop you don't create new object, you assign values to the same object so it will take the values of the last row
you should do this if you want to get a list :
List<OYUNCU> listOyuncular = new List<OYUNCU>();
for (int i = 0; i < dsX.Tables[0].Rows.Count; i++)
{
var oyunclar = new OYUNCU();
oyuncular.oyuncuID = Convert.ToInt32(dsX.Tables[0].Rows[i]["inID"]);
oyuncular.oyuncuMail = dsX.Tables[0].Rows[i]["stMail"].ToString();
oyuncular.oyuncuPass = dsX.Tables[0].Rows[i]["stPass"].ToString();
oyuncular.oyuncuToken = dsX.Tables[0].Rows[i]["stToken"].ToString();
listOyuncular.Add(oyunclar);
}
string json = JsonConvert.SerializeObject(listOyuncular);

In MVC, pass complex query and view model to session?

I have a view model:
public class UserCollectionView
{
public CardCollection CardCollections { get; set; }
public Card Cards { get; set; }
}
I have a List View Controller:
public ActionResult ViewCollection(int? page)
{
var userid = (int)WebSecurity.CurrentUserId;
var pageNumber = page ?? 1;
int pageSize = 5;
ViewBag.OnePageOfCards = pageNumber;
if (Session["CardCollection"] != null)
{
var paging = Session["CardCollection"].ToString.();
return View(paging.ToPagedList(pageNumber, pageSize));
}
var viewModel = from c in db.Cards
join j in db.CardCollections on c.CardID equals j.CardID
where (j.NumberofCopies > 0) && (j.UserID == userid)
orderby c.Title
select new UserCollectionView { Cards = c, CardCollections = j };
Session["CardCollection"] = viewModel;
return View(viewModel.ToPagedList(pageNumber, pageSize));
I am trying to use the PagedList to add paging to the results. I have been able to do this when I am not using a query that returns data from 2 databases in a single view. As shown here
My end result looks something like this:
Cards.SeveralColumns CardCollections.ColumnA CardCollections.ColumnB
Row 1 Data from Cards Table A from CardCollections B from CardCollections
Row 2 Data from Cards Table A from CardCollections B from CardCollections
Row 3 Data from Cards Table A from CardCollections B from CardCollections
And so on... I get an error
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
I have tried variations of SQL statements but can't get it to fit with my view model. In SQL Management Studio this brings back the correct results
Select * from Cards Inner Join CardCollections On Cards.CardID = CardCollections.CardID where CardCollections.UserID = 1 and CardCollections.NumberofCopies > 0;
I need a way to pass the query in session so the paging will operate correctly. Any advice is appreciated. :)
Short answer is, you can't. The model needs to be a snapshot of the content and therefore you can't pass an open query across the boundary (either as a hand-off to a session or to the client directly).
What you're seeing is the disposal of the context beyond it's initial use (where you assemble var viewmodel).
With that said, you can cache the results (to save overhead) if querying the data is an expensive operation. Basically, you'd store the entire collection (or at least a large subset of the collection) in the session/memorycache (which can then be manipulated into a paged list). Something to the effect of:
public ActionResult ViewCollection(int? page)
{
var userId = (int) WebSecurity.CurrentUserId;
var pageNumber = page ?? 1;
var pageSize = 5;
ViewBag.OnePageOfCards = pageNumber;
var cacheKey = String.Format("ViewCollection[{0}]", userId);
var entities = GetOrCreateCacheItem<IEnumerable<UserCollectionView>>(cacheKey, () => {
var query = (from c in db.Cards
join j in db.CardCollections on c.CardID equals j.CardID
where (j.NumberofCopies > 0) && (j.UserID == userid)
orderby c.Title
select new UserCollectionView { Cards = c, CardCollections = j }
)
.ToList(); // Force fetch from Db so we can cache
});
return View(entities.ToPagedList(pageNumber, pageSize));
}
// To give an example of a cache provider; Feel free to change this,
// abstract it out, etc.
private T GetOrCreateCacheItem<T>(string cacheKey, Func<T> getItem)
{
T cacheItem = MemoryCache.Default.Get(cacheKey) as T;
if (cacheItem == null)
{
cacheItem = getItem();
var cacheExpiry = DateTime.Now.AddMinutes(5);
MemoryCache.Default.Add(cacheKey, cacheItem, cacheExpiry);
}
return cacheItem;
}
It turns out that I didn't need to pass the query at all. If I let it run through it works fine without the session. I am not really sure why this works but my search query has to be passed. Maybe it is because I am using a viewmodel to perform the query. I will experiment and post if I find anything. Currently the working code is:
public ActionResult ViewCollection(int? page)
{
var userid = (int)WebSecurity.CurrentUserId;
var pageNumber = page ?? 1;
int pageSize = 5;
ViewBag.OnePageOfCards = pageNumber;
ViewBag.Rarity_ID = new SelectList(db.Rarities, "RarityID", "Title");
ViewBag.MainType_ID = new SelectList(db.MainTypes, "MainTypeID", "Title");
ViewBag.CardSet_ID = new SelectList(db.CardSets, "CardSetID", "Title");
ViewBag.SubType_ID = new SelectList(db.SubTypes, "SubTypeID", "Title");
var viewModel = from c in db.Cards
join j in db.CardCollections on c.CardID equals j.CardID
where (j.NumberofCopies > 0) && (j.UserID == userid)
orderby c.Title
select new UserCollectionView { Cards = c, CardCollections = j };
return View(viewModel.ToPagedList(pageNumber, pageSize));

insert selected value from drop down by razor mvc

hi, I had aproject and one of my task as to insert selected value from
drop down to DB field by razor mvc. I did my code but no values inserted ,Also the DDL have items from DB well . my project with razor mvc4.
public ActionResult Create()
{
var data = db.Categories.ToList().Distinct();
foreach (var t in data)
{
s.Text = t.Name;
s.Value = t.Cat_ID.ToString();
items.Add(s);
}
ViewBag.Parent = items;
return View();
}
[HttpPost]
public ActionResult Create(Category category, IEnumerable<HttpPostedFileBase> files)
{
if (Request.Files.Count > 0)
{
var uploadedFile = Request.Files[0];
var fileSavePath = "";
var fileName = "";
fileName = Path.GetFileName(uploadedFile.FileName);
fileSavePath = Server.MapPath("~/App_Data/Uploads/" + fileName);
uploadedFile.SaveAs(fileSavePath);
category.Path = "~/App_Data/Uploads/" + fileName;
}
var data = db.Categories.ToList().Distinct();
List<SelectListItem> items = new List<SelectListItem>();
foreach (var t in data)
{
SelectListItem s = new SelectListItem();
s.Text = t.Name;
s.Value = t.Cat_ID.ToString();
items.Add(s);
if (s.Selected)
{ category.Parent_ID = int.Parse(s.Value); }
}
db.Categories.Add(category);
db.SaveChanges();
return RedirectToAction("Index");
}
Hi Your code should be something like this. I am assuming that you have model with certain structure. If belo code does not give you a clue then please. Tell how your view and model is and what is your requirement.
Hope this helps.
[HttpPost]
public ActionResult Create(Category category, IEnumerable<HttpPostedFileBase> files)
{
if (Request.Files.Count > 0)
{
var uploadedFile = Request.Files[0];
var fileSavePath = "";
var fileName = "";
fileName = Path.GetFileName(uploadedFile.FileName);
fileSavePath = Server.MapPath("~/App_Data/Uploads/" + fileName);
uploadedFile.SaveAs(fileSavePath);
category.Path = "~/App_Data/Uploads/" + fileName;
}
var data = db.Categories.ToList().Distinct();
//I assume that you need to find the category from db.Caegories which user has selected on the UI and submited the form.
//I assume the parameter category is the one which you want to find from DB.
//category is your model has Parent_Id property which is bound to UI control (ie. dropdown)
var categoryToSave = (from c in data
where c.Cat_ID == category.Parent_ID
select c).firstOrDefault();
if(categoryToSave!=null)
{
//I believe here you want to save this category to some other table.
//Now you have got the category tht user has selected on UI.
//Write the further logic here.....
db.SaveChanges();
}
return RedirectToAction("Index");
}
Regards, Mahesh
you are creating the fresh selectListItem s here in the same loop. You will get seleced == true for any of the item.
May be item, that user has selected on UI (before post) exist in category param if it is your model that is bound to desired dropdown.
I suspect it is a logical error.
Regards, Mahesh

JSON, MVC2 Disordered data in even cell cointainers

I got into troubles trying to feed the jqgrid with required information. I did everything as suppose to be done, but apparently there is an issue.
Every second cell is order differently, so first row is ok:
[{"id":"AA1","cell":["AA1","AD + DNS + WINS","dev"]},
but the next one is ordered like below:
{"id":"AA2","cell":["dev","AD + DNS + WINS","AA2"]}
when 3rd is ok, and 4th is disordered and so on.
Code which is responsible for this process is below:
var jsonData = new
{
total = totalPages,
page = page,
records = totalRecords,
rows = (
from l in lst
select new
{
id = l.HostName,
cell = new List<string> {
l.HostName, l.Description, l.Type
}
}).ToArray()
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
Why is like that? I was trying use instead of List the String[], but Linq doesn't like that and pop up error, which suggest List instead of string array.
Is there any way to sustain desired order?
What was your code to use string[]? I got this working without any trouble:
var jsonData = new
{
total = totalPages,
page = page,
records = totalRecords,
rows = (from l in lst
select new
{
id = l.HostName,
cell = new string[] {
l.HostName,
l.Description,
l.Type
}
}).ToArray()
};
You can find similar samples here (but remember that in general they are very old and I would suggest looking at more up to date ones here or here).

Linq-2-Sql code: Does this scale?

I'm just starting to use linq to sql. I'm hoping that someone can verify that linq-2-sql has deferred execution until the foreach loop is executed. Over all, can someone tell me if this code scales. It's a simple get method with a few search parameters. Thanks!
Code:
public static IList<Content> GetContent(int contentTypeID, int feedID, DateTime? date, string text)
{
List<Content> contentList = new List<Content>();
using (DataContext db = new DataContext())
{
var contentTypes = db.ytv_ContentTypes.Where(p => contentTypeID == -1 || p.ContentTypeID == contentTypeID);
var feeds = db.ytv_Feeds.Where(p => p.FeedID == -1 || p.FeedID == feedID);
var targetFeeds = from f in feeds
join c in contentTypes on f.ContentTypeID equals c.ContentTypeID
select new { FeedID = f.FeedID, ContentType = f.ContentTypeID };
var content = from t in targetFeeds
join c in db.ytv_Contents on t.FeedID equals c.FeedID
select new { Content = c, ContentTypeID = t.ContentType };
if (String.IsNullOrEmpty(text))
{
content = content.Where(p => p.Content.Name.Contains(text) || p.Content.Description.Contains(text));
}
if (date != null)
{
DateTime dateTemp = Convert.ToDateTime(date);
content = content.Where(p => p.Content.StartDate <= dateTemp && p.Content.EndDate >= dateTemp);
}
//Execution has been defered to this point, correct?
foreach (var c in content)
{
Content item = new Content()
{
ContentID = c.Content.ContentID,
Name = c.Content.Name,
Description = c.Content.Description,
StartDate = c.Content.StartDate,
EndDate = c.Content.EndDate,
ContentTypeID = c.ContentTypeID,
FeedID = c.Content.FeedID,
PreviewHtml = c.Content.PreviewHTML,
SerializedCustomXMLProperties = c.Content.CustomProperties
};
contentList.Add(item);
}
}
//TODO
return contentList;
}
Depends on what you mean with 'scales'. DB side this code has the potential of causing trouble if you are dealing with large tables; SQL Server's optimizer is really poor at handling the "or" operator in where clause predicates and tend to fall back to table scans if there are multiple of them. I'd go for a couple of .Union calls instead to avoid the possibility that SQL falls back to table scans just because of the ||'s.
If you can share more details about the underlying tables and the data in them, it will be easier to give a more detailed answer...