Issues with Cefsharp and foreach loop - c#

I'm new to working with async and I'm trying to build a Cefsharp application that collects data from an external API, stores it in local variables and then exports these through JavaScript to HTML. It's not a beautiful implementation and I'm sure my code is pretty awful but here goes:
My application performs a tick every 5 seconds, where it executes a HTTP Post request and stores the result in a QuickType (app.quicktype.io) list. This is the tick:
private async void timer1_Tick(object sender, EventArgs e)
{
await chromeBrowser.WaitForInitialLoadAsync();
if (httpPost.ConnectionSuccesful())
{
var devtoolsContext = await chromeBrowser.CreateDevToolsContextAsync();
var postResult = await httpPost.SendPost("robot_info");
try {
var result = Welcome.FromJson(postResult);
foreach (var robot in result.Result.Robots.Select((value, i) => (value, i)))
{
Console.WriteLine(robot.value.Id);
if (robot.value.ChargingStateCode == 9 || robot.value.ChargingStateCode == 12)
await devtoolsContext.EvaluateFunctionAsync("function setBatteryCharge() { var batteryLevel = jQuery('#robot" + robot.i + "Charge'); batteryLevel.css('width', "+ robot.value.StateOfCharge + " + '%'); batteryLevel.text('Charging'); batteryLevel.addClass('high'); batteryLevel.removeClass('medium'); batteryLevel.removeClass('low'); }");
else if (robot.value.StateOfCharge > 75)
await devtoolsContext.EvaluateFunctionAsync("function setBatteryHigh() { var batteryLevel = jQuery('#robot" + robot.i + "Charge'); batteryLevel.css('width', " + robot.value.StateOfCharge + " + '%'); batteryLevel.text(" + robot.value.StateOfCharge + " + '%'); batteryLevel.addClass('high'); batteryLevel.removeClass('medium'); batteryLevel.removeClass('low'); }");
else if (robot.value.StateOfCharge >= 50)
await devtoolsContext.EvaluateFunctionAsync("function setBatteryMedium() { var batteryLevel = jQuery('#robot" + robot.i + "Charge'); batteryLevel.css('width', " + robot.value.StateOfCharge + " + '%'); batteryLevel.text(" + robot.value.StateOfCharge + " + '%'); batteryLevel.addClass('medium'); batteryLevel.removeClass('high'); batteryLevel.removeClass('low'); }");
else
await devtoolsContext.EvaluateFunctionAsync("function setBatteryLow() { var batteryLevel = jQuery('#robot" + robot.i + "Charge'); batteryLevel.css('width', " + robot.value.StateOfCharge + " + '%'); batteryLevel.text(" + robot.value.StateOfCharge + " + '%'); batteryLevel.addClass('low'); batteryLevel.removeClass('high'); batteryLevel.removeClass('medium'); }");
}
}
catch (ArgumentNullException Nex) {
Console.Write("[Error] - " + Nex.Message);
}
catch (Exception ex)
{
Console.WriteLine("[Error] - " + ex.Message);
}
}
else
Console.WriteLine("[Error] - Check connection or access to API server.");
}
I'm currently trying to update the battery level and it successfully does this for the first tick (the JavaScript works as intended and both the css, classes and text is changed). Then it stops working. I've checked that the correct results are coming in from the HTTP Post and that the data is stored properly in the local variables. The problem seems to occur in the foreach. I've tried to read up about async a bit but I can't seem to find the culprit. After the first execution of the code, something seems to be blocking the iteration of the for each. I'm using Cefsharp.Winforms and Cefsharp.Puppeteer.
Any idea on why this is happening? Also thankful for any pointers or tips on how to improve the code.
EDIT: This is the Console Output
[Query] Sending post request to xxx with method 'robot_info'
[Success] - API Post Request was succesful.
PR1#11
PR1#15
[Query] Sending post request to xxx with method 'robot_info'
[Success] - API Post Request was succesful.
PR1#11
[Query] Sending post request to xxx with method 'robot_info'
[Success] - API Post Request was succesful.
PR1#11
The first iteration goes through fine.
EDIT2: This is the timer
public void InitTimer()
{
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = 5000;
timer1.Start();
}
EDIT3: Method SendPost
public async Task<string> SendPost(string method)
{
HttpClient httpClient = new HttpClient();
string data = new JavaScriptSerializer().Serialize(new
{
jsonrpc = "2.0",
method = method,
id = Guid.NewGuid().ToString()
});
StringContent content = new StringContent(data, System.Text.Encoding.UTF8, "application/json");
try
{
Console.WriteLine("[Query] Sending post request to " + url.ToString() + " with method '" + method + "'");
HttpResponseMessage response = await httpClient.PostAsync(url, content).ConfigureAwait(false);
string result = await response.Content.ReadAsStringAsync();
if (IsValidJson(result))
{
Console.WriteLine("[Success] - API Post Request was succesful.");
return result;
}
else
return null;
} catch (HttpRequestException hre)
{
Console.WriteLine("[Error]: " + hre);
return null;
}
}
EDIT4: Structure of Welcome
public partial class Welcome
{
[JsonProperty("jsonrpc")]
public string Jsonrpc { get; set; }
[JsonProperty("result")]
public Result Result { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
}
public partial class Result
{
[JsonProperty("timestamp")]
public long Timestamp { get; set; }
[JsonProperty("robots")]
public List<Robot> Robots { get; set; }
}
Robots is a list with a bunch of longs and ints.

Related

Trying to move the output of method to the output of variable

I am working on Azure Function (Http Trigger), and came across with this task.
I am trying to display the output of method (ListVendors.Run(logger)) into inside variable (responseMessage) so that the values would be carried into Http post.
public static class Function1
{
[FunctionName("HttpTrigger_1111_1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
///Calling from other method starts:
ILogger logger = Bootstrap.Logger("Program");
ListVendors.Run(logger);
///Calling from other method ends:
log.LogInformation("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
string responseMessage = string.IsNullOrEmpty(name)
? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
: $"Hello, {name}. This HTTP triggered function executed successfully.";
return new OkObjectResult(responseMessage);
}
}
Basically, I am trying to insert the output of:
ListVendors.Run(logger);
Inside "responseMessage".
return new OkObjectResult(responseMessage);
How do I modify the code to do that?
Bottom is code for ListVendors:
public static class ListVendors
{
public static void Run(ILogger logger)
{
OnlineClient client = Bootstrap.Client(logger);
ReadByQuery query = new ReadByQuery()
{
ObjectName = "VENDOR",
PageSize = 2, // Keep the count to just 2 for the example
Fields =
{
"RECORDNO",
"VENDORID",
}
};
logger.LogInformation("Executing query to Intacct API");
Task<OnlineResponse> task = client.Execute(query);
task.Wait();
OnlineResponse response = task.Result;
Result result = response.Results[0];
try
{
dynamic json = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(result.Data));
string jsonString = json.ToString();
logger.LogDebug(
"Query successful - page 1 [ Total count={0}, Data={1} ]",
result.TotalCount,
jsonString
);
Console.WriteLine("Page 1 success! Number of vendor objects found: " + result.TotalCount + ". Number remaining: " + result.NumRemaining);
} catch (NullReferenceException e)
{
logger.LogDebug("No response in Data. {0}", e);
}
LogManager.Flush();
int i = 1;
while (result.NumRemaining > 0 && i <= 3 && !string.IsNullOrEmpty(result.ResultId))
{
i++;
ReadMore more = new ReadMore()
{
ResultId = result.ResultId
};
Task<OnlineResponse> taskMore = client.Execute(more);
taskMore.Wait();
OnlineResponse responseMore = taskMore.Result;
Result resultMore = responseMore.Results[0];
try
{
dynamic resultMoreJson =
JsonConvert.DeserializeObject(JsonConvert.SerializeObject(resultMore.Data));
string resultMoreJsonString = resultMoreJson.ToString();
logger.LogDebug(
"Read More successful - page " + i + " [ Total remaining={0}, Data={1} ]",
resultMore.NumRemaining,
resultMoreJsonString
);
Console.WriteLine("Page " + i + " success! Records remaining: " + resultMore.NumRemaining);
}
catch (NullReferenceException e)
{
logger.LogDebug("No response in Data. {0}", e);
}
finally
{
LogManager.Flush();
}
}
Console.WriteLine("Successfully read " + i + " pages");
}
}
}

return string after a request to firebase in Unity / c#

Does anyone know how to return a value of a get to a Firebase Database after it is completed?
I want for example to return the string "extracted.pl_superhit" to another class and it's an async process...
public void LoadData_element(string player)
{
FirebaseApp.DefaultInstance.SetEditorDatabaseUrl(DATA_URL);
FirebaseDatabase.DefaultInstance.GetReferenceFromUrl(DATA_URL).GetValueAsync()
.ContinueWith((task =>
{
if (task.IsFaulted)
{
print("Falhou o Load dos dados");
}
if (task.IsCanceled)
{
print("Cancelou o load dos dados");
}
if (task.IsCompleted)
{
DataSnapshot datasnap = task.Result;
string pData = datasnap.GetRawJsonValue();
var humidval = datasnap.Child(player).GetRawJsonValue();
string test = humidval.ToString();
print("x:" + test);
Firebase_Database_Player extracted = JsonUtility.FromJson<Firebase_Database_Player>(test);
print("Player_name:" + extracted.pl_name);
print("Player_lfbar:" + extracted.pl_lfbar);
print("Player_hit:" + extracted.pl_hit);
print("Player_superhit:" + extracted.pl_superhit);
print("Player_defend:" + extracted.pl_defend);
print("Player_atuallife:" + extracted.pl_atuallife);
print("Player_atualattack:" + extracted.pl_atualattack);
}
}));
}
thanks
Make the function async and await the necessary calls
public async Task<string> LoadData_element(string player) {
FirebaseApp.DefaultInstance.SetEditorDatabaseUrl(DATA_URL);
var reference = FirebaseDatabase.DefaultInstance.GetReferenceFromUrl(DATA_URL);
DataSnapshot datasnap = await reference.GetValueAsync()
string pData = datasnap.GetRawJsonValue();
var humidval = datasnap.Child(player).GetRawJsonValue();
string test = humidval.ToString();
print("x:" + test);
Firebase_Database_Player extracted = JsonUtility.FromJson<Firebase_Database_Player>(test);
print("Player_name:" + extracted.pl_name);
print("Player_lfbar:" + extracted.pl_lfbar);
print("Player_hit:" + extracted.pl_hit);
print("Player_superhit:" + extracted.pl_superhit);
print("Player_defend:" + extracted.pl_defend);
print("Player_atuallife:" + extracted.pl_atuallife);
print("Player_atualattack:" + extracted.pl_atualattack);
return extracted.pl_superhit;
}

Xamarin forms Crash when user exit screen and come back after PUT process

My XF app crash when user try to open any screen after finishing update data in one specific screen, the others works well.
Only I got is :
"08-20 23:41:19.211 W/art (15347): JNI RegisterNativeMethods: attempt to register 0 native methods for android.runtime.JavaProxyThrowable".
No HokeyApp message received in my email and no extra information appears so I can solve the problem, just crash and close the app.
I tried to decrease the amount of requests to local database, tried to follow step by step the execution process so I could get any clue about causes.
Task act = Task.Run(async () => await App.DataService.UpdateItemAsync(CP, ToServer, "Contact_Party/EditContact_Party/" + CP.Id));
await act.ContinueWith(async (antecedent) =>
{
foreach (var sam in specialty)
{
if (CP.Id > 0)
{
sam.Cntct_SEQ = CP.Id;
}
else
{
sam.Tmp_Cntct_SEQ = CP.Cntct_SEQ;
}
if (sam.Id == 0)
{
if (sam.Cntct_Spec_SEQ == 0)
await App.DataService.CreateItemAsync(sam, ToServer, "Contact_Specialty/AddContact_Specialty");
else
{
await App.DataService.UpdateItemAsync(sam, ToServer, "Contact_Specialty/EditContact_Specialty/" + sam.Id);
}
}
else
{
await App.DataService.UpdateItemAsync(sam, ToServer, "Contact_Specialty/EditContact_Specialty/" + sam.Id);
}
}
}, TaskContinuationOptions.None);
Below is the other code or the final step in Update data...
public async Task<T> UpdateItemAsync<T>(T item, bool ToServer, string url) where T : BaseModel, new()
{
try
{
HttpResponseMessage hrm = new HttpResponseMessage();
if (!CrossConnectivity.Current.IsConnected)
ToServer = false;
if (ToServer)
{
RestURL = PrimaryRestURL;
RestURL += url;
var content = JsonConvert.SerializeObject(item);
content = content.Replace("null", " ");
try
{
hrm = await _client.PutAsync(RestURL, new StringContent(content, System.Text.Encoding.UTF8, "application/json"));
RestURL = PrimaryRestURL;
}
catch (Exception hre)
{
RestURL = PrimaryRestURL;
ContentPage page = new ContentPage();
string inner = "", source = "", trace = "", data = "";
if (hre.InnerException != null)
inner = hre.InnerException.Message;
data = hre.Data.ToString();
source = hre.Source;
trace = hre.StackTrace;
string msg = "RestURL: " + RestURL + "\n\n Data: " + data + "\n\n Message: " + hre.Message + "\n\n Source: " + source + "\n\n Trace: " + trace + "\n\n Inner Message: " + inner;
await page.DisplayAlert("Error", msg, "Ok");
}
if (hrm.StatusCode == System.Net.HttpStatusCode.OK || hrm.StatusCode == System.Net.HttpStatusCode.NoContent)
{
item.Updated = true;
await database.UpdateAsync(item);
DependencyService.Get<IMessage>().LongAlert("Completed");
}
else
{
item.Changed = true;
await database.UpdateAsync(item);
DependencyService.Get<IMessage>().LongAlert("Error connection to server");
}
}
else
{
item.Changed = true;
await database.UpdateAsync(item);
DependencyService.Get<IMessage>().LongAlert("Completed");
}
}
catch (Exception xc)
{
ContentPage page = new ContentPage();
string inner = "", source = "", trace = "", data = "";
if (xc.InnerException != null)
inner = xc.InnerException.Message;
data = xc.Data.ToString();
source = xc.Source;
trace = xc.StackTrace;
string msg = "RestURL: " + RestURL + "\n\n Data: " + data + "\n\n Message: " + xc.Message + "\n\n Source: " + source + "\n\n Trace: " + trace + "\n\n Inner Message: " + inner;
await page.DisplayAlert("Error", msg, "Ok");
}
return item;
}
Finally, I solved the issue, it was because I wanted to make the process of updating in a task so being continues with sub updates, after implementeing each update process alone it work ... the code that produced the issue is:
Task act = Task.Run(async () => await App.DataService.UpdateItemAsync(CP, ToServer, "Contact_Party/EditContact_Party/" + CP.Id));
await act.ContinueWith(async (antecedent) =>
{
foreach (var sam in specialty)
{
if (CP.Id > 0)
{
sam.Cntct_SEQ = CP.Id;
}
else
{
sam.Tmp_Cntct_SEQ = CP.Cntct_SEQ;
}
if (sam.Id == 0)
{
if (sam.Cntct_Spec_SEQ == 0)
await App.DataService.CreateItemAsync(sam, ToServer, "Contact_Specialty/AddContact_Specialty");
else
{
await App.DataService.UpdateItemAsync(sam, ToServer, "Contact_Specialty/EditContact_Specialty/" + sam.Id);
}
}
else
{
await App.DataService.UpdateItemAsync(sam, ToServer, "Contact_Specialty/EditContact_Specialty/" + sam.Id);
}
}
}, TaskContinuationOptions.None);

Sending a response to HTTP POST made by a third-party

I'm working with a third-party who are posting information via HTTP POST to a .NET site I host locally. The POST is successful but I need to have the site send a success/failure response to the POST.
I have looked around but have been unable to find any suggestions to meet this need.
Please let me know if I can further clarify anything.
Thank you.
Edit: To include the code.
if (!string.IsNullOrEmpty(nvc["id"]) )
{
/* Populate the variables with the POST data
* Check first that the data is not empty or null */
if (!string.IsNullOrEmpty(nvc["id"]))
{ leadID = nvc["id"]; }
if (!string.IsNullOrEmpty(nvc["FN"]))
{ fn = nvc["FN"]; }
if (!string.IsNullOrEmpty(nvc["LN"]))
{ ln = nvc["LN"]; }
if (!string.IsNullOrEmpty(nvc["EMAIL"]))
{ email = nvc["EMAIL"]; }
if (!string.IsNullOrEmpty(nvc["PHONE"]))
{ phone = nvc["PHONE"]; }
if (!string.IsNullOrEmpty(nvc["ADDRESS"]))
{ address = nvc["ADDRESS"]; }
if (!string.IsNullOrEmpty(nvc["CITY"]))
{ city = nvc["CITY"]; }
if (!string.IsNullOrEmpty(nvc["STATE"]))
{ state = nvc["STATE"]; }
if (!string.IsNullOrEmpty(nvc["ZIP"]))
{ zip = nvc["ZIP"]; }
if (!string.IsNullOrEmpty(nvc["GENDER"]))
{ gender = nvc["GENDER"]; }
if (!string.IsNullOrEmpty(nvc["BIRTHDAY"]))
{ birthday = nvc["BIRTHDAY"]; }
if (!string.IsNullOrEmpty(nvc["TB"]))
{ tobacco = nvc["tobacco"]; }
// if (!string.IsNullOrEmpty(nvc["PPCSource"]))
// { PPCSource = nvc["PPCSource"]; }
if (!string.IsNullOrEmpty(nvc["GC_Source"]))
{ GC_Source__c = nvc["GC_Source"]; }
if (!string.IsNullOrEmpty(nvc["GC_Medium"]))
{ GC_Medium__c = nvc["GC_Medium"]; }
if (!string.IsNullOrEmpty(nvc["GC_Term"]))
{ GC_Term__c = nvc["GC_Term"]; }
if (!string.IsNullOrEmpty(nvc["GC_Content"]))
{ GC_Content__c = nvc["GC_Content"]; }
if (!string.IsNullOrEmpty(nvc["GC_Campaign"]))
{ GC_Campaign__c = nvc["GC_Campaign"]; }
if (!string.IsNullOrEmpty(nvc["GC_Custom_Segment"]))
{ GC_Custom_Segment__c = nvc["GC_Custom_Segment"]; }
if (!string.IsNullOrEmpty(nvc["GC_Num_of_Visits"]))
{ GC_Num_of_Visits__c = nvc["GC_Num_of_Visits"]; }
googleCookie = "Source: " + GC_Source__c + "; Medium: " + GC_Medium__c + "; Term: " + GC_Term__c + "; Content: " + GC_Content__c + "; Camp: " + GC_Campaign__c + "; Segment: " + GC_Custom_Segment__c + "; Visits: " + GC_Num_of_Visits__c;
GC_Source__c = "PPCSource";
if (ln != null & !string.IsNullOrEmpty(ln))
{
/* Call SetClientFunction with the POST Parameters Passed */
string result = SetClient(leadID, fn, ln, email, phone, address,city, state, zip, gender, birthday, tobacco, PPCSource, googleCookie, 0, GC_Source__c, GC_Medium__c, GC_Term__c);
SendNotice(GC_Source__c, fn, ln, result);
}

C# paypal IPN communication

I've set up the IPN to communicate with my website within Paypal, but for some reason paypal does not seem to call it. Below is the method that is listening, but its does not seem to get anything.
Could someone please point me in the write direction?
Thanks
[HttpPost]
public void paypalipn(string receiver_email, string receiver_id, string test_ipn, string txn_id, string payer_id, string payer_status, string payment_date, string payment_status, string payment_type)
{
string subject = "Audit - Paypal IPN ";
string buildemail = "receiver_email: " + receiver_email;
buildemail += "receiver_id: "+receiver_id;
buildemail += "<br>test_ipn: "+test_ipn;
buildemail += "<br>txn_id: " + txn_id;
buildemail += "<br>payer_id: " + payer_id;
buildemail += "<br>payer_status: " + payer_status;
buildemail += "<br>payment_date: " + payment_date;
buildemail += "<br>payment_status: " + payment_status;
buildemail += "<br>payment_type: " + payment_type;
Libraries.Email.Product.SendAudit(subject, buildemail);
}
If you are setting your IPN in your PayPal account, make sure that it is enabled and that the URL is correct. Also, if you are setting it in your account you can check your IPN history to see if the IPN POSTs are being sent out. They will either be marked as sent, retrying, or failed. If they are in a failed or retrying status you can click the message and if your server is sending back any error code it should be listed here. Also, check your error logs on your server to make sure the script is not erroring out.
I did something like this:
public class IPNData
{
public string Response { get; set; }
public NameValueCollection Args { get; set; }
}
Then a method for collecting data from the request, and sends the data to Paypal for verification.
IPNData GetIPNData()
{
var ipnData = new IPNData();
var param = Request.BinaryRead(HttpContext.Request.ContentLength);
var ipnStr = Encoding.ASCII.GetString(param);
ipnData.Args = HttpUtility.ParseQueryString(ipnStr);
// Return the ipn string to paypal for validation
ipnStr += "&cmd=_notify-validate";
var request = (HttpWebRequest)WebRequest.Create("https://www.paypal.com/cgi-bin/webscr");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = strRequest.Length;
using (var sw = new StreamWriter(request.GetRequestStream(), Encoding.ASCII))
{
sw.Write(ipnStr);
}
using (var sr = new StreamReader(request.GetResponse().GetResponseStream()))
{
// Response should be "VERIFIED"
ipnData.Response = sr.ReadToEnd();
}
return ipnData;
}
PaymentController.cs example for a subscriptionpayment, or if a user cancel a subscription.
public ActionResult PaypalIPNExample()
{
var ipn = GetIPNData();
if (ipn.Response != "VERIFIED")
{
// Do some logging
return null;
}
var type = ipn.Args["txn_type"];
var email = ipn.Args["payer_email"];
var transactionId = ipn.Args["txn_id"];
switch (type)
{
case "subscr_cancel":
UserService.CancelSubscription(email);
break;
case "subscr_payment":
if (ipn.Args["payment_status"].Equals("Completed"))
{
LogPayment(email, transactionId);
UserService.ExtendMembership(email);
}
break;
default:
// Do some logging?
break;
}
return Json("ok");
}
When I was debugging PayPal IPN responses, I did something like this:
string keysReceived = "";
foreach (string key in Request.Params.AllKeys)
keysReceived += "\r\nKey: " + key + ", Val: " + Request.Params[key];
string debugLogPath = HttpContext.Server.MapPath("/") + "debug_PayPalNotify.log";
System.IO.File.AppendAllText(debugLogPath, keysReceived);
Note the use of the global object Request. You can do a lot with that for debugging.

Categories