c# how to only get updated objects from web api - c#

I'm polling data to my angular app from a c# web api. Every time all data is polled, even though much of the data haven't changed. I would like to poll only the objects which have actually been updated in any sort of way.
This is my code in my Controller.cs
//Get all details of the available vehicles
[HttpGet]
[Route("api/details")]
public object GetFleetStatusDetails()
{
var fmsData = this.fmsdb.Value.GetFleetStatusDetails();
var data = fmsData.Entries;
List<VehicleDetails> result = new List<VehicleDetails>();
foreach (var item in data)
{
if (item != null)
{
var details = ConvertVehicleDetail(item);
result.Add(details);
}
}
return result;
}
As you can see im converting the data into VehicleDetails which I later add to my VehicleDetails list. The data im getting is in JSON-format. Is there a way of comparing my last poll with the current poll without going to much deeper down into the database? If so how would I do that?

I suggest saving the last state either through the Browser's local storage or using ngrx.

Without knowing what this.fmsdb.Value.GetFleetStatusDetails(); does or the schema of the database you're calling the best guess answer would be to create two endpoints in the API.
The first would use this.fmsdb.Value.GetFleetStatusDetails(); to get the full set of results. Once the data has been downloaded from the endpoint store the current date/time in the angular view and pass that to the second endpoint...
The second endpoint would get the records that have been changed since the date/time you got the first set of data. This assumes that you are storing the updated date time.
[HttpGet]
[Route("api/updateddetails")]
public object GetUpdatedFleetStatusDetails([FromUrl]DateTime date)
{
var fmsData = this.fmsdb.Value.GetUpdatedFleetStatusDetails(date);
return fmsData.Entries
.Where(x => x != null)
.Select(ConvertVehicleDetail);
}
Could give more details if knew what was in this.fmsdb.Value.GetFleetStatusDetails()
PS Haven't tested this code.

Related

Foreach in not iterating through values

I am developing an application where I have to perform some update operation on each machine in the database. Every machine has a unique Id. Then there is also an area code under which several machines come. Area codes are also unique. I am reading these ids from the database and storing them in a list and then I want to hit the API one by one using these Ids. The API will give me a response which I have to read and update the database accordingly . I am using foreach but I don't know what mistake I am doing that it is not iterating to the second element(second id) of the list and I am not able to call the function with the 2nd Id to hit the API.
public static void ProcessIds(string areacode1, string areacode2)
{
// this is working fine I am getting correct values
List<IntermediateAPIRequest.IntermediateIds> Ids =
GetIntermediateIDList(areacode1, areacode2);
APIRequest apiRequest = new APIRequest();
foreach (IntermediateAPIRequest.IntermediateIds id in Ids)
{
//code for creating API request--this now fetches the 1st Id from
// the list and creates the request
APIresponse result = GetAPIResponsePerID(URL, id.machineID, apiRequest);
//Code for dealing with the response, for the time being I am
// simply displaying it onto the console.
} // end of foreach loop
}
I am able to read the response properly. The main issue is that I am not able to call the api with the 2nd value in the list.
Please let me know if I need to add more code for clarification.

Microsoft Graph SDK Request Next Link of the Batch Response

