How to Unpark a Call - c#

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.

Related

Alert Notification in asp.net c# through loop

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.

Pay with Amazon behaving async

I have integrated Pay with Amazon with my web app, but I have determined that capturing funds only works when I step through the code debugging, and does not happen if I don't have a break-point. To me, this indicates that a pause is necessary. I am using recurring payments. The relevant section of code is below:
...
//make checkout object
AmazonAutomaticSimpleCheckout asc = new AmazonAutomaticSimpleCheckout(billingAgreeementId);
//capture
CaptureResponse cr = asc.Capture(authId, amount, 1);
//check if capture was successful
if (cr.CaptureResult.CaptureDetails.CaptureStatus.State == PaymentStatus.COMPLETED)
{
...
//give the user the things they paid for in the database
...
return "success";
}
...
So, if I have a break-point at the capture line under //capture, then the function returns success. If I do not have the break-point, I get a runtime exception System.NullReferenceException: Object reference not set to an instance of an object. regarding the following if statement.
To me, this implies that I should be able to await the capture method.
Also note, the capture(...) method is calling the CaptureAction(...) method, just as the C# sample does.
//Invoke the Capture method
public CaptureResponse Capture(string authId, string captureAmount, int indicator)
{
return CaptureAction(propertiesCollection, service, authId, captureAmount, billingAgreementId, indicator, null, null);
}
How can I await the capture call? Am I forgetting to pass a parameter to indicate that it should execute the operation immediately?
It seems after some experimentation, that a function that will essentially achieve the wait I was performing manually using a break-point is the function CheckAuthorizationStatus(), which is also in the C# sample provided with the documentation.
So the fixed code simply adds CheckAuthorizationStatus() before calling the capture() method. CheckAuthorizationStatus() apparently loops until the state of the authorization changes. This seems somewhat kludgey to me, but seems to be how the Pay with Amazon APIs are meant to be used, as best I can tell. Corrected code below:
//make checkout object
AmazonAutomaticSimpleCheckout asc = new AmazonAutomaticSimpleCheckout(billingAgreeementId);
//capture
CaptureResponse cr;
GetAuthorizationDetailsResponse gadr = asc.CheckAuthorizationStatus(authId);
cr = asc.Capture(authId, amount, 1);
//gadr = asc.CheckAuthorizationStatus(authId);
//check if capture was succeddful
if (cr.CaptureResult.CaptureDetails.CaptureStatus.State == PaymentStatus.COMPLETED)
{
...
return "success";
}
When using asynchronous mode you will typically rely on a couple of ways of handling it. The result of AuthorizeOnBillingAgreement will return a Amazon authorization Id (e.g. P01-1234567-1234567-A000001). Once you have the authorization Id you can:
Poll GetAuthorizationDetails - This will return the authorization details which will contain the "State" of the authorization. When the state is "Open" you can then make the Capture API call passing in the authorization Id.
Wait for the Instant Payment Notification (IPN). If you have a IPN handler you can watch for it and make the capture API call as described in step 1. The IPN is usually sent within 60 seconds and it will have the final processing status (Open or Declined).
You shouldn't add an arbitrary pause. You should always check the state of the authorization before making the capture. Even if the payment status is completed you still need to check the state.
Disclaimer:
I don't implement recurring payments, only a straightforward payment - though just reading the documentation it seems similar or at least there is a synchronous option.
Because it meets my requirements, I opt for the synchronous process. In essence treating it like a "payment gateway" - give me the result "now" and I'll deal with whatever result.
Additionally, AUTH and CAPTURE in one step - again, this is based on one's operational requirement/s.
The 2 related items are:
CaptureNow=true
TransactionTimeout=0
A value of zero always returns a synchronous Open or Declined
You'll get (synchronously):
AuthorizeResult.AuthorizationDetails which will have
AmazonAuthorizationId, AuthorizationAmount, etc
AuthorizeResult.AuthorizationDetails.IdList
null on failure
otherwise it will contain the capture id (if capture was successful)
AuthorizeResult.AuthorizationDetails.IdList.member - I've only seen this to contain 1 item (the CaptureId)
You can then use the CaptureId to call GetCaptureDetails and do what you need to do after parsing the GetCaptureDetailsResponse
Again, above is based on Payments API flow (not recurring Payments/Billing Agreement) so I hope it at least helps/gives you an avenue/idea for testing the synchronous option.

ohLibspotify not calling any callback after login

