I want to make an application which can make a call to other peoples using Twilio in vb.net. whenever i am passing the URL parameter it is showing me invalid URL error. I have made a service which is returning Twimil response. And i am passing this the service URL as a parameter to Twilio URL to Initiate a call.
Not Sure is it the correct way to make call from vb.net
Twilio callvar to = new PhoneNumber("+917715*****");
var from = new PhoneNumber("+1*********");
var call = CallResource.Create(to, from,
url: new Uri("demo.twilio.com/docs/voice.xml"));
service public class Service1 : IService1
{
public void GetDataJSONFormat()
{
var response = new VoiceResponse(); response.Say("Hello Shrikant");
}
}
Related
For the time being I use a test account in Twilio, but I hope that this has no relevance regarding my question.
As my firs experimental step towards Twilio, I'm testing the client-quickstart-csharp-1.4 package on Visual Studio 2017 on Windows.
Outgoing calls work fine to my verified phone, but I have problems with incoming calls. When I make a call from a real phone to my Twilio phonenumber, then my code in VoiceController.cs doesn't run (doesn't hit any breakpoint) and I hear a voice message about that I should reconfigure something my application (but I don't understand, what). In contrast of this, when I make a call from my TwiMLApp config page, pressing the red Call button (see picture),
then my code stops at the breakpoints, and says the text I wrote in the argumet of response.Say().
My questions:
Why does the call work differently from a real phone then from my
TwiMLApp config page?
How can I achieve my code run (i.e. say the text I wrote in the code) also when I make a call from a real phone?
How Can I achieve a real, live voice dialogue between the caller phone and my computer's speaker and microphone at incoming calls (similarly to
the outgoing calls)?
Remark 1.
Both outgoing an incoming calls work fine in Agile CRM using the Twilio widget for voice calls. But for the time of my experiments I've removed this widget (and also the "Agile CRM Twilio Saga" TwiML App from Twilio), to avoid the interferences between the different applications.
Remark 2.
Perhaps I should configure something with this screen (the screenshot found here), but I don't find this page on my twilio portal.
Instead of this, I have a page like this:
But I don't know what to change here to make my program work.
It seems that this application is designed
to manage outgoing calls (to a real phone, or to an other client of this
application) and
accept calls from the web (from an another client,
or from the TwiML App setting page, seen on the first screenshot on the o.p.), but not from a real phone.
Every (outgoing or incoming) call falls into the Index() method of the VoiceController class. This method tries to find out whether a call is incoming or outgoing.
In the case of on outgoing call, the To property of the request parameter of this method is a phonenumber, while at an incoming call from the web is a string (a username), or null (when the call comes from the TwiML App setting page). This justifies the if-else structure in the original code (extended just my remarks starting with (mma))
public ActionResult Index(VoiceRequest request)
{
var callerId = ConfigurationManager.AppSettings["TwilioCallerId"];
var response = new TwilioResponse();
if (!string.IsNullOrEmpty(request.To))
{
// wrap the phone number or client name in the appropriate TwiML verb
// by checking if the number given has only digits and format symbols
if (Regex.IsMatch(request.To, "^[\\d\\+\\-\\(\\) ]+$")) //(mma) supposed to be an outgoing call
{
response.Dial(new Number(request.To), new { callerId });
}
else //(mma) a call from one client to antorher
{
response.Dial(new Client(request.To), new { callerId });
}
}
else //(mma) incoming call from the TwiML App setting page
{
response.Say("Thanks for calling!");
}
return TwiML(response);
Question 3. can be separated into the following two parts:
If at an incoming call we want to establish a real connection with a pre-specified client (say calledUser) instead of reading out the "Thanks for calling!" message, we should replace response.Say("Thanks for calling!"); by response.Dial(cl, new { request.From }); where cl = new Client(calledUser); We can put the value of calledUser into our Local.config, so we can read it from there: var calledUser = ConfigurationManager.AppSettings["calledUser"];
If we want to accept a call from a real phone, then we should recognize this situation. This is exactly when request.To == callerId( = our Twilio phononumber) , so we must split the first condition according this. The new branch will call the pre-specified user.
Putting these together, our new code in VoiceController.cs will look like this:
public ActionResult Index(VoiceRequest request)
{
var callerId = ConfigurationManager.AppSettings["TwilioCallerId"];
var calledUser = ConfigurationManager.AppSettings["calledUser"];
var response = new TwilioResponse();
if (!string.IsNullOrEmpty(request.To))
{
// wrap the phone number or client name in the appropriate TwiML verb
// by checking if the number given has only digits and format symbols
if (Regex.IsMatch(request.To, "^[\\d\\+\\-\\(\\) ]+$"))
{
if (request.To != callerId) //(mma) supposed to be an outgoing call
{
response.Dial(new Number(request.To), new { callerId });
}
else //(mma) supposed to be an incoming call from a real phone
{
var cl = new Client(calledUser);
response.Dial(cl, new { request.From });
}
}
else //(mma) a call from one client to antorher
{
response.Dial(new Client(request.To), new { request.From });
}
}
else //(mma) incoming call from the TwiML App setting page
{
var cl = new Client(calledUser);
response.Dial(cl, new { request.From });
}
return TwiML(response);
}
Of course, if we want to accept a call, then we should start a client with the pre-defined username (calledUser). In order to do this, we can introduce a new Url parameter User, put its value into TempData["User"] by the HomeController and change the var identity = Internet.UserName().AlphanumericOnly(); line in the TokenController.cs to var identity = TempData["User"] == null ? Internet.UserName().AlphanumericOnly() : TempData["User"].ToString();
So, our new HomeController and TokenController look like this:
public class HomeController : Controller
{
public ActionResult Index(string user)
{
TempData["User"] = user;
return View();
}
}
and this:
public class TokenController : Controller
{
// GET: /token
public ActionResult Index()
{
// Load Twilio configuration from Web.config
var accountSid = ConfigurationManager.AppSettings["TwilioAccountSid"];
var authToken = ConfigurationManager.AppSettings["TwilioAuthToken"];
var appSid = ConfigurationManager.AppSettings["TwilioTwimlAppSid"];
// Create a random identity for the client
var identity = TempData["User"] == null ? Internet.UserName().AlphanumericOnly() : TempData["User"].ToString();
// Create an Access Token generator
var capability = new TwilioCapability(accountSid, authToken);
capability.AllowClientOutgoing(appSid);
capability.AllowClientIncoming(identity);
var token = capability.GenerateToken();
return Json(new
{
identity,
token
}, JsonRequestBehavior.AllowGet);
}
}
And, of course, our Local.config file should contain such a line:
<add key="calledUser" value="TheNameOfThePreDefinedUser" />
The title is a bit misleading, here is my situation: with postman, i can call the following url issuing a post and my function works:
http://localhost/odataservice/odata/Evaluations(9)/CreateEmptyForm
For it to work, i have to send the following in the body portion:
{
"#odata.type": "#Common.Data.Client",
"ClientId": 1
}
My issue arises when i try to replicate this inside my asp.net mvc application. There, im doing
public int CreateRvaForm(int clientId, int evalId, int type)
{
var key = Task.Run(async () =>
{
var data = await
client
.For<Evaluation>(Constants.DataService.PLURAL_EVALUATIONS)
.Key(evalId)
.Function( type==0 ? Constants.DataService.FUNCTION_CREATE_RVA_EMPTY : Constants.DataService.FUNCTION_CREATE_RVA_DUPLICATE)
.Set( new{ClientId=clientId} )
.ExecuteAsScalarAsync<int>();
return data;
}).GetAwaiter().GetResult();
return key;
}
Here, the variable client is the Simple.Odata.Client object.
The error i'm getting is something related to route not found; debug shows me that the library is trying to execute the url
http://localhost/odataservice/odata/Evaluations(9)/CreateEmptyForm(clientId=XX).
I dont have access to modify the odata service.
According to this text ("Executing functions and actions"), you should rather try using Action instead of Function since action is POST-based call while function translates to HTTP GET
I have some strange problem. I am using Microsoft.AspNet.WebApi.Client.5.2.3 for simple .NET client for API. I want to post some data to API. I am using PostAsJsonAsync method for it.
using (var client = new HttpClient())
{
var adress = new Uri("http://localhost:28906/v1/things?access_token=SOMETOKEN");
var result = await client.PostAsJsonAsync(adress, new ThingModel() { Name = "test"});
}
When I am sending request, my uri is transformed from "http://localhost:28906/v1/things?access_token=SOMETOKEN" to "http://localhost:28906/v1/things/?access_token=SOMETOKEN" ( '/' is inserted before '?'). And request becomes wrong. How can I overcome this? In fact, how can I pass query string and json body?
I have overridden the built in WebClient as below. Then I call it
public class HttpWebClient : WebClient
{
private Uri _responseUri;
public Uri ResponseUri
{
get { return _responseUri; }
}
protected override WebResponse GetWebResponse(WebRequest request)
{
WebResponse response = base.GetWebResponse(request);
_responseUri = response.ResponseUri;
return response;
}
}
Then I consume it like this:
using (HttpWebClient client = new HttpWebClient())
{
client.Headers[HttpRequestHeader.Authorization] = $"Bearer { _token }";
client.Headers[HttpRequestHeader.ContentType] = "application/json";
client.UploadData(_url, Encoding.UTF8.GetBytes(_data));
string queryString = client.ResponseUri.Query.Split('=').Last();
}
The response uri comes back with "https://login.microsoftonline" rather than url returned from the MVC controller with a query string, as it is authenticating first with that bearer token using AzureAd/OpenId. If i call it twice it returns the original _url but not the redirected one. If I remove AzureAd authentication it works fine. Is there a way to force the response uri to come back as what the MVC controller sets it to?
Assuming you use the 'UseOpenIdConnectAuthentication' and configuring it to use AAD authentication, you can modify the redirect uri by setting Notifications.RedirectToIdentityProvider, something like:
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = async _ =>
{
_.ProtocolMessage.RedirectUri = _.Request.Uri.ToString();
}
}
If you use something else , or maybe I didn't understand your problem - please supply more information
I am unable to post data to a ASP.NET WebAPI server.
I can get data from the WEBAPI server. However, I am unable to post.
The following code fails to post:
response = await client.PostAsync("api/Cars", content);
Error:
StatusCode: 415, ReasonPhrase: 'Unsupported Media Type', Version: 1.1
Client:
[TestClass]
public class UnitTest1
{
// http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client
[TestMethod]
public async Task TestMethod1()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:48213/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HTTP GET
var response = await client.GetAsync("api/Cars");
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync();
}
// HTTP POST
using (var content = new StringContent(#"some_value"))
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
response = await client.PostAsync("api/Cars", content);
if (response.IsSuccessStatusCode)
{
Debug.WriteLine("Post was successful.");
}
}
}
WebAPI:
namespace FSharpWebAPI.Controllers
open System.Web.Http
open FSharpWebAPI.Models
type CarsController() =
inherit ApiController()
let values = [| { Make = "Ford"; Model = "Mustang" }; { Make = "Nissan"; Model = "Titan" } |]
member x.Get() = values
member x.Post(data) =
ignore
What updates do I need to make just to make a simple post?
As #Fyodor Soikin has pointed out, the Post method is generic ('a -> 'b -> unit), and ASP.NET Web API refuses to wire up such methods.
ASP.NET Web API uses convention over configuration in order to figure out how to route and handle incoming requests. If an HTTP POST arrives, it'll go hunting for a method (partially) named Post, and attempt to call it. While you could argue that if a generic method could handle the input, it'd be possible for Web API to still call it, it doesn't do that.
You'll need to add a type annotation - for example:
member x.Post(data : Car) =
ignore
That's probably still not going to be enough, because the type of that version of Post is Car -> 'a -> unit, so the return value is a generic function. I'd be surprised if Web API knows what to do with that.
The reason is that ignore is a function, and since Post doesn't invoke the function, the return value is the function itself.
If you want to ignore the input and return unit, you can simply do this:
member x.Post(data : Car) = ()
This version has the type Car -> unit, which I expect Web API will find acceptable.