Alert Notification in asp.net c# through loop - c#

How to display an alert box in UI from code behind through for loop?
I have a function that processes data from the CSV file and writes logs into the database. I also want to show a notification or alert in the UI so that I can know instantly what's happening in the system. I tried toast notification and alert but it only displays once after the loop finished.
Here is my code:
AddLog(finalJobId, taskId, "Sending batch to Payment Gateway # of Records:" + JobCount + " from" + txtCSVFile.Text);
for (int i = 0; i < JobCount; i++)
{
var items = csvLists[i];
Page.ClientScript.RegisterStartupScript(this.GetType(), "ShowMessage", string.Format("<script type='text/javascript'>alert('{0}')</script>", "The Payment is being proceed for : " + items["First Name"] + " " + items["Last Name"]));
var paymentId = items["Payment Id"];
var clientId = items["Client Id"];
var client = items["Client Name"];
var amount = items["Total Payment Amount"];
var method = items["Payment Method"];
AddLog(finalJobId, taskId, "Sending payment #" + i + "- Client: " + client + " - PaymentId: " + paymentId + " - Amount: " + amount + " - Payment Method: " + method);
//Process Actual Payment Options with Details
var task = ProcessPayment.Process(int.Parse(clientId), int.Parse(paymentId), serverValue);
AddLog(finalJobId, taskId, "Received Response #" + i + " - Client: " + client + " - PaymentId: " + paymentId + " - Amount: " + amount + " - Payment Method: " + method + " - Result: " + task.Result.Response);
}
AddLog(finalJobId, taskId, "Completed batch for Payment Request # of Records:" + JobCount);
I usually have more than 200 records in the CSV file, so I have to wait for a while after process a payment. I don't know what is the best way to shows a notification so that users will understand what is happening at the moment.