I'm trying to create a project where I use the ohLibspotify .Net libspotify wrapper to login to spotify and stream playlists.
As far as I can see I've set everything up the same way like in the example. First create a session like so:
SpotifySessionConfig sp_config = new SpotifySessionConfig()
{
ApiVersion = 12,
CacheLocation = "cache",
SettingsLocation = "settings",
UserAgent = "player",
ApplicationKey = Properties.Resources.appkey,
Listener = new sp_Listener()
};
sp_session = SpotifySession.Create(sp_config);
Then I call relogin() if that fails than I show the login window to the user because no stored credentials have been found. When the user has supplied me with his account details I call login(username, password, true, null). After that I'm awaiting a call back to the sp_Listener class.
In the sp_Listener class I have overridden the following functions:
SpotifySessionListener.LoggedIn(SpotifySession session, SpotifyError error)
SpotifySessionListener.ConnectionError(SpotifySession session, SpotifyError error)
SpotifySessionListener.LogMessage(SpotifySession session, string data)
The only callback that gets called is the LogMessage callback. I've hooked it up to log4net to read all the output efficiently. This is all of the LogMessageoutput:
2015-02-22 20:58:38,636 [18] DEBUG Namespace.sp_Listener - 19:58:38.634 I [c:/Users/spotify-buildagent/BuildAgent/work/1e0ce8a77adfb2dc/client/core/session/offline_authorizer.cpp:297] Unable to login offline: no such user
2015-02-22 20:58:38,649 [18] DEBUG Namespace.sp_Listener - 19:58:38.649 I [c:/Users/spotify-buildagent/BuildAgent/work/1e0ce8a77adfb2dc/client/core/session/offline_authorizer.cpp:297] Unable to login offline: no such user
2015-02-22 20:58:38,651 [14] DEBUG Namespace.sp_Listener - 19:58:38.649 E [c:/Users/spotify-buildagent/BuildAgent/work/1e0ce8a77adfb2dc/client/core/network/proxy_resolver_win32.cpp:215] WinHttpGetProxyForUrl failed
2015-02-22 20:58:38,664 [19] DEBUG Namespace.sp_Listener - 19:58:38.661 I [ap:1752] Connecting to AP ap.gslb.spotify.com:4070
2015-02-22 20:58:38,713 [19] DEBUG Namespace.sp_Listener - 19:58:38.713 I [ap:1226] Connected to AP: 193.182.7.34:4070
It seems like I must have forgotten something. I've no idea what, maybe one of you guys knows a solution.
I'm the original author of the ohLibSpotify wrapper library. I think you possibly have overlooked the need to call ProcessEvents. ohLibSpotify tries as far as possible to provide only a thin layer over libspotify. Almost everything in the libspotify docs remains relevant when you are using ohLibSpotify, and you should consider those docs your first port-of-call. https://developer.spotify.com/docs/libspotify/12.1.51/index.html
In particular:
The library itself uses multiple threads internally. To allow for synchronization between these threads, you must implement the sp_session_callbacks::notify_main_thread callback. Whenever called (from some internal thread), the application must wake up the main loop so the sp_session_process_events() function can be run.
The API itself is not thread-safe. Thus, you must take care not to call the API functions from more than one of your own threads.
The names are slightly different, but the concepts are the same - you need to implement NotifyMainThread to get notifications that libspotify wants to communicate with you, then you need to make sure that your main thread calls sp_session.ProcessEvents. You also need to make sure that only one thread ever interacts with ohLibSpotify at a time, either by coordinating so that only one thread calls ohLibSpotify, or by using appropriate locks around calls into ohLibSpotify.
(I'm using libspotify names here: the following advice applies equally whether you're using libspotify directory or ohLibSpotify.)
With a few exceptions, libspotify only ever calls your callbacks from inside a call to sp_session_process_events. (The exceptions are notify_main_thread and the callbacks associated with music delivery.) So if you're not set up to call that regularly, you'll find that libspotify doesn't do very much. If your program has an event loop, you should arrange to send yourself events whenever you receive the notify_main_thread callback or when the time specified by your last call to sp_session_process_events has passed, and call sp_session_process_events in the event handler. If you have no event loop, you might want to spawn a thread for this purpose, and make sure to use appropriate locks to stop other threads from calling into libspotify at the same time.

How Implementing a windows service on a server that is hosted with ISP

