I am working on a small C# application using Woocommerce.net library to make RESP API calls. My goal here is to retrieve all products from my online store which I have done. However, while the products are being retrieved, I want to show the user progress with a progress bar preferably. Here is the code I am using for retrieving products.
RestAPI rest = new RestAPI("https://www.store.ca/wp-json/wc/v3/", "key", "key");
WCObject wc = new WCObject(rest);
//Get all products
products = new List<Product>();
Dictionary<string, string> dic1 = new Dictionary<string, string>();
dic1.Add("per_page", "100");
int pageNumber1 = 1;
dic1.Add("page", pageNumber1.ToString());
bool endWhile1 = false;
while (!endWhile1)
{
var productsTemp = await wc.Product.GetAll(dic1);
if (productsTemp.Count > 0)
{
products.AddRange(productsTemp);
pageNumber1++;
dic1["page"] = pageNumber1.ToString();
}
else
{
endWhile1 = true;
}
}
Is there any way possible to report back progress for such call. I couldn't find anything related to this. I came across IProgress<int> but I believe that would not work in this scenario.
Any ideas?
Any help is appreciated.
Thanks in advance.
You read objects 'per page'.
1.If you can get product count please do it first (version 3 had count method)
2. progress step will be (page number * 100 items) which you can notify right after addRange
Related
Since a few days I have been using Youtube's (Google's) API 3.0 (.NET Google API Library)
Everything was going smooth until I stumbled across a problem. I've tried many methods to figure out why I got a low amount of info from my results.
What I am trying in the code down below, is requesting the first comment on a video.
Then with that first comment (CommentThread), I am trying to retrieve all the replies of users that reacted on this comment.
I have tried getting information before, it works fine. I could loadup the entire comment section. Except for more than 5 replies per CommentThread. (CommentThread is basicly a comment under a video, where some have replies.)
This is my code, I have modified it alot of times, but from the looks of it. This one should work.
private static void searchReplies()
{
int count = 0;
YouTubeService youtube = new YouTubeService(new BaseClientService.Initializer() { ApiKey = Youtube.API.KEY });
List<string[]> comments = new List<string[]>();
var commentThreadsListRequest = youtube.CommentThreads.List("snippet,replies");
commentThreadsListRequest.VideoId = Youtube.Video.ID;
commentThreadsListRequest.Order = CommentThreadsResource.ListRequest.OrderEnum.Relevance;
commentThreadsListRequest.MaxResults = 1;
var commentThreadsListResult = commentThreadsListRequest.Execute();
foreach (var CommentThread in commentThreadsListResult.Items)
{
var commentListRequest = youtube.Comments.List("snippet");
commentListRequest.Id = CommentThread.Id;
var commentListResult = commentListRequest.Execute();
foreach (var Item in commentListResult.Items)
{
CommentThreadIDs.Add(Item.Id);
}
MessageBox.Show("COUNT:" + CommentThread.Replies.Comments.Count);
foreach (var Reply in CommentThread.Replies.Comments)
{
CommentThreadIDs.Add(Reply.Id);
}
}
}
I have checked my API and the video ID. They are all fine as I can request alot of other information.
I have tested this with several videos, but all videos where the first comment have more than 5 replies, it fails to get them all.
The result (Message Box with "Count:") I get (the amount of replies I get in CommentThread.Replies.Comments is 5. No matter what I do. Going to next page with a token does not work either as it is empty.
Does anyone know why it only returns 5 comments instead of more?
I found the answer with help of someone.
The problem was that I set the ID of a commentThread to a comment ID.
Instead I have to set the commentThread ID to the parent ID.
The following code fully replaces my old code if anyone ever needs it.
YouTubeService yts = new YouTubeService(new BaseClientService.Initializer() { ApiKey = "12345" });
var commentThreadsListRequest = yts.CommentThreads.List("snippet,replies");
commentThreadsListRequest.VideoId = "uywOqrvxsUo";
commentThreadsListRequest.Order = CommentThreadsResource.ListRequest.OrderEnum.Relevance;
commentThreadsListRequest.MaxResults = 1;
var commentThreadResult = commentThreadsListRequest.Execute().Items.First();
var commentListRequest = yts.Comments.List("snippet");
commentListRequest.Id = commentThreadResult.Id;
commentListRequest.MaxResults = 100;
var commentListResult = commentListRequest.Execute();
var comments = commentListResult.Items.Select(x => x.Snippet.TextOriginal).ToList();
I am working on an application which requires to fetch entities from one system (Contacts from Dynamics CRM). The app does some process on those contacts, basically convert to compatible payload for other system and then sync it back.
The Dynamics CRM has over 8000 contacts so no brainer, I went ahead with pagination approach.. The code looks something like this -
string nextPageUrl = string.Empty;
bool nextPageAvailable = true;
int totalContactsCount = 0;
bool firstCall = true;
JArray totalContacts = new JArray();
while (nextPageAvailable)
{
string contacts = string.Empty;
if (string.IsNullOrEmpty(nextPageUrl) && firstCall)
{
contacts = await _genericService.GetEntity("contacts", pageSize: 100);
firstCall = false;
}
else
{
contacts = await _genericService.GetEntityFromPaginationUrl(nextPageUrl, pageSize: 100);
}
var contactsObj = JObject.Parse(contacts);
var contactArr = (JArray)contactsObj["value"];
var contactsLength = contactArr.Count;
foreach(var contactObject in contactArr)
{
totalContacts.Add(contactObject);
}
var contactsCt = totalContacts.Count;
nextPageUrl = contactsObj["#odata.nextLink"].IsNullOrEmpty() ? string.Empty : contactsObj["#odata.nextLink"].ToString();
if(string.IsNullOrEmpty(nextPageUrl) && !firstCall)
{
nextPageAvailable = false;
}
Console.WriteLine(nextPageUrl);
}
This works perfectly but till I get 8000 contacts (100 at a time), the memory utilization is almost over 370mb. I am sure there is a better way to achieve this but can not think of any.
The memory problem will get more serious when I reiterate through totalContacts which will be having over 8000 contacts and process them.
Since the contacts coming from Dynamics CRM may have newly added properties, I can not strongly type the objects with models. This is why I have decided to go with JArray. Is there any better alternative to achieve this?
Thanks in advance.
I'm trying to filter EC2 instances using the AWS SDK in .NET and, although I have seen inumerous threads on SO and on other websites of people resolving this issue, nothing I've tried on my end worked.
So, as a last resource, I'm coming to you guys for help. Can anyone shed some light on what I'm missing ? I know it's very likely that I'm doing something stupid, but I can't afford to waste too much time solving this issue.
This is the chunk of code I'm using to filter an EC2 instance (get it's metadata) by it's tag name:
DescribeInstanceStatusRequest req = new DescribeInstanceStatusRequest ();
req.Filters.Add (new Filter() { Name = "tag:Name", Values = new List <string> () { "some_random_name" } });
// Executing request & fetching response
DescribeInstanceStatusResponse resp = m_ec2Client.DescribeInstanceStatus (req);
But I keep on running into this exception:
The filter 'tag:Name' is invalid
I have replaced the filter name ("tag:Name" in the example) by several filters listed in the documentation (e.g. "tag-key", "tag-value", "tag:key=value"), but nothing works.
Thank you all in advance :)
After a more thorough research, I found out that the "DescribeInstanceStatus" routine doesn't support searching by tag, but I found a somewhat "simple" way of doing so. I'll post it in here in case anyone goes through the same situation.
Here's how:
DescribeInstancesRequest req = new DescribeInstancesRequest ();
req.Filters.Add (new Filter () { Name = "tag-value", Values = new List <string> () { "something" }});
// Executing request & fetching response
DescribeInstancesResponse resp = m_ec2Client.DescribeInstances (req);
return resp.Reservations.SelectMany (x => x.Instances).Where (y => y.State.Name == InstanceStateName.Pending || y.State.Name == InstanceStateName.Running).ToList (); {code}
In theory, with this routine you can use any of the filters listed under the "Supported Filters" table in the documentation.
Getting Number of running instance from AWS EC2
DescribeInstancesRequest req = new DescribeInstancesRequest();
req.Filters.Add(new Filter {
Name = "instance-state-name",
Values = new List<string>() { "running" }
});
DescribeInstancesResponse resp = _amazonEC2Client.DescribeInstances(req);
It's may be...
// Executing request & fetching response
DescribeInstancesResponse resp = m_ec2Client.DescribeInstances (
new DescribeInstancesRequest()
{
Filters = new List<Filter>()
{
new Filter("tag:Name", new List<string>(){"some_random_name"})
}
});
Hello SO folks and more specifically Google folks monitoring this tag per your support page. I am working from .NET and PlaylistItems.List("snippet,contentDetails") does not do a whole lot compared to the old RSS Feed search. In fact adding part contentDetails adds little value in that only the VideoID is now returned but it is already part of Snippet.ResourceId.VideoId
"kind": "youtube#playlistItem",
bla,
bla,
"contentDetails": {
"videoId": "DLME0PsJRnk"
}
Why add a "part" which is only going to return one bit of information?
How about supporting something like "snippet,contentDetails(duration,PublishedAt,Views)"
I feel this is kind of basic metadata (snippet) most apps would want to list to the users.
While you are at it please please remove this non-sense of Java casing of parameters. Why would you leak-out your language of choice into an API, that's really sad. Yes it is frustrating to keep checking whether I case-spelled them correctly.
Well, it looks like you are forcing "us" to build a list of VideoIds than turn around and make more API calls when I was doing it previously with fewer.
It also means, I will have to manage the 50 items max paging twice, once for the playlist if it is over 50 videos and then manage manually my list of VideosIds paging when I turn around to make Videos.List calls.
Let me know if I missed an All-In-One call type of API, thank you.
Here is what I have now working, let me know if there is a better way
// 20150802
public async Task<List<YouTubeInfo>> PlaylistVideosInfo(String PlaylistID)
{
var YoutubeService = YouTubeService();
//
List<YouTubeInfo> VideoInfos = new List<YouTubeInfo>();
//
var NextPageToken = "";
while (NextPageToken != null)
{
//
var SearchListRequest = YoutubeService.PlaylistItems.List("snippet");
SearchListRequest.PlaylistId = PlaylistID;
SearchListRequest.MaxResults = 50;
SearchListRequest.PageToken = NextPageToken;
// Call the search.list method to retrieve results matching the specified query term.
var SearchListResponse = await SearchListRequest.ExecuteAsync();
// Collect Video IDs from this page
var VideoIDsBatch = new List<string>(); // batch Video detail search by 50 max
foreach (var searchResult in SearchListResponse.Items)
{
VideoIDsBatch.Add(searchResult.Snippet.ResourceId.VideoId);
}
// Make API call for this batch - expect a single page :(
var VideoListRequest = YoutubeService.Videos.List("snippet,contentDetails");
VideoListRequest.Id = String.Join(",", VideoIDsBatch);
VideoListRequest.MaxResults = 50;
var VideoListResponse = await VideoListRequest.ExecuteAsync();
// Collect each Video details
foreach (var VideoResult in VideoListResponse.Items)
{
YouTubeInfoAdd(VideoInfos, VideoResult);
}
// request next page
NextPageToken = SearchListResponse.NextPageToken;
}
// Return All Videos' detail
return VideoInfos;
}
In ServiceNow, I am able to get only a maximum of 250 records in a SOAP request. How to get all the records?
Web Reference Url = https://*****.service-now.com/rm_story.do?WSDL
Code:
var url = "https://*****.service-now.com/rm_story.do?SOAP";
var userName = *****;
var password = *****;
var proxy = new ServiceNow_rm_story
{
Url = url,
Credentials = new NetworkCredential(userName, password)
};
try
{
var objRecord = new Namespace.WebReference.getRecords
{
// filters..
};
var recordResults = proxy.getRecords(objRecord);
}
catch (Exception ex)
{
}
In recordResults, I am getting only 250 records. How to get all the records ?
Also see this stack overflow answer which provides info.
Get ServiceNow Records Powershell - More than 250
Note that returning a large number of records can affect performance of the response and it may be more efficient to process your query in batches using offsets (i.e., get 1-100, then 101-200, ...). This can be achieved by using a sort order and offset. The ServiceNow REST Table API actually returns link headers from Get requests providing you links for the first, next and last set of records making it easy to know the url to query the next batch of records.
See: http://wiki.servicenow.com/index.php?title=Table_API#Methods
and look under 'Response Header'.
Have u tried to pass/override __limit parameter?
Google / wiki / Users manual / Release notes are always helpful
In your code snippet in line where it says //filter you should define __limit (and potentially __first_row and __last_row as explained in the example bellow)
int Skip = 0;
int Take = 250;
while (true)
{
using (var soapClient = new ServiceNowLocations.ServiceNow_cmn_location())
{
var cred = new System.Net.NetworkCredential(_user, _pass);
soapClient.Credentials = cred;
soapClient.Url = _apiUrl + "cmn_location.do?SOAP";
var getParams = new ServiceNowLocations.getRecords()
{
__first_row = Skip.ToString(),
__last_row = (Skip + Take).ToString(),
__limit = Take.ToString()
};
var records = soapClient.getRecords(getParams);
if (records != null)
{
if (records.Count() == 0)
{
break;
}
Skip += records.Count();
if (records.Count() != Take)
{
// last batch or everything in first batch
break;
}
}
else
{
// service now web service endpoint not configured correctly
break;
}
}
}
I made an library that handles interacting with ServiceNow Rest API much easier
https://emersonbottero.github.io/ServiceNow.Core/