Twilio - Call Forwarding - c#

I am building an application where a user will call my Twilio Number. After connecting, Twilio will call another user and connect the two parties. However, the number displayed for the second party should be Twilio's number (or no caller ID), not the user's number.
I tired adding SIP header such as privacy = full & p-asserted-identity="anonymous" but none is working.
Code I am using for the callback:
[HttpPost]
public async Task<ActionResult> Connect(string from, string to)
{
//var outgoingPhoneNumber = await GatherOutgoingPhoneNumberAsync(from, to);
var response = new TwilioResponse();
response.Say("Please wait while we contact the other party");
response.Dial("+14085993263", new { });
return TwiML(response);
}
Is there anyway to do that?

Twilio developer evangelist here.
You're very close to the solution, but what want to do is add a callerid attribute to the Dial verb. That way, you can either add your Twilio number, or your own business' verified number. To do that just change your code to the following:
[HttpPost]
public async Task<ActionResult> Connect(string from, string to)
{
var response = new TwilioResponse();
response.Say("Please wait while we contact the other party");
response.Dial("+14085993263", new { callerId = "+1234567890" });
return TwiML(response);
}
Make sure you replace callerId with the number you wish to use. The caller ID can only be one of your Twilio numbers or a verified number as stated above.
Hope this helps you

Related

Problem: how to get the current User by gRPC (using also WebApi) c#

First I will talk of what both of the projects to get an idea of what I'm doing
gRPC Server
Have Context DB and some services ( the User AddUser(User user) ) and the (IEnumerable getAllUsers())
The DB calls Users_1
Proto (Server Part) have some methods like a InsertNewUser, SelectAllUsers and here also have a SelectByID and Update method but not implement in the services yet
UserService (using the proto file) that have InsertNewUser and SelectAllUsers done, need to do the SelectByID and the Update method
To Select/Update a user I have some messages like this
service UserAuth {
rpc SelectAll (Empty) returns (stream ShowUser); //this is ok and it is in the UserService
rpc SelectByID (UserFilter) returns (ShowUser);
rpc InsertNew (RUser) returns (UserFilter); //this is ok and it is in the UserService
rpc Update (ShowUser) returns (Empty);
}
message Empty {
}
message RUser {
string username = 1;
string password = 2;
string email = 3;
int32 age = 4;
}
message ShowUser {
string username = 1;
string email = 2;
int32 age = 3;
bool test = 4;
}
message UserFilter
{
string userID = 1;
}
In the WebApi I have this
methods [httpPost] InsertNewUser(User user) and [httpGet] SelectAll() and this is using the gRPC Server that I talk previously (the InsertNewUser will be my register). Both works fine
This is use protos too (but in the Client part)
method [httpPost] Login(User user) that creates a token and also check if the user is in
the gRPC DB or not
Need to add the [httpGet] SelectByID(Guid UserFilter) -> return an user, and the [httpPut] Update(User user) BUT and here is where my problem comes in
The methods I want to do can only be given to the user who has been logged in, that is, he can see his information and also edit his own information (and not the information of another user)
That is, I will have to save the user who logged in in something similar to "localStorage()", now will it be possible to do this in two different projects? Is it possible to use it in a Web Api-only method (which does not use gRPC) to put this user in a Select/Update method that will be used in the WebApi but it calls methods coming from gRPC?
If you don't understand what I want I can then send the signature of the methods but the ideia of "what is my problem is?" is was well explained
Any answer is welcome

Caller doesn't connect into the conference