I am using Microsoft Graph SDK to create a batch request that contains individual requests to request 20 different users. When I call GetNextLinkAsync() the result is always null. I have tried requesting 1000 different users using batch requests each containing 20 individual requests. This works fine, response is always returned in a single batch response.
I couldn't understand why the response is returned in single batch response content rather than giving me the link to fetch the next response?
Even though next link is null always, how can I follow it using Graph SDK? It is a string. It's not like next page request.
foreach (var batchRequest in batchRequests)
{
try
{
var responses = await PostBatchRequest(batchRequest.Request);
foreach (var id in batchRequest.RequestIds)
{
try
{
var user = await responses.GetResponseByIdAsync<User>(id);
users.Add(user.UserPrincipalName, user.Id);
} catch (ServiceException e)
{
logger.LogInformation(e.StatusCode);
}
}
} catch (ServiceException e)
{
logger.LogInformation(e.StatusCode);
}
}
I couldn't find proper documentation that tells you how to follow next link using Graph SDK or why it is always null for this type of requests, or are there any special type of requests for which next link is returned?
So a lot of this is framework stuff that's inside my wrapper classes, but the crux of the solution to your issue should be inside here:
var results = await batch.ParseAsync<ContactFolderContactsCollectionResponse, IContactFolderContactsCollectionPage>(response => {
var page = response.Value;
if (response?.AdditionalData != null && response.AdditionalData.ContainsKey("#odata.nextLink"))
{
page.InitializeNextPageRequest(Application.GraphConnection.Client, (string)response.AdditionalData["#odata.nextLink"]);
}
return page;
});
In this snippet I'm parsing out a ContactFolderContactsCollectionResponse from a batch with steps generated from a get request that would normally return a IContactFolderContactsCollectionPage. The ContactFolderContactsCollectionResponse is fetched by the wrapper internals using
GetResponseByIdAsync<ContactFolderContactsCollectionResponse>(id)
So it's pretty analogous to what you're doing except that there is probably some kind of UserResponse type that you should probably be using instead of User.
In my case the ContactFolderContactsCollectionResponse contains the IContactFolderContactsCollectionPage I actionally want in the Vvalue property hence:
var page = response.Value;
Now, IContactFolderContactsCollectionPage normally has a NextPageRequest property, but when you parse it directly from the ContactFolderContactsCollectionResponse, this is not filled out. Luckily, we can find the raw #odata.nextPage link in the ContactFolderContactsCollectionResponse's AdditionalData dictionary, and we can set it using the IContactFolderContactsCollectionPage.InitializeNextPageRequest methhod.
Hence the :
if (response?.AdditionalData != null && response.AdditionalData.ContainsKey("#odata.nextLink"))
{
page.InitializeNextPageRequest(Application.GraphConnection.Client, (string)response.AdditionalData["#odata.nextLink"]);
}
Hopefully that give you enough thread to pull on. Sorry if the rest of the syntax is confusing, as I said, a lot of it is operating in a wrapper framework I'm building and I
don't have time to build and test a clean solution.
It's also possible that the whole thing is different anyway on account of you having a batch with a thousand steps as opposed to a batch whose steps return thousands of objects like as in my case.
Either way, happy hunting.

Send and return variable with c# API call?

I have a c# script task in an ssis package designed to geocode data through my company's proprietary system. It currently works like this:
1) Pull query of addresses and put in data table
2) Loop through that table and Foreach row, build request, send request, wait for response, then insert back into the database.
The issue is that each call takes forever to return, because before going out and getting a new address on the api side, it checks a current database(string match) to ensure the address does not already exist. If not exists, then go out and get me new data from a service like google.
Because I'm doing one at a time, it makes it easy to keep the ID field with the record when I go back to insert it into the database.
Now comes the issue at hand... I was told to configure this as multi-thread or asynchronous. Here is the page I was reading on here about this topic:
ASP.NET Multithreading Web Requests
var urls = new List<string>();
var results = new ConcurrentBag<OccupationSearch>();
Parallel.ForEach(urls, url =>
{
WebRequest request = WebRequest.Create(requestUrl);
string response = new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd();
var result = JsonSerializer().Deserialize<OccupationSearch>(new JsonTextReader(new StringReader(response)));
results.Add(result);
});
Perhaps I'm thinking about this wrong, but if I send 2 requests(A & B) and lets say B actually returns first, how can I ensure that when I go back to update my database I'm updating the correct record? Can I send the ID with the API call and return it?
My thoughts are to create an array of requests, burn through them without waiting for a response and return those value in another array, that I will then loop through on my insert statement.
Is this a good way of going about this? I've never used Parrallel.ForEach, and all the info I find on it is too technical for me to visualize and apply to my situation.
Perhaps I'm thinking about this wrong, but if I send 2 requests(A & B) and lets say B actually returns first, how can I ensure that when I go back to update my database I'm updating the correct record? Can I send the ID with the API call and return it?
None of your code contains anything that looks like an "ID," but I assume everything you need is in the URL. If that is the case, one simple answer is to use a Dictionary instead of a Bag.
List<string> urls = GetListOfUrlsFromSomewhere();
var results = new ConcurrentDictionary<string, OccupationSearch>();
Parallel.ForEach(urls.Distinct(), url =>
{
WebRequest request = WebRequest.Create(url);
string response = new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd();
var result = JsonSerializer().Deserialize<OccupationSearch>(new JsonTextReader(new StringReader(response)));
results.TryAdd(url, result);
});
After this code is done, the results dictionary will contain entries that correlate each response back to the original URL.
Note: you might want to use HttpClient instead of WebClient, and you should take care to dispose of your disposable objects, e.g. StreamReader and StringReader.