Ok, the most easy way to figure this out?
Well, when you click on a button, the page (post back) is sent to the server.
You code runs - and all code behind is BLOCKED until it is done.(you can NOT make additional calls from that web page. The web page is sitting "stuck" on server side land, waiting for code to finish.
When code does finally finish, the page is sent BACK down to the client side.
So, obviously this line of code can't work:
Page.ClientScript.RegisterStartupScript(this.GetType(), "ShowMessage" bla bla
Since, after above, the long delay code runs. ONLY AFTER that long running code is finished, then does the code stub finish, and THEN the WHOLE PAGE is sent back down to the client. (including the above idea of wanting to run some js - that will only start running after the page is sent down BACK to the client side.
So, there are as many ways to do this as their are flavors of ice cream, but the MOST simple?
Well, whatever button they click on that starts your above code simply has to show your toast message client side BEFORE the post back.
Thus, you pop up the toast, and THEN your code behind runs. We don't even have to write code to dismiss/hide/close/remove the message, since when the page comes rolling down back down the pipe to the browser?
Well the whole page is re-loaded for you in the client, and thus your toast message will go away.
This is thus the "most" easy. But it does mean the web page is blocked quite much from interaction and we ARE waiting for a whole copy of that page to come zooming down from the server WHEN that long running code is finally finished.
So, super simple:
We assume you have a asp.net button on the form.
We assume the user going to click on that button, and then run your code.
Note that the web page travels back up to the server and THEN your code runs.
The web page is not coming back to client side until that code runs and is done.
As noted, we can use this effect to our advantage.
So, your asp button click can use OnClientClick(). This means that the client side code (js) will run BEFORE your server (code behind runs) on that button click.
And it also runs before the post back to server occurs. (web page travel to server).
So, we use this to display a "div", or fill out a text box, or in your case some toast message.
So, button code will be:
<asp:Button ID="Button2" runat="server" Text="Confirm my order"
OnClientClick="GoGo2()" />
So the above is our lovable standard asp button. But, note the "OnClientClick".
So, it will run both client side and server side events. But it WILL FIRST run the client side code we call (the client side routine called GoGo2()).
That client side routine can thus display the message.
Above calls our client side code stub, say this:
<script>
function GoGo2() {
$.toast({
heading: "Working",
text: 'Processing order - - please wait',
hideAfter: false,
position: 'top-right',
icon: 'info'
})
}
</script>
Now, of course you could get/grab/pull/use a value of a text box or other controls (client side) to create a "better" message.
So the message could say:
heading: "Order #" + $('#txtBoxOrderNum').val(),
text: 'Processing order please wait',
Or whatever else you have on that web page. Do note that we can only get/grab/use current values in the web page (no server side values from code behind).
So, now we have this:
User clicks on button.
Above toast message displays (our client side js).
Heck you can display (shove) info in a text box, or even hide/show a "div" and NOT even use toast. But some kind of toast plug in is just fine.
Now that routine runs, displays your message client side.
THEN the web page makes trip up to server. Then your code behind for that button click starts running. When the long running code is done, then the page THEN makes the trip back to the browser.
Because we getting a whole new page back down browser side?
Well then the toast message will be blown out (disappear) and thus we don't need code to update, or hide the message, since we just received a fresh new copy of the web page anyway!
So above is the most easy.
If the process was LONG(er) running, say more then a few seconds, say 25 seconds? Well, you don't want to block up a whole web page for that long. (all other (server side code) and any buttons be frozen.
In that case? Well, then we need to use a thread object and thread out the call to a sperate thread. (it is easy to do).
Now the button click and browser round trip will occur very fast.
However, for status updates, we would have to START that running code AFTER the page comes back client side. (you can try and inject script as you attempted for this idea).
However, its usually better to NOT do a post back if you going to status update the page in the FIRST place.
jQuery.AJAX calls are VERY easy, and you can call web methods on the existing page (no need to setup a web server page (asmx) for this.
In effect if you REALLY want a process update (say % done), or show several messages as the long processing is occurring? We will want to avoid a post back, and avoid post back blockage. One way is to use a update-panel. But your main page will have to thread out the long running process regardless and NOT BE BLOCKED (ever!!!).
I could add a edit to this page to include a jQuery AJAX call, but the above is oh so simple, and I think should suffice fine for this example.
And this approach is super simple - no need to introduce new technology, ajax calls, or signalR concepts.
EVEN if you did/do introduce signalR, then you STILL will have to thread out the long process to ensue that the browser round trip is not blocked.
As noted, in these cases (wanting % status updates etc.), then I REALLY (no, but REALLY REALLY) would not do a post back. So one then would be wise to start the whole process and status updates using a AJAX call.
And since we assume it is most practical to AVOID post back WHEN we want a status update system (% done etc.), then a few simple ajax calls are less work and easier then signalR setup anyway.

Related

Making async call to Controller function (void). Not getting control back to UI

I am working on a MVC 5 based report generating web application (Excel files). On one "GenerateReports" page, on button click, I am calling StartMonthly function. This takes control to a void method "GenerateReportMainMonthly" in the controller. This method calls another void method "GenerateReportMain". In GenerateReportMain, there are 5 other void functions that are being called.
I do not want the control to get stuck at back-end until the report generation is completed. On button click, an alert box should show "Report Generation started." and the control should come back to the "GenerateReports" page.
I have tried ajax but have not been able to get the control back to UI. How can I get the control back to the same page without waiting for the back-end process to complete?
$('#btnStart').on('click', StartMonthly);
function StartMonthly() {
var url = '/GenerateReport/GenerateReportMainMonthly';
window.location.href = url;
}
public void GenerateReportMainMonthly()
{
_isDaily = false;
GenerateReportMain();
}
It seems you are after running background tasks in your controllers. This is generally a bad idea (see this SO answer) as you might find that your server process has been killed mid-way and your client will have to handle it somehow.
If you absolutely must run long-ish processes in your controller and cannot extract it into a background worker of some sort, you can opt for something like this SO answer suggests. Implementation will vary depending on your setup and how fancy you are willing/able to go, but the basics will ramain the same:
you make an instantaneous call to initiate your long action and return back a job id to refer back to
your backend will process the task and update the status accordingly
your client will periodically check for status and do your desired behaviour when the job is reported complete.
If I were to tackle this problem I'd try to avoid periodic polling and rather opt for SignalR updates as describled in this blog post (this is not mine, I just googled it up for example).

How to Unpark a Call

I want to hold/unhold my calls using Asterisk AMI. I have used Park AMI Action. Then, My phone disconnects, and Senders phone plays a music. How to Unpark this Call ? Can anybody help me Please ?
UnParkAction upac = new UnParkAction(channel, channel1, "360000");
ManagerResponse rr = ApplicationVariables.manager.SendAction(upac); //Sending it to Manager COnnection
You can use Redirect AMI command.
This solves the unparking issue but with a difference that the initiator will still need to answer a call. In other words he does not fully retrieve the call without any action at all.
In more detail:
When you park the call you need to have both channels:
(1) Channel to be parked
(2) Channel that makes the park
Store in a static variable (1).
Then when you finished parking do the following:
Initiate redirect call from the Channel parked (essentially what you have stored) and as destination, your number.
Example URL:
https://<YOUR AMI URL>?action=Redirect&channel=" + channelParked + "&context=" + context + "&priority=1&Exten=" + myPhoneNumber;
When you parking call it say you parking lot id.
You have call that lot id to catch phone.
If you want just hold it use Musiconhold command.
If you want more controlable automated parking-like setup, use transfer to conference on musiconhold extension.

How to refresh a label without reloading the page

I want to refresh a label on a page without reloading the page.
The page is used to send SMSs. Because I am using a GSM modem connected to a COM port, it is quite a slow process taking about 3 seconds per text. (There's a lengthy reason why I'm using a serial GSM modem, not an online service or USB connection.)
Multiple numbers can be specified, delimited by ";". I want to update the page as soon as each text is sent; but at the moment it just updates the label all in one go at the end. What's the simplest way to achieve this? Thoughts were maybe AJAX, JavaScript or Threading. (As I say, simple is good!)
Current code:
SerialPort sp = new SerialPort("COM1", 115200, Parity.None, 8, StopBits.One);
try
{
String[] numbers = tbNo.Text.Split(';');
foreach (string n in numbers)
{
sp.Open();
sp.Write("AT+CMGF=1" + (char)(13));
Thread.Sleep(200);
sp.Write("AT+CMGS=" + n.Replace(" ", string.Empty) + (char)(13));
Thread.Sleep(200);
sp.Write(tbMsg.Text + (char)(13) + (char)(26));
Thread.Sleep(3000);
sp.Close();
Label1.Text = Label1.Text + "Message sent to " + n + "<br />";
}
} catch (Exception error) {
Label1.Text = error.Message;
};
The best way is to create a service on server side if you have ASP.net, it can be a WCF Rest service, send a post request to server as ajax call and upon receiving the result change the label text in javascript.
You definitely want to use some AJAX for this. One way that's actually quite easy to implement is to use SignalR.
SignalR is a framework that supports a realtime connection between the client and the server. This makes your code a lot easier. If you don't use SignalR you would have to manually implement something like polling (where the client browser asks the server every X seconds what the status of your task is) or some variation on this.
SignalR hides the underlying mechanism used and creates a connection between the server and client.
Your code on the server would look something like this:
public class SmsHub : Hub
{
public Task SendMessages(string input)
{
// ... send sms message
Caller.updateStatus('Message send!');
}
}
And on your client you would use the javascript hub to send and receive messages. The updateStatus function can append a HTML message to some information div.
This is a nice blog post by Scott Hanselman that can also help you getting started.

Event of FiddlerApp descirbing moment when page is completely loaded

What event of FiddlerApplication specifies moment when page is fully loaded into web browser? Event AfterSessionComplete is fired before all page items are loaded...
I am using exteral dll (fiddlercore).
Fiddler.FiddlerApplication.AfterSessionComplete += delegate(Fiddler.Session session)
{
Console.WriteLine("End time:\t" + session.fullUrl + ", " + session.Timers.ClientDoneResponse.ToString("dd-MM-yyyy HH:mm:ss")); }
};
This question was answered an hour before you posted here in the forum where you originally asked it.
A web proxy (e.g. Fiddler) cannot possibly know when a web browser is
finished loading a page. Even if you were running code in the web
browser itself, it's a non-trivial exercise.
About the closest you could come is to use the proxy to inject
JavaScript which then emits out the timing information to the network
for the proxy to catch, but even doing this from JavaScript isn't
necessarily precise.

What's the correct way of posting this data asynchronously, and canceling/queuing new requests?

I am attempting to improve the stability of the web dashboard I have created. I have noticed that the main cause of getting into a bad state is when the user moves too quickly and requests get cut short.
For instance, I have the following javascript:
//When a resize occurs a lot of handling needs to happen to convert the user's action into
//a visibly-pleasing result. In addition, the server has to be spoken with in order to save the controls.
function OnClientResizing(pane, eventArgs) {
eventArgs.set_cancel(true);
var parameters = new Array();
parameters.push("Resize");
parameters.push(pane.get_id());
parameters.push(eventArgs.get_delta());
__doPostBack(pane.get_splitter()._uniqueID, parameters);
}
This function passes the hard work back to the server, so that it can calculate the appropriate ways to resize the controls on the page during resizes. This takes X seconds. If the user then resizes the page again before X seconds has elapsed -- I enter into a bad state. Either the old request gets cut off prematurely, or the new one runs at the same time. Either way, controls become mishapen on the page.
As such, I would like to queue future resizes, or play around with canceling current requests. I read that the best way to do something like this is to simply set a flag outside the scope of this function. I can do that, but I am not sure how to detect the end of a doPostBack. Am I supposed to change the javascript variable from the server-side somehow in PageRequestManager - EndRequest?
Cheers
First off, don't let your server participate in UI resize algorithms. Do that entirely client side. You can send resulting data to the server at any time, but don't make a real-time UI positioning depend upon a server response. That should be handled client-side with CSS or javascript logic.
Second off, if your code can't handle two ajax calls in flight at the same time, then your options are as follows:
Fix your code so it can handle sequential ajax responses in flight at the same time.
Cancel/ignore the first ajax response the moment you send a second one so that you ignore the response from the first and wait for the response from the second.
Prevent a second ajax request until the first one completes. I wouldn't suggest queueing them because that's just going to lead to an even worse user experience.
The details of how to do 1, 2 or 3 depend upon how your code works which you have not yet shared.
The easiest is option 3). That can be done with just a global flag. Just define a global variable, set it to true when you start an ajax call and clear it when the ajax call completes (in a completion function):
var ajaxInFlight = false; // global declaration
function OnClientResizing(pane, eventArgs) {
if (ajaxInFlight) return; // do nothing if ajax call already in flight
ajaxInFlight = true;
eventArgs.set_cancel(true);
var parameters = new Array();
parameters.push("Resize");
parameters.push(pane.get_id());
parameters.push(eventArgs.get_delta());
__doPostBack(pane.get_splitter()._uniqueID, parameters);
}
function postBackCompletionHandler(id, parms) {
ajaxInFlight = false; // clear global flag, ajax call done
// ... rest of your function here
}
You will also have to make sure that error conditions are handled so that the global flag is reset if the ajax call fails for any reason.

Categories