I am working on an assignment in asp.net to send notification email to users at specific intervals.
But the problem is that since the server is not privately owned i cannot implement a windows service on it.
Any ideas?
There's no reliable way to achieve that. If you cannot install a Windows Service on the host you could write a endpoint (.aspx or .ashx) that will send the email and then purchase on some other site a service which will ping this endpoint at regular intervals by sending it HTTP request. Obviously you should configure this endpoint to be accessible only from the IP address of the provider you purchase the service from, otherwise anyone could send an HTTP request to the endpoint and trigger the process which is probably undesirable.
Further reading: The Dangers of Implementing Recurring Background Tasks In ASP.NET.
There are several ways to get code executing on an interval that don't require a windows service.
One option is to use the Cache class - use one of the Insert overloads that takes a CacheItemRemovedCallback - this will be called when the cache item is removed. You can re-add the cache item with this callback again and again...
Though, the first thing you need to do is contact the hosting company and find out if they already have some sort of solution for you.
You could set up a scheduled task on the server to invoke a program with the desired action.
You can always use a System.Timer and create a call at specific intervals. What you need to be careful is that this must be run one time, eg on application start, but if you have more than one pools, then it may run more times, and you also need to access some database to read the data of your actions.
using System.Timers;
var oTimer = new Timer();
oTimer.Interval = 30000; // 30 second
oTimer.Elapsed += new ElapsedEventHandler(MyThreadFun);
oTimer.Start();
private static void MyThreadFun(object sender, ElapsedEventArgs e)
{
// inside here you read your query from the database
// get the next email that must be send,
// you send them, and mark them as send, log the errors and done.
}
why I select system timer:
http://msdn.microsoft.com/en-us/magazine/cc164015.aspx
more words
I use this in a more complex class and its work fine. What are the points that I have also made.
Signaling the application stop, to wait for the timer to end.
Use mutex and database for synchronize the works.
Easiest solution is to exploit global.asax application events
On application startup event, create a thread (or task) into a static singleton variable in the global class.
The thread/task/workitem will have an endless loop while(true) {...} with your "service like" code inside.
You'll also want to put a Thread.Sleep(60000) in the loop so it doesn't eat unnecessary CPU cycles.
static void FakeService(object obj) {
while(true) {
try {
// - get a list of users to send emails to
// - check the current time and compare it to the interval to send a new email
// - send emails
// - update the last_email_sent time for the users
} catch (Exception ex) {
// - log any exceptions
// - choose to keep the loop (fake service) running or end it (return)
}
Thread.Sleep(60000); //run the code in this loop every ~60 seconds
}
}
EDIT Because your task is more or less a simple timer job any of the ACID type concerns from an app pool reset or other error don't really apply, because it can just start up again and keep trucking along with any data corruption. But you could also use the thread to simply execute a request to an aspx or ashx that would hold your logic.
new WebClient().DownloadString("http://localhost/EmailJob.aspx");

AMI Asterisk Manager Interface Originate Action

I am currently constructing a C#.NET wrapper for the Asterisk Interface Manager.
I can do simple things like transfers and hangups. I am now in the process of building conference calling. I can set up an n-user conference, but I have to do so in terms of "Action: redirect" on existing active channels.
What I'd like to do is route as now non-existent calls (i.e. there is no channel in "core show channels") to my context/extension that puts people in conference rooms.
But I cannot get "Action: originate" to work for anything. What does originate take a channel as an argument when there is not channel yet? What is it that you pass to the channel header? SIP/ does not work for me.
Thanks in advance.
What exactly are you trying to do? You can't use a non-existent channel to bridge into a conference room. If you're looking to create a conference, then have people called on their extensions (or on any number, really) and placed into the conference room, that's simple.
I assume you're using Asterisk.NET. The originate command expects a number to dial (this is the channel), a context, and an extension to connect the call to within the dialplan (this can be hard-coded or can presumably be created through the AMI).
Say you set up a conference room on extension 300. Your originate command would look something like this:
OriginateAction oc = new OriginateAction();
oc.Context = "YourDialPlanContext";
oc.Priority = 1;
// Channel is however you're dialing (extensions, SIP, DAHDI, etc.)
oc.Channel = "SIP/12125551212#Your-Sip-Prover-Peer-Name";
// or in the alternative
// oc.Channel = "ZAP/ZapChannelName/12125551212";
oc.CallerId = "9998887777";
// This is the extension you want dialed once the call is connected
// 300 in our example
oc.Exten = "300";
oc.Timeout = 60000; // Our timeout in ms
oc.Variable = "VAR1=ABC|VAR2=25"; // If you need to pass variables to the dialplan
// Async should be set to true, unless you want your code to wait until the call
// is complete
oc.Async = true;
// Go ahead and place the call
ManagerResponse originateResponse = AsteriskManager.SendAction(oc, oc.Timeout);
Voila! You have now originated a call to your intended conference participant, and upon answering they will be directed into your conference room.

Categories