couchbase lite xamarin pull replication with sync-gateway

I want to pull documents with username attribute
as user1 for user1 like that for each user only attribute with their name.
This is my replication code.
private void setupreplication(){
Console.WriteLine ("Setting up replication");
Uri Server = new Uri("http://192.168.1.213:4984/aussie-coins-syncgw/");
var pull = _db.CreatePullReplication (Server);
var push = _db.CreatePushReplication (Server);
pull.Filter = "byUser";
pull.FilterParams = new Dictionary<string, object> { {"type", "user1"} };
pull.Continuous = true;
push.Continuous = true;
pull.Start();
push.Start();
}
This is my set filter code
_couchBaseLiteLocal.SetFilter("byUser", (revision, filterParams) =>
{
var typeParam = filterParams["type"].ToString();
return (typeParam != null) && typeParam.Equals("user1");
});
With the above code generic pull itself not working.
I just tried to do as given in the documentation.
I do not understand how the setfilter function works to filter data from server. It would be great if someone help in understanding how setfilter works and to make the above code working
Thanks in advance.
The filter function in pull replications can indeed return the specific documents you are interested in. But it's not very efficient, the filter function will run on all the documents on the remote database to determine which ones to pull, every time a pull replication is started.
Instead Sync Gateway introduces the concept of a sync function that incrementally routes and computes access control rules on documents. That way, when starting the pull replication, it's fast and straightforward for Sync Gateway to return the specific documents the user has access to.
You can specify individual channels in a pull replication from Sync Gateway if needed. But the thing to remember is that filtered pull replication between Sync Gateway and Couchbase Lite is not based on filter functions. It's based on the sync function and channel based filtering if needed.
In a P2P scenario (replications between two Couchbase Lite instances), the filter function model is used.

How to persist keeping the info in the Session["Stuff"]?

When the user makes selection and clicks a button, I call to:
public ActionResult Storage(String data)
{
Session["Stuff"] = data;
return null;
}
Then, I redirect them to another page where the data is accessed by
#Session["Stuff"]
This far, I'm happy. What I do next is that upon a click on a button on the new page, I perform a call to:
public ActionResult Pdfy()
{
Client client = new Client();
byte[] pdf = client.GetPdf("http://localhost:1234/Controller/SecondPage");
client.Close();
return File(pdf, "application/pdf", "File.pdf");
}
Please note that the PDFization itself works perfectly well. The problem is that when I access the second page a second time (it's beeing seen by the user and looks great both in original and on reload), it turns out that Session["Stuff"] suddenly is null!
Have I started a new session by the recall?
How do I persistently retain data stored in Session["Stuff"] before?
If you're simply storing string data (as would be indicated by your method signature) in an MVC application, don't.
It's far easier to pass the data as a query parameter to each method that needs it. It's far easier to manage and doesn't rely on Session sticky-ness.
To generate the appropriate links, you can pass data to your views and use Html.ActionLink to generate your links with the appropriate parameter data.
Here's several reasons why the session variable could return null:
null is passed into Storage
Some other code sets Session["Stuff"] to null
The session times out
Something calls Session.Clear() (or Session.Abandon())
The underlying AppPool is restarted on the server
Your web server is farmed and session state is not distributed properly
The first two can be discovered by debugging.

Categories