I'm trying to use Twilio to connect workers through a kind of Walkie Talkie (all the workers get a JWT to make browser calls using the Javascript SDK), for this I use the Twiml verb conference, when the worker press the conference button in the browser it sends a list of the active workers (except for the one who started the conference), I use the callSid as the name of the conference to make it unique and the CallResource to put every worker into the conference.
However, the workers in the list start listening the wait music for a conference room, but the caller automatically end the connection as soon as it is open, it doesn't even ends the conference, I don't know what's wrong with the code, I'm following the documentation for conferences in https://www.twilio.com/docs/voice/twiml/conference
Here is the method that's called when a conference needs to be created:
public VoiceResponse ConferenceTalk(List<string> recipients, string caller, string callSid)
{
TwilioClient.Init(my_account_sid, my_auth_token);
var confName = $"wt_{callSid}";
foreach (var recipient in recipients)
{
CallResource.Create(
url: new Uri($"{this.publicUrl}/Conference/WtConference/{confName}"),
to: new Twilio.Types.Client($"client:{recipient}"),
from: new Twilio.Types.Client(caller));
}
var response = new VoiceResponse();
var dial = new Dial();
dial.Conference(confName,
startConferenceOnEnter: true,
endConferenceOnExit: true);
response.Append(dial);
return response;
}
Here is the endpoint the CallResource target with the url attribute:
[HttpPost]
public TwiMLResult WtConference()
{
var confName = Request.Url.Segments[Request.Url.Segments.Length - 1];
var response = new VoiceResponse();
var dial = new Dial();
dial.Conference(confName);
response.Append(dial);
return TwiML(response);
}
I feel like the time all of this takes to happen might be causing your issues here. And the Twilio Voice SDK may not be the best product for this. I'd have to see maybe a video showing how the interaction works to fully commit to this.
In the meantime, I might try to speed up people joining the conference by sending the TwiML for the conference in the API call, not waiting for the webhook. e.g.:
public VoiceResponse ConferenceTalk(List<string> recipients, string caller, string callSid)
{
TwilioClient.Init(my_account_sid, my_auth_token);
var confName = $"wt_{callSid}";
var outboundResponse = new VoiceResponse();
var outboundDial = new Dial();
outboundDial.Conference(confName);
outboundResponse.Append(outboudDial);
foreach (var recipient in recipients)
{
CallResource.Create(
twiml outboundResponse,
to: new Twilio.Types.Client($"client:{recipient}"),
from: new Twilio.Types.Client(caller));
}
var response = new VoiceResponse();
var dial = new Dial();
dial.Conference(confName,
startConferenceOnEnter: true,
endConferenceOnExit: true);
response.Append(dial);
return response;
}
I say that Twilio Voice might not be best for this because on the Twilio back end, this is going through a whole stack that is built for making phone calls. Outbound calls are made at a rate of 1 call per second, so that might be slowing the calling of your list down.
You could consider the Twilio Video SDK for this instead (you can make audio only calls with the Twilio Video product). For this you would need to be able to trigger each of workers joining a room that was then used to distribute the audio. There aren't limits on calls per second, workers would just need to connect to a room and your application would be able to control who could talk at any one time.

Twilio MVC , how do i make phone number/message dynamic

