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/
Related
New Info:
I thought I would paste this in full as I can not seem to find any samples on the web of a c# solution for StarLink so hopefully anyone else looking for something may find this helpful and may contribute.
My New Proto File - (partial) - I took the advise of Yuri below. Thanks for the direction here. I was able to I have been using this tool and it has brought a lot of insight but I am still stuck on the c# side of the solution. I am an old VB.Net developer though I have done a bunch in c# I am by no means savvy in it and am probably missing something so simple. Again, any insight would be awesome. I can not post the full proto here as stack has char limit on posts. this is the first bit with messages etc. I can post more if it helps but trying to keep it to the important part.
syntax = "proto3";
option csharp_namespace = "SpaceX.API.Device";
package SpaceX.API.Device;
service Device {
//rpc Handle (.SpaceX.API.Device.Request) returns (.SpaceX.API.Device.Response) {}
//rpc Stream (stream .SpaceX.API.Device.ToDevice) returns (stream .SpaceX.API.Device.FromDevice) {}
rpc Handle (Request) returns (Response);
rpc Stream (Request) returns (Response);
}
message ToDevice {
string message = 1;
}
message Request {
uint64 id = 1;
string target_id = 13;
uint64 epoch_id = 14;
oneof request {
SignedData signed_request = 15;
RebootRequest reboot = 1001;
SpeedTestRequest speed_test = 1003;
GetStatusRequest get_status = 1004;
AuthenticateRequest authenticate = 1005;
GetNextIdRequest get_next_id = 1006;
GetHistoryRequest get_history = 1007;
GetDeviceInfoRequest get_device_info = 1008;
GetPingRequest get_ping = 1009;
SetTrustedKeysRequest set_trusted_keys = 1010;
FactoryResetRequest factory_reset = 1011;
GetLogRequest get_log = 1012;
SetSkuRequest set_sku = 1013;
UpdateRequest update = 1014;
GetNetworkInterfacesRequest get_network_interfaces = 1015;
PingHostRequest ping_host = 1016;
GetLocationRequest get_location = 1017;
EnableFlowRequest enable_flow = 1018;
GetHeapDumpRequest get_heap_dump = 1019;
RestartControlRequest restart_control = 1020;
FuseRequest fuse = 1021;
GetPersistentStatsRequest get_persistent_stats = 1022;
GetConnectionsRequest get_connections = 1023;
FlushTelemRequest flush_telem = 1026;
StartSpeedtestRequest start_speedtest = 1027;
GetSpeedtestStatusRequest get_speedtest_status = 1028;
ReportClientSpeedtestRequest report_client_speedtest = 1029;
InitiateRemoteSshRequest initiate_remote_ssh = 1030;
SelfTestRequest self_test = 1031;
SetTestModeRequest set_test_mode = 1032;
DishStowRequest dish_stow = 2002;
DishGetContextRequest dish_get_context = 2003;
DishSetEmcRequest dish_set_emc = 2007;
DishGetObstructionMapRequest dish_get_obstruction_map = 2008;
DishGetEmcRequest dish_get_emc = 2009;
DishSetConfigRequest dish_set_config = 2010;
DishGetConfigRequest dish_get_config = 2011;
StartDishSelfTestRequest start_dish_self_test = 2012;
WifiSetConfigRequest wifi_set_config = 3001;
WifiGetClientsRequest wifi_get_clients = 3002;
WifiSetupRequest wifi_setup = 3003;
WifiGetPingMetricsRequest wifi_get_ping_metrics = 3007;
WifiGetDiagnosticsRequest wifi_get_diagnostics = 3008;
WifiGetConfigRequest wifi_get_config = 3009;
WifiSetMeshDeviceTrustRequest wifi_set_mesh_device_trust = 3012;
WifiSetMeshConfigRequest wifi_set_mesh_config = 3013;
WifiGetClientHistoryRequest wifi_get_client_history = 3015;
TransceiverIFLoopbackTestRequest transceiver_if_loopback_test = 4001;
TransceiverGetStatusRequest transceiver_get_status = 4003;
TransceiverGetTelemetryRequest transceiver_get_telemetry = 4004;
}
reserved 1025, 3011, 3014;
}
message SignedData {
bytes data = 1;
bytes signature = 2;
}
My New .cs
I have tried many things from Microsoft's examples to thing I can gather from other samples. I simply can not get it to work and am lost. Again, any insight would be amazing and hopefully helpful to others looking for a solution in c#. You will see my commented code of this I have been playing with. Basically I am attempting to achieve three things and have made some movement in one of them.
Goals:
1 - Use Server Reflection to discover services.
I think I got this one resolved with dot-net grpc.
2 - Simply want to check available methods under a service and potentially either check or generate a new .proto file in case things change. StaLink does not publish its proto schema so I assume it could change anytime without warning.
3 - Just run any one of the available methods. I have tried the GetDeviceInfoRequest but can not seem to construct the request message properly. I have not been able to get this accomplishe in the gRPCurl tool either. I can do it on the basic service shown by Microsoft of course but these methods seem to be more complex and I simply get all kinds of errors.
Again, any insight or assistance would be amazing. Thanks to any and all in advance.
New .cs File
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Net.Client;
using Grpc.Reflection.V1Alpha;
using ServerReflectionClient = Grpc.Reflection.V1Alpha.ServerReflection.ServerReflectionClient;
using SpaceX.API.Device;
public class Program
{
static async Task Main(string[] args)
{
//SETUP CHANNEL AND CLIENT
using var channel = GrpcChannel.ForAddress("http://192.168.100.1:9200");
var client = new ServerReflectionClient(channel);
var StarLinkClient = new Device.DeviceClient(channel);
//using var call = StarLinkClient.StreamAsync(new ToDevice { Request = GetDeviceInfoRequest });
//await foreach (var response in call.ResponseStream.ReadAllAsync())
//var request = Device.GetDeviceInfoRequest;
//var reply = await StarLinkClient.HandleAsync(
// new Request {'"getDeviceInfo" : {} '});
//Console.WriteLine(reply.Message);
//=============================================SERVER REFLECTION=============================================================
Console.WriteLine("Calling reflection service:");
var response = await SingleRequestAsync(client, new ServerReflectionRequest
{
ListServices = "" // Get all services
});
Console.WriteLine("Services:");
foreach (var item in response.ListServicesResponse.Service)
{
Console.WriteLine("- " + item.Name);
Console.WriteLine();
var StarLink = item.Name;
//Console.WriteLine(StarLink.getStatus());
}
//=============================================SERVER REFLECTION=============================================================
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
void setupchannel()
{
}
private static Task SingleRequestAsync(ServerReflectionClient client, Metadata metadata)
{
throw new NotImplementedException();
}
private static async Task<ServerReflectionResponse> SingleRequestAsync(ServerReflectionClient client, ServerReflectionRequest request)
{
using var call = client.ServerReflectionInfo();
await call.RequestStream.WriteAsync(request);
Debug.Assert(await call.ResponseStream.MoveNext());
var response = call.ResponseStream.Current;
await call.RequestStream.CompleteAsync();
return response;
}
}
Again, thanks in advance to anyone willing to assist here. Hopefully this helps others as well.
This question is related to Google Sheets API (C#).
I have to write more than 1000 rows into a Google sheet, therefore I need to increase the number of rows (I got the Google.Apis.Requests.RequestError when I attempted to write 4640 rows).
Searching the Stack Overflow website resulted in information telling me that I needed to use UpdateSheetPropertiesRequest or InsertDimensionRequest and create a new request that could be in the same Spreadsheets.BatchUpdate call.
In line with this Python example, I set the properties of the InsertDimensionRequest instance and included them in my existing code (= publicly available C# code by Ian Preston).
The code then looks like this:
public void AddCells(GoogleSheetParameters googleSheetParameters, List<GoogleSheetRow> rows)
{
var requests = new BatchUpdateSpreadsheetRequest { Requests = new List<Request>() }; //Existing code
int sheetId = GetSheetId(_sheetsService, _spreadsheetId, googleSheetParameters.SheetName); //Existing code
InsertDimensionRequest insertDimensionRequest = new InsertDimensionRequest(); //Added code
insertDimensionRequest.Range.SheetId = sheetId; //Added code
insertDimensionRequest.Range.Dimension = "ROWS"; //Added code
insertDimensionRequest.Range.StartIndex = 999; //Added code
insertDimensionRequest.Range.EndIndex = 6999; //Added code
insertDimensionRequest.InheritFromBefore = false; //Added code
var request = new Request { UpdateCells = new UpdateCellsRequest { Start = gc, Fields = "*" } }; //Existing code
//some code here
var request1 = new Request { ???????? }; //code to be added - how should the request look like?
requests.Requests.Add(request); //Existing code
requests.Requests.Add(request1); //Added code
}
But I do not know how a new request can be created in C#.
My question is: How to create such an request (named as request1 in my code)?
Meanwhile, I have managed to figure out an answer.
DimensionRange dr = new DimensionRange
{
SheetId = sheetId,
Dimension = "ROWS",
StartIndex = 999,
EndIndex = 6999 // adding extra 6000 rows
};
var request1 = new Request { InsertDimension = new InsertDimensionRequest { Range = dr, InheritFromBefore = false } };
And then (the order of the requests matters):
requests.Requests.Add(request1);
requests.Requests.Add(request);
EDIT 01-06-2022: The entire code using the aforementioned snippet can be downloaded from GitHub - see the GoogleSheets project there.
It is also possible to use userEnteredValue. This clears the sheet and, for me inexplicably, sets the number of rows to an unknow value, but my 4640 rows were accepted.
EDIT 31-05-2022: If you know more about the usage of userEnteredValue, feel free to elaborate on this matter.
GridRange dr2 = new GridRange
{
SheetId = sheetId
};
var request2 = new Request { UpdateCells = new UpdateCellsRequest { Range = dr2, Fields = "userEnteredValue" } };
And then (the order of the requests probably also matters):
requests.Requests.Add(request2);
requests.Requests.Add(request);
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 have an invoice with multiple lines that I want to consolidate into one line. It takes the and iterates through each . It sums each to a variable. After the loop, it should create a new line on the invoice and delete the others.
I keep getting a "TxnLineID: required field is missing" even though I am providing it as "-1" for a new line:
private static void Main(string[] args)
{
// creates the session manager object using QBFC
var querySessionManager = new QBSessionManager();
// want to know if a session has begun so it can be ended it if an error happens
var booSessionBegun = false;
try
{
// open the connection and begin the session with QB
querySessionManager.OpenConnection("", "Test Connection");
querySessionManager.BeginSession("", ENOpenMode.omDontCare);
// if successful then booSessionBegin = True
booSessionBegun = true;
// Get the RequestMsgSet based on the correct QB Version
var queryRequestSet = GetLatestMsgSetRequest(querySessionManager);
// Initialize the message set request object
queryRequestSet.Attributes.OnError = ENRqOnError.roeStop;
// QUERY RECORDS **********************
// appendInvoiceQuery to request set
// only invoices that start with the consulting invoice prefix
// include all of the line items
// only unpaid invoices
var invoiceQ = queryRequestSet.AppendInvoiceQueryRq();
invoiceQ.ORInvoiceQuery.InvoiceFilter.ORRefNumberFilter.RefNumberFilter.MatchCriterion.SetValue(ENMatchCriterion.mcStartsWith);
invoiceQ.ORInvoiceQuery.InvoiceFilter.ORRefNumberFilter.RefNumberFilter.RefNumber.SetValue("ML-11");
invoiceQ.ORInvoiceQuery.InvoiceFilter.PaidStatus.SetValue(ENPaidStatus.psNotPaidOnly);
invoiceQ.IncludeLineItems.SetValue(true);
// DELETE INVOICE ***********************************
// var deleteI = queryRequestSet.AppendTxnDelRq();
// deleteI.TxnDelType.SetValue(ENTxnDelType.tdtInvoice);
// deleteI.TxnID.SetValue("3B57C-1539729221");
// Do the request and get the response message set object
var queryResponseSet = querySessionManager.DoRequests(queryRequestSet);
// Uncomment the following to view and save the request and response XML
var requestXml = queryRequestSet.ToXMLString();
// Console.WriteLine(requestXml);
SaveXML(requestXml, 1);
var responseXml = queryResponseSet.ToXMLString();
// Console.WriteLine(responseXml);
SaveXML(responseXml, 2);
// Get the statuscode of the response to proceed with
var respList = queryResponseSet.ResponseList;
var ourResp = respList.GetAt(0);
var statusCode = ourResp.StatusCode;
// Test what the status code
if (statusCode == 0)
{
// Parse the string into an XDocument object
var xmlDoc = XDocument.Parse(responseXml);
// Set the xmlDoc root
var xmlDocRoot = xmlDoc.Root.Element("QBXMLMsgsRs")
.Element("InvoiceQueryRs")
.Elements("InvoiceRet");
var i = 1;
// Iterate through the elements to get values and do some logic
foreach (var invoiceElement in xmlDocRoot)
{
// Create connection to update
var updateSessionManager = new QBSessionManager();
updateSessionManager.OpenConnection("", "Test Connection");
updateSessionManager.BeginSession("", ENOpenMode.omDontCare);
// Make the request set for updates
var updateRequestSet = GetLatestMsgSetRequest(updateSessionManager);
updateRequestSet.Attributes.OnError = ENRqOnError.roeStop;
// Set the variables required to edit a file
var txnId = (string) invoiceElement.Element("TxnID");
var editSequence = (string) invoiceElement.Element("EditSequence");
var xmlLineItemRoot = invoiceElement.Elements("InvoiceLineRet");
var feeAmount = 0.0f;
foreach (var invoiceLineItemElement in xmlLineItemRoot)
{
if (invoiceLineItemElement.Element("ItemRef").Element("FullName").Value == "Consulting Fees:Consulting")
{
feeAmount = float.Parse(invoiceLineItemElement.Element("Amount").Value) + (float) feeAmount;
}
}
//// UPDATING RECORDS ******************************
//// TxnID and EditSequence required
var invoiceM = updateRequestSet.AppendInvoiceModRq();
invoiceM.TxnID.SetValue(txnId);
invoiceM.EditSequence.SetValue(editSequence);
invoiceM.ORInvoiceLineModList.Append().InvoiceLineMod.TxnLineID.SetValue("-1");
invoiceM.ORInvoiceLineModList.Append().InvoiceLineMod.ItemRef.FullName.SetValue("Consulting Fees:Consulting");
invoiceM.ORInvoiceLineModList.Append().InvoiceLineMod.Amount.SetValue((double)feeAmount);
updateSessionManager.DoRequests(updateRequestSet);
i++;
updateSessionManager.EndSession();
updateSessionManager.CloseConnection();
}
}
// end and disconnect after done
querySessionManager.EndSession();
booSessionBegun = false;
querySessionManager.CloseConnection();
}
catch (Exception e)
{
// if it couldn't connect then display a message saying so and make sure to EndSession/CloseConnection
Console.WriteLine(e.Message.ToString() + "\nStack Trace: \n" + e.StackTrace + "\nExiting the application");
if (booSessionBegun)
{
querySessionManager.EndSession();
querySessionManager.CloseConnection();
}
}
}
Furthermore, I want it to remove the lines from the invoice that were used in the sum. I've read conflicting information on how to do this.
One camp says, don't specify those lines and it will erase them when the updateRequestSet is executed. Another contradicts by saying that not specifying them, it will retain them. Can someone please clear this up. I haven't gotten far enough to test, however.
Oh and here is the entirety of the error:
InvoiceMod
ORInvoiceLineModList:
element(2) - InvoiceLineMod:
TxnLineID: required field is missing
End of InvoiceLineMod
End of ORInvoiceLineModList
End of InvoiceMod
Stack Trace:
at Interop.QBFC13.IQBSessionManager.DoRequests(IMsgSetRequest request)
at ConsolidateInvoiceLineItems.Program.Main(String[] args) in C:\qb\QuickBooks\ConsolidateInvoiceLineItems\ConsolidateInvoiceLineItems\Program.cs:line 226
Exiting the application
Wish I could take credit for this, but actually got help from the Intuit Developers forum.
Need to change the multiple Append() to the following:
var invoiceModLineItems = invoiceM.ORInvoiceLineModList.Append().InvoiceLineMod;
invoiceModLineItems.TxnLineID.SetValue("-1");
invoiceModLineItems.ItemRef.FullName.SetValue("Consulting Fees:Consulting");
invoiceModLineItems.Amount.SetValue((double)feeAmount);
I am trying to get direction details between a source and destination by calling Google Map API XML in a web service using c#. When I try to call below function locally, it works fine. But when I deploy my code on the server, for some locations, it does not give direction details. The local System where I try is Win2K8 R2 and the web server is Win2K3. Here is my Code
public List<DirectionSteps> getDistance(string sourceLat, string sourceLong, string destLat, string destLong)
{
var requestUrl = String.Format("http://maps.google.com/maps/api/directions/xml?origin=" + sourceLat + "," + sourceLong + "&destination=" + destLat + "," + destLong + "&sensor=false&units=metric");
try
{
var client = new WebClient();
var result = client.DownloadString(requestUrl);
//return ParseDirectionResults(result);
var directionStepsList = new List<DirectionSteps>();
var xmlDoc = new System.Xml.XmlDocument { InnerXml = result };
if (xmlDoc.HasChildNodes)
{
var directionsResponseNode = xmlDoc.SelectSingleNode("DirectionsResponse");
if (directionsResponseNode != null)
{
var statusNode = directionsResponseNode.SelectSingleNode("status");
if (statusNode != null && statusNode.InnerText.Equals("OK"))
{
var legs = directionsResponseNode.SelectNodes("route/leg");
foreach (System.Xml.XmlNode leg in legs)
{
//int stepCount = 1;
var stepNodes = leg.SelectNodes("step");
var steps = new List<DirectionStep>();
foreach (System.Xml.XmlNode stepNode in stepNodes)
{
var directionStep = new DirectionStep();
directionStep.Index = stepCount++;
directionStep.Distance = stepNode.SelectSingleNode("distance/text").InnerText;
directionStep.Duration = stepNode.SelectSingleNode("duration/text").InnerText;
directionStep.Description = Regex.Replace(stepNode.SelectSingleNode("html_instructions").InnerText, "<[^<]+?>", "");
steps.Add(directionStep);
}
var directionSteps = new DirectionSteps();
//directionSteps.OriginAddress = leg.SelectSingleNode("start_address").InnerText;
//directionSteps.DestinationAddress = leg.SelectSingleNode("end_address").InnerText;
directionSteps.TotalDistance = leg.SelectSingleNode("distance/text").InnerText;
directionSteps.TotalDuration = leg.SelectSingleNode("duration/text").InnerText;
directionSteps.Steps = steps;
directionStepsList.Add(directionSteps);
}
}
}
}
return directionStepsList;
}
catch (Exception ex)
{
throw ex;
}
}
After reading many posts and google usage policy, it turns out that Google does not allow such automated queries from FQDN or any public server. I was making around 15-20 direction request which was blocked after around 10 requests. I had to change my logic and implemented the same function in mobile device and called the google maps directions api from mobile and it works perfectly !! It seems that google is not blocking such requests when they come from mobile devices. But you never know when they change it back.
You can use Google maps api
http://maps.googleapis.com/maps/api/directions/
Instaructions here: https://developers.google.com/maps/documentation/directions/
Limits:
2,500 directions requests per day.
Google Maps API for Business customers have higher limits:
100,000 directions requests per day.
23 waypoints allowed in each request.