I am creating a small program to get a instagram users following list using C# and instasharp. The code below will get me the first 50. I believe I have to use the pagination option to get the next url to get to the next page. Thats where Im stuck. How do I use pagination to loop through all of a users following?
var config = new InstaSharp.InstagramConfig("api", "oauth", "xxxxxx", "xxxxxxx", "xxxxxx");
var config1 = new InstaSharp.Endpoints.Relationships.Unauthenticated(config);
var result = config1.Follows(000000);
dynamic dyn = JsonConvert.DeserializeObject(result.Json);
foreach (var data in dyn.data)
{
listBox1.Items.Add(data.username);
}
Based on my response here: https://stackoverflow.com/a/25139236/88217
If you look at the unit tests on the InstaSharp github, you can see an example of how to use Pagination:
public async Task Follows_NextCursor()
{
//This test will fail if testing with an account with less than one page of follows
var result = await relationships.Follows();
result = await relationships.Follows(457273003/*ffujiy*/, result.Pagination.NextCursor);
Assert.IsTrue(result.Data.Count > 0);
}
In the case where you want to loop through and get all of them, I would expect you to do something like this:
int userID = 000000;
var result = await relationships.Follows(userID);
while(result.Data.Count > 0)
{
dynamic dyn = JsonConvert.DeserializeObject(result.Json);
foreach (var data in dyn.data)
{
listBox1.Items.Add(data.username);
}
result = await relationships.Follows(userID, result.Pagination.NextCursor)
}
Because this code uses await, you will have to mark the method as async, for more information on what that entails, I would suggest looking at the async/await keywords, a good introduction can be found at Stephen Cleary's Blog
Related
I would like to build an app that i'll use for myself so i'm targeting the simple authentification through Token.
I had my token from Discog and i know it works because i tried it in a third party app.
I'm using DiscogClient which seems to be the most popular client.
I'm following the Sample usage in the following way :
var tokenInformation = new TokenAuthenticationInformation("My token"); // i'm using my real token of course
//Create discogs client using the authentication
var discogsClient = new DiscogsClient.DiscogsClient(tokenInformation);
var discogsSearch = new DiscogsSearch()
{
artist = "Michael Jackson"
};
//Retrieve observable result from search
var observable = discogsClient.Search(discogsSearch);
I dont have any exception when i run that code, but if i look at the observable var in debug mode, there is no result whatsoever.
I'm lost and am seeking help.
Thanks in advance
ok so this is how i made it work, sound simple but i'm not used to thread programming.
var tokenInformation = new TokenAuthenticationInformation("My token"); // i'm using my real token of course
{
//Create discogs client using the authentication
var discogsClient = new DiscogsClient.DiscogsClient(tokenInformation);
var discogsSearch = new DiscogsSearch()
{
artist = "Michael Jackson"
};
await SearchDis(discogsClient, discogsSearch);
}
then the function
private async static Task SearchDis (DiscogsClient.DiscogsClient dc, DiscogsSearch ds)
{
var res = await dc.SearchAsync (ds);
}
I'm trying to send an activity through DirectLineClient library to my bot :
var directLineClient = new DirectLineClient($"{secret}");
directLineClient.BaseUri = new Uri($"https://directline.botframework.com/");
var conversation = await directLineClient.Conversations.StartConversationAsync().ConfigureAwait(false);
var activity = new Microsoft.Bot.Connector.DirectLine.Activity();
activity.From = new Microsoft.Bot.Connector.DirectLine.ChannelAccount();
activity.From.Name = "Morgan";
activity.Text = message;
activity.Type = "message";
var resourceResponse = await directLineClient.Conversations.PostActivityAsync(conversation.ConversationId, activity).ConfigureAwait(false);
await ReadBotMessagesAsync(directLineClient, conversation.ConversationId);
resourceResponse is always null.
Edit after Nicolas R answer
I added a method to wait for a response from the bot :
private static async Task ReadBotMessagesAsync(DirectLineClient client, string conversationId)
{
string watermark = null;
while (true)
{
var activitySet = await client.Conversations.GetActivitiesAsync(conversationId, watermark);
watermark = activitySet?.Watermark;
foreach (Microsoft.Bot.Connector.DirectLine.Activity activity in activitySet.Activities)
{
Console.WriteLine(activity.Text);
if (activity.Attachments != null)
{
foreach (Microsoft.Bot.Connector.DirectLine.Attachment attachment in activity.Attachments)
{
Console.WriteLine(attachment.ContentType);
}
}
}
if (activitySet.Activities.Count > 0)
{
return;
}
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
}
}
But I never get out of ReadBotMessagesAsync.
I precise that I can communicate with my bot through HTTP request (tested with Postman), and it should be sending a response message whenever a message is sent.
Edited after OP precision
Methods always returns null
Based on the documentation/samples, it looks like this PostActivityAsync return is never used so the value may not be relevant.
From the samples:
await client.Conversations.PostActivityAsync(conversation.ConversationId, userMessage);
See example here.
For those who want more details, because this answer is only limited to the comparison with the sample use, this package is sadly not open-source: https://github.com/Microsoft/BotBuilder/issues/2756
Remarks (for those who would be using the wrong packages)
I would not recommend to use this DirectLineClient Nuget package located here:
https://www.nuget.org/packages/DirectLineClient as it is not maintained since May 2016 and the Bot Framework has changed a lot since that time.
Moreover, it is using DirectLine API 1.0, which is not the best practice at the time. See documentation here:
Important
This article introduces key concepts in Direct Line API 1.1 and
provides information about relevant developer resources. If you are
creating a new connection between your client application and bot, use
Direct Line API 3.0 instead.
I have used the following code to retrieve the content of a JSON feed and as you see I have used the paging techniques and Skip and Take methods like this:
[HttpGet("[action]")]
public async Task<myPaginatedReturnedData> MyMethod(int page)
{
int perPage = 10;
int start = (page - 1) * perPage;
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("externalAPI");
MediaTypeWithQualityHeaderValue contentType =
new MediaTypeWithQualityHeaderValue("application/json");
client.DefaultRequestHeaders.Accept.Add(contentType);
HttpResponseMessage response = await client.GetAsync(client.BaseAddress);
string content = await response.Content.ReadAsStringAsync();
IEnumerable<myReturnedData> data =
JsonConvert.DeserializeObject<IEnumerable<myReturnedData>>(content);
myPaginatedReturnedData datasent = new myPaginatedReturnedData
{
Count = data.Count(),
myReturnedData = data.Skip(start).Take(perPage).ToList(),
};
return datasent;
}
}
My paging works fine, however I can't see any performance improvement and I know this is because every time I request a new page it calls the API again and again and after retrieving all contents, it filters it using Skip and Take methods, I am looking for a way to apply the Skip and Take methods with my HttpClient so that it only retrieves the needed records for every page. Is it possible? If so, how?
In order to apply the Take/Skip to the data retrieval, the server would have to know about them. You could do that with an IQueryable LINQ provider (see [1] for getting only an idea of how complex that is) or, better, by passing the appropriate values to the client.GetAsync call, something like
HttpResponseMessage response = await client.GetAsync(client.BaseAddress + $"?skip={start}&take={perPage}");
Of course, your server-side code has to interpret those skip and take parameters correctly; it's not automatic.
You might also want to look at OData (see [2]), but I have never actually used it in production; I just know it exists.
[1] https://msdn.microsoft.com/en-us/library/bb546158.aspx
[2] https://learn.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata-v3/calling-an-odata-service-from-a-net-client
My question may be trivial but I have spent almost 6hrs just trying things out.
public async Task<object> save()
{
var uri = "https://newsapi.org/v1/articles?source=talksport&apiKey=longKey";
var httpClient = new HttpClient ();
HttpResponseMessage res = await httpClient.GetAsync(uri);
var data = await res.Content.ReadAsStreamAsync();
// this is what I want to achieve like in python you can do something like this
foreach(var item in data){
Console.writeline(item.summary);
}
// end of arbitrary code
return data;
}
My problem is ,am unable to do this conversion to get the response and then accessing the json data.
In python you can do something
r = request.get(apiUrl)
data = r.json()
for item in data:
print(item.summary)
This is all I have struggle to achieve with c#, Any help to complete the code or explanation. Thanks
Try to use something like this:
Install Newtonsoft.Json package and add using Newtonsoft.Json;
using (var request = new HttpRequestMessage()) {
request.RequestUri = new Uri("https://newsapi.org/v1/articles?source=talksport&apiKey=longKey");
request.Method = HttpMethod.Get;
using (var response = await httpClient.SendAsync(request)) {
string content = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<IList<dynamic>>(content);
foreach(var item in result){
Console.writeline(item.summary);
}
}
}
From comment
Then i get this
"{\"vouchers\":[\"UN9NKK\",\"FYMFVS\",\"WV5AX7\",\"M2TJJ8\",\"FBB9AL\",\"MBW8Z4\"]}"
You can create a new class
public class MyResponse {
public IEnumerable<string> Vouchers {get;set; }
}
then
var response = JsonConvert.DeserializeObject<MyResponse>(content);
foreach(var item in response.Vouchers){
Console.WriteLine(item);
}
If you don't mind a small library dependency, Flurl (disclaimer: I'm the author) gets you Python's simplicity in C#:
var data = await apiUrl.GetJsonAsync();
In this case, data is a C# dynamic type, which means you can access all the JSON object's properties by name without defining a corresponding C# class, much like an untyped language. If you do want to declare a class and get compile-time type checking, that works with Flurl too:
var data = await apiUrl.GetJsonAsync<MyClass>();
Now data is an instance of MyClass instead of a dynamic.
Get Flurl.Http on Nuget, and reference it with using Flurl.Http;.
I am very new to MVC and making api calls server side and need a little guidance. I have created a simple method to call an api to retrieve results in a JSON object:
apiController.cs (normal controller.cs file)
[HttpGet]
public JsonResult getDefaultStuff(string a = "abc") {
var url = "https://myapiurl";
var client = new HttpClient();
client.DefaultRequestHeaders.UserAgent.ParseAdd("Blah");
var response = client.GetStringAsync(url);
return Json(response, JsonRequestBehavior.AllowGet);
}
The results return in an array like this:
{Result: {examples: [[0000,6.121],[0000,1.122],[0000,9.172]]},"Id":81,"Exception":null,"Status":5,"IsCanceled":false,"IsCompleted":true,"CreationOptions":0,"AsyncState":null,"IsFaulted":false}
I need it to return with keynames like this :
{
"examples": [
{
"Keyname1": "45678",
"Keyname2": "1234"
},
{
"Keyname1": "14789",
"Keyname2": "1234"
},
{
"Keyname1": "12358",
"Keyname2": "4569"
}
]
}
Do I need to use IDictonary? I am unsure of the approach. Do I create a new object and then loop through each result adding keynames? an example would be much appreciated or just the approach will be very helpful.
You can do the following:
By using the Json.Net nuget package first deserialize the response into, for example, an anonymous object:
var deserialized = JsonConvert.DeserializeAnonymousType(response, new
{
examples = new[] { new decimal[] { } }
});
Then transform this object into the new one that has the property structure you need:
var result = new
{
examples = deserialized.Result.examples.Select(x => new
{
Keyname1 = x[0],
Keyname2 = x[1]
})
};
And return it to the client:
return Json(result, JsonRequestBehavior.AllowGet);
This is what your solution could roughly look like but you do have to keep several things in mind though:
Exception handling for deserialization
Checks for possible nulls in the deserialized object
Maybe also the safer way of retrieving values from the array to avoid possible out of range exceptions.
Also the GetStringAsync method is asynchronous and you should put an await keyword in front of it, but in order to do so you need to make your method async as well:
public async Task<JsonResult> getDefaultStuff(...)
If you don't have enough knowledge of asynchronous programming, here is the most advanced, in-depth and comprehensive video explaining it from top to bottom I have ever seen, so check it out whenever you find time...