I am using Visual studio. This is for Asp.net web application (.net framework)
this solution as a webcore application is acceptable as well.
I would like to be able to enter the information for message and to phone number dynamically , but i dont know how to "pause" the program so that this can happen. I understand the dynamic part, and can use Javascript to do that,
Basically what I want is an app that brings up a webpage where the end user enters the to number and the message, and then clicks send to send.
I thought it would be simple, but not so much :(
I have the quick start code for C# as -
// Install the C# / .NET helper library from twilio.com/docs/csharp/install
using System;
using Twilio;
using Twilio.Rest.Api.V2010.Account;
class Program
{
static void Main(string[] args)
{
// Find your Account Sid and Token at twilio.com/console
const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
const string authToken = "your_auth_token";
TwilioClient.Init(accountSid, authToken);
var message = MessageResource.Create(
body: "Join Earth's mightiest heroes. Like Kevin Bacon.",
from: new Twilio.Types.PhoneNumber("+15017122661"),
to: new Twilio.Types.PhoneNumber("+15558675310")
);
Console.WriteLine(message.Sid);
}
}
Okay I'm going to assume you want to send SMS. Further, I'm going to assume you're using Asp.Net MVC. Twilio voice is a little bit more complex, as Twilio calls back several times to get voice scripts and update statuses. More complex if you need phone tree behavior.
SMS Callbacks happen more than once too, but they're calling the same callback URL over and over, nothing fancy there.
The flow should look like this:
Web interface -> Asp.Net MVC Controller Action -> Database -> Twilio
I'll leave the web interface to you, and give some examples of the backend stuff.
You'll want a database, with one table 'Message'
Message should have these columns (at a minimum, you may need more):
message_id_pk
twilio_sid (nullable)
message_content (160 character limit if you want to keep messages in one SMS segment, this has considerations on operating cost)
status (nullable)
recipient_phone
Controller Action:
[Authorize] //assuming you'll want to have users authenticate before they can send the sms
[RequireHttps]
public async Task<ActionResult> SendSMS(
[Bind(Include = "message_id_pk, message_content, recipient_phone"] Message message)
{
db.Messages.Add(message);
TwilioSmsSender.SendSMS(message);
return RedirectToAction("Success");
}
And in TwilioSender.cs
public static void SendSMS(Message message)
{
const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
const string authToken = "your_auth_token";
TwilioClient.Init(accountSid, authToken);
var message = MessageResource.Create(
body: message.message_content,
from: new Twilio.Types.PhoneNumber("+15017122661"), //note: you can let your Twilio Messaging service handle the phone number, I recommend you look into that
to: new Twilio.Types.PhoneNumber(message.recipient_phone)
statusCallback: new Uri(TwilioCallBackController.SMSCallBackURL)
);
message.twilio_sid = message.Sid;
db.SaveChanges();
}
And in TwilioCallBackController.cs (You need to handle callbacks from Twilio here)
[ValidateTwilioRequest]
public ActionResult TwilioSMSCallback()
{
string sid = Request.Form["SmsSid"];
List<Message> msg = db.Message.Where(x=> x.twilio_sid == sid).ToListAsync();
if(msg.Count > 0)
{
Message message = msg.First();
message.status = Request.Form["SmsStatus"];
}
}

Twilio Function Read Multiple Speech Input

The use case is the call an IVR system using programmable voice in twilio. Based the IVR question, send answers using twilio function and TWIML. How can I achieve this? So far I have made call using Twilio and refer below the callback webhook.
[HttpPost]
public TwiMLResult Index(string message)
{
var response = new VoiceResponse();
var gather = new Gather(input: new List<Gather.InputEnum>()
{
Gather.InputEnum.Speech
} ,
timeout: 5, action:new Uri("https://url-sample/GatherSample"));
gather.Say("Please press 1 or say sales for sales.");
response.Append(gather);
LogWriter.Debug($"Message : {response.ToString()}");
return new TwiMLResult(response);
}
Also Twilio Function Code.
exports.handler = function(context, event, callback) {
const twiml = new Twilio.twiml.VoiceResponse();
const command = event.SpeechResult.toLowerCase();
twiml.say(`You said ${command}. I'll give you a ${command} fact.`);
callback(null, twiml);
};

Can't send message to specific user with SignalR

I can't make works the message sending to one specific user from the code behind. Clients.All works, Clients.AllExcept(userId) works, but not Client.User(userId).
My hub:
public class MessagingHub : Hub
{
public override Task OnConnected()
{
var signalRConnectionId = Context.ConnectionId;
// for testing purpose, I collect the userId from the VS Debug window
System.Diagnostics.Debug.WriteLine("OnConnected --> " + signalRConnectionId);
return base.OnConnected();
}
}
My controller to send message from code behind:
public void PostMessageToUser(string ConnectionId)
{
var mappingHub = GlobalHost.ConnectionManager.GetHubContext<MessagingHub>();
// doesn't works
mappingHub.Clients.User(ConnectionId).onMessageRecorded();
// doesn't works
mappingHub.Clients.Users(new List<string>() { ConnectionId }).onMessageRecorded();
// works
mappingHub.Clients.All.onMessageRecorded();
// works (?!)
mappingHub.Clients.AllExcept(ConnectionId).onMessageRecorded();
}
How my hub is initialized on the JS:
var con, hub;
function StartRealtimeMessaging()
{
con = $.hubConnection();
hub = con.createHubProxy('MessagingHub');
hub.on('onMessageRecorded', function () {
$(".MessageContainer").append("<div>I've received a message!!</div>");
});
con.start();
}
And finally how I send a(n empty) message to the hub:
function TestSendToUser(connectionId)
{
$.ajax({
url: '/Default/PostMessageToUser',
type: "POST",
data: { ConnectionId: connectionId},// contains the user I want to send the message to
});
}
So, it works perfectly with mappingHub.Clients.All.onMessageRecorded(); but not with mappingHub.Clients.User(ConnectionId).onMessageRecorded(); or mappingHub.Clients.Users(new List<string>() { ConnectionId}).onMessageRecorded();.
But interestingly, it works with mappingHub.Clients.AllExcept(ConnectionId).onMessageRecorded(); : All users connected receive the message except the given userid, which means the userid is good, and the user is well identified. So, why Clients.User(ConnectionId) doesn't works?
If you want to send a message to one particular connection and when you want to use the ConnectionId, make sure you use Clients.Client, and not Clients.User
Like this:
public void PostMessageToUser(string connectionId)
{
var mappingHub = GlobalHost.ConnectionManager.GetHubContext<MessagingHub>();
// Like this
mappingHub.Clients.Client(connectionId).onMessageRecorded();
// or this
mappingHub.Clients.Clients(new List<string>() { connectionId }).onMessageRecorded();
}
I had the same problem. I couldn't get .User(ConnectionId) to work.
I have just spent days trying to get SignalR to report progress on a long processing job to only the client who requested the job. That is, it isn't a chat app which most of the examples describe.
Any 'long processing progress reporting' examples I found only have a sim of the job in the hub. I have a controller doing real work and need to send messages from the controller, not the hub.
I used this answer https://stackoverflow.com/a/21222303/3251300. as a workaround for your stated problem but have included all the code snippets I use for the long processing job in case they are useful for anyone who stumbles on this answer.
The workaround has an elegance in that it uses the .Group() feature. By setting each groupID equal to the internal userID, messages can be sent using .Group(userID) without having to separately maintain a list of the userID/connectionID relationships outside SignalR.
There may be a way to maintain the relationships in SignalR without using the .Group() feature but I haven’t found it yet.
Pass the userID to the view using a hidden type which then makes it available to the js.
<input type="hidden" value="#ViewBag.UserID" id="userID" />
Then in the js hub script use the following to send the userID to the hub when the hub connection starts up.
$.connection.hub.start()
.done(function () {
var userID = document.getElementById('userID').value;
$.connection.myHub.server.announce(userID);
})
.fail(function () { alert("Hub failed to start.") });
The hub then has one statement which associates the userID and connectionID to the groupID, which is then the same string as the userID.
public class MyHub : Hub
{
public void Announce(string userID)
{
Groups.Add(Context.ConnectionId, userID);
}
}
To send messages from the controller (Again, not the hub in this case, the message is reporting progress to the client on a long processing request running in the controller) after setting the hub context, use .Group() and the internal userID.
var hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
string fileMessage = "Some message";
hubContext.Clients.Group(userID).hubMessage(fileMessage);
This is then displayed in the view using the js to place the message in a div
$.connection.myHub.client.hubMessage = function (message) {
$("#hubMessages").html(message);
}
'#hubMessages' refers to this div in the view. Examples use .append which makes the div grow each time you send a message, .HTML replaces whatever is in the div with the new message.
<div id="hubMessages"></div>
Anyone who comes to this answer and is trying to get going on MVC and SignalR, a big shout out to Caleb who has a great series of intro vids for SignalR https://youtu.be/kr8uHeNjOKw Anyone who finds this answer who is new to SignalR I recommend you spend an hour watching these.
I face same problem.
I change from:
Clients.User(connectionId).SendAsync(CallbackDefinition.DirectMessage, directMessageResult);
to:
Clients.Client(connectionId).SendAsync(CallbackDefinition.DirectMessage, directMessageResult);
And it work :D
Thank to: Matthieu Charbonnier

Categories

Resources