twilio nuget package not sending SMS message in vb.net - vb.net

Does the twilio asp.net helper library package NOT work in vb.net? I can get it to work in c# web app but not vb.net web app.
In a vb.net web application project the following code doesnt send an sms message and when stepping through with the debugger, errs on the send message line and brings up a file dialog asking for access to core.cs. The twilio library's were installed via nuget.
Public Shared Sub SendAuthCodeViaSms(ByVal number As String)
Dim twilioAccountInfo As Dictionary(Of String, String) = XmlParse.GetAccountInfoFromXmlFile("twilio")
Dim accountSid As String = twilioAccountInfo("username")
Dim authToken As String = twilioAccountInfo("password")
If (Not String.IsNullOrEmpty(accountSid) AndAlso Not String.IsNullOrEmpty(authToken)) Then
Dim client = New TwilioRestClient(accountSid, authToken)
client.SendMessage(TwilioSendNumber, ToNumber, "Testmessage from My Twilio number")
Else
'log error and alert developer
End If
End Sub
But in a C# web API project the same code sends the message as expected.
protected void Page_Load(object sender, EventArgs e)
{
const string AccountSid = "mysid";
const string AuthToken = "mytoken";
var twilio = new TwilioRestClient(AccountSid, AuthToken);
var message = twilio.SendMessage(TwilioSendNumber,ToNumber,"text message from twilio");
}
and all the sid's and tokens and phone number formats are correct, otherwise the c# one wouldnt send and I wouldnt get to the client.SendMessage part of vb.net version (client.SendSMSMessage produces the same result)

Twilio evangelist here.
I tried our your code by creating a simple VB console app and it worked for me.
The only thing I can think of is that either you are not getting your Twilio credentials correctly when parsing the XML, or the phone number you are passing into the function is not formatted correctly.
I'd suggest putting the result of call to SendMessage() into a variable and checking to see if RestException property is null:
Dim result = client.SendMessage(TwilioSendNumber, ToNumber, "Testmessage from My Twilio number")
If (Not IsNothing(result.RestException)) Then
' Something bad happened
Endif
If Twilio returns a status code greater than 400, then that will show up as an exception in the RestException property and will give you a clue as to whats going on.
If that does not work, you can always break out a tool like Fiddler to watch and see if the library is making the property HTTP request and Twilio is returning the proper result.
Hope that helps.

Related

Custom Post function to upload a file in Self Hosted REST API

I have written a VB.Net Visual basic console application for Self hosting a custom file upload service to be consumed by an application. Concept being the end user uses the application to generate data, when completed the file is uploaded to our server without user intervention. I have complete control over both applications. The problem is I can't figure out the POST Upload signature that can accept several params, including the file or how to actually receive the file. The User application is in beta now, testing all other functionality excluding the "Send File" sub's. I've never seen a file larger then 180 KB; I plan on accepting files sizes up to 1 MB. This lets me place some limitations (and filters) to help avoid abuse of the service.
I'm using NuGet packages webapi.client (4.0.30506), webapi.selfhost (4.0.3056) (and their associated required packages) and newtonsoft.json (4.5.11) and PostMan to test/debug the process. I'm using Visual Studio 2019 (Fully patched and up to date). All of the examples and google research point only to C# (not my language of choice), or are for hosted solutions like IIS.
In Postman, the only place where filenames are accepted are in the body, form-data. So, there is where I set up my key/value pairs with matching (including case and order) the params as defined in the FileULRequest class.
Everything that I've tried returns either
'500 internal server error'
or
"Message": "No HTTP resource was found that matches the request URI 'http://10.0.1.102:21212/file/upload/'."
The class object of the request looks like this:
Public Class FileULRequest
Public Property EncToken As String 'Holds an encrypted token for authorization
Public Property Filename As String 'Holds a recommended file name
Public Property AppID As String 'Holds the client/app ID for simpler server actions
Public Property File As Byte() 'Not sure if this is the right type/ should be the encrypted file contents.
End Class
The POST function signature currently looks like this:
Imports System.Web.Http
Namespace Controllers
Public Class FileController
Inherits ApiController
Public Function PostUpload(<FromBody()> ByVal ObjRequest As FileULRequest) As String
Return ""
End Function
End Class
End Namespace
In the Sub Main I have: (note, this is cleaned out)
Sub Main()
API_URL = Dns.GetHostByName(Dns.GetHostName()).AddressList(0).ToString()
Dim ThisConfig As New HttpSelfHostConfiguration("HTTP://" & API_URL & ":" & API_PORT)
ThisConfig.Routes.MapHttpRoute(name:="FileUpload", routeTemplate:="{controller}/{ObjRequest}", defaults:=New With {.id = RouteParameter.Optional})
ThisConfig.MaxConcurrentRequests = API_MaxCon
Dim Config As HttpSelfHostConfiguration = ThisConfig
Using Webserver As New HttpSelfHostServer(Config)
Try
Webserver.OpenAsync().Wait() 'Start the web server
Console.WriteLine("Listening at: " & API_URL & ":" & API_PORT) 'use the URL & port defined
Console.WriteLine("Enter to end")
Catch ex As Exception
Console.WriteLine("Error:{0}", ex.Message.ToString)
Console.WriteLine("Enter to end")
Console.ReadLine()
End
End Try
Dim Cmd As String = UCase(Console.ReadLine())
End
End Using
End Sub
API_Port and API_MaxCon are properties stored in the Appsettings.
What I'm trying to do is set the FileULRequest object params, post this to the service, confirm & validate the data and, if successful, save the file onto a network share. I've tried a large number of different combinations and nothing seems to get close; I cant get inside the Post event in the debugger to figure out or test anything.

How to new a new access token from a refresh token using vb.net?

I don't know if you can help me understand the right way forward with this issue. I need to provide a little bit of background first.
I have a VB.Net Console Utility that uses the Google V3 Calendar API. This utility has the following process to authenticate:
Private Function DoAuthentication(ByRef rStrToken As String, ByRef rParameters As OAuth2Parameters) As Boolean
Dim credential As UserCredential
Dim Secrets = New ClientSecrets() With {
.ClientId = m_strClientID,
.ClientSecret = m_strClientSecret
}
'm_Scopes.Add(CalendarService.Scope.Calendar)
m_Scopes.Add("https://www.googleapis.com/auth/calendar https://www.google.com/m8/feeds/ https://mail.google.com/")
Try
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(Secrets, m_Scopes,
"user", CancellationToken.None,
New FileDataStore("PublicTalkSoftware.Calendar.Application")).Result()
' Create the calendar service using an initializer instance
Dim initializer As New BaseClientService.Initializer() With {
.HttpClientInitializer = credential,
.ApplicationName = "~~~~~~~~~~"
}
m_Service = New CalendarService(initializer)
rStrToken = credential.Token.AccessToken.ToString()
rParameters.AccessToken = credential.Token.AccessToken
rParameters.RefreshToken = credential.Token.RefreshToken
Catch ex As Exception
' We encountered some kind of problem, perhaps they have not yet authenticated?
Return False
End Try
Return True
End Function
This part of the application process works fine. The data store file gets created and once the user has authenticated it all seems to just work find from there on. The user will be able to update the calendar without any further authenticating on there part.
Now, I also have a part of my MFC (the main application) project that sends emails for the user. This uses the following CkMainManW library.
For the most part that works too. If the user has correctly set up their credentials it is fine. However, if they are using GMail, then I do things slightly differently. This is to avoid the need to have the "Allow third party apps" option to be ticked in the Google account.
So, for GMail users, we send emails like this:
mailman.put_SmtpUsername(strUsername);
mailman.put_OAuth2AccessToken(strGoogleToken);
As you can see, I use the OAuth2AccessToken. This actual value passed is the credential.Token.AccessToken.ToString() value stored from when the user authenticated. Now, I have since understood that this actual token only lasts for one hour. This would explain why some users have to repeatedly run my calendar authentication again to get a new access token.
Clearly, when I do the calendar authentication which uses the data store file, it does something under the hood the avoid the user being asked all the time to authenticate.
Now, I have read this tutorial about using the Chilkat Library for this. I notice now that in the sample code it has a comment:
// Now that we have the access token, it may be used to send as many emails as desired
// while it remains valid. Once the access token expires, a new access token should be
// retrieved and used.
So, with all the background, how do I resolve my issue? So I have a data store file that contains the original access token from when they authorised and a refresh token. This file was created by the VB.Net command line module.
By the sounds of it, the Chilkat routine needs an access token that is valid. So, what is the right way for me to get an updated access token from the refresh token, so that when I send emails it won't fail after an hour?
Update
I am getting myself confused. I changed my code so that it called the DoAuthentification call above to get the refresh token and access token. But I am finding that the actual data store file is not getting revised. The text file is not being revised.
I have to revoke access and then do the authentication to get the data store file revised. And it is only once it has been revised that the access token will work for sending emails.
I think I have found the solution. I saw this answer:
https://stackoverflow.com/a/33813994/2287576
Based on the answer I added this method:
Private Function RefreshAuthentication(ByRef rStrAccessToken As String, ByRef rStrRefreshToken As String) As Boolean
Dim parameters As New OAuth2Parameters
With parameters
.ClientId = m_strClientID
.ClientSecret = m_strClientSecret
.AccessToken = rStrAccessToken ' Needed?
.RefreshToken = rStrRefreshToken
.AccessType = "offline"
.TokenType = "refresh"
.Scope = "https://www.googleapis.com/auth/calendar https://www.google.com/m8/feeds/ https://mail.google.com/"
End With
Try
Google.GData.Client.OAuthUtil.RefreshAccessToken(parameters)
rStrAccessToken = parameters.AccessToken
rStrRefreshToken = parameters.RefreshToken
RefreshAuthentication = True
Catch ex As Exception
RefreshAuthentication = False
End Try
End Function
I am not sure if I need to pass in the existing access token or not before refreshing. But either way, the tokens get updated and I can proceed with sending emails.
FYI, in the end it became apparent that I did not need any bespoke Refresh at all because the system manages it for you under the hood.
Private Async Function DoAuthenticationAsync() As Task(Of Boolean)
Dim credential As UserCredential
Dim Secrets = New ClientSecrets() With {
.ClientId = m_strClientID,
.ClientSecret = m_strClientSecret
}
Try
credential = Await GoogleWebAuthorizationBroker.AuthorizeAsync(Secrets, m_Scopes,
"user", CancellationToken.None,
New FileDataStore("xxx.Calendar.Application"))
' Create the calendar service using an initializer instance
Dim initializer As New BaseClientService.Initializer() With {
.HttpClientInitializer = credential,
.ApplicationName = "yy"
}
m_Service = New CalendarService(initializer)
Catch ex As Exception
' We encountered some kind of problem, perhaps they have not yet authenticated?
' Can we isolate that as the exception?
m_logger.Error(ex, "DoAuthenticationAsync")
Return False
End Try
Return True
End Function
I have not required any bespoke Refresh of tokens for a long time now.

Google Sheets API v4 receives HTTP 401 responses for public feeds

I'm having no luck getting a response from v4 of the Google Sheets API when running against a public (i.e. "Published To The Web" AND shared with "Anyone On The Web") spreadsheet.
The relevant documentation states:
"If the request doesn't require authorization (such as a request for public data), then the application must provide either the API key or an OAuth 2.0 token, or both—whatever option is most convenient for you."
And to provide the API key, the documentation states:
"After you have an API key, your application can append the query parameter key=yourAPIKey to all request URLs."
So, I should be able to get a response listing the sheets in a public spreadsheet at the following URL:
https://sheets.googleapis.com/v4/spreadsheets/{spreadsheetId}?key={myAPIkey}
(with, obviously, the id and key supplied in the path and query string respectively)
However, when I do this, I get an HTTP 401 response:
{
error: {
code: 401,
message: "The request does not have valid authentication credentials.",
status: "UNAUTHENTICATED"
}
}
Can anyone else get this to work against a public workbook? If not, can anyone monitoring this thread from the Google side either comment or provide a working sample?
I managed to get this working. Even I was frustrated at first. And, this is not a bug. Here's how I did it:
First, enable these in your GDC to get rid of authentication errors.
-Google Apps Script Execution API
-Google Sheets API
Note: Make sure the Google account you used in GDC must be the same account you're using in Spreadsheet project else you might get a "The API Key and the authentication credential are from different projects" error message.
Go to https://developers.google.com/oauthplayground where you will acquire authorization tokens.
On Step 1, choose Google Sheets API v4 and choose https://www.googleapis.com/auth/spreadsheets scope so you have bot read and write permissions.
Click the Authorize APIs button. Allow the authentication and you'll proceed to Step 2.
On Step 2, click Exchange authorization code for tokens button. After that, proceed to Step 3.
On Step 3, time to paste your URL request. Since default server method is GET proceed and click Send the request button.
Note: Make sure your URL requests are the ones indicated in the Spreadsheetv4 docs.
Here's my sample URL request:
https://sheets.googleapis.com/v4/spreadsheets/SPREADSHEET_ID?includeGridData=false
I got a HTTP/1.1 200 OK and it displayed my requested data. This goes for all Spreadsheetv4 server-side processes.
Hope this helps.
We recently fixed this and it should now be working. Sorry for the troubles, please try again.
The document must be shared to "Anyone with the link" or "Public on the web". (Note: the publishing settings from "File -> Publish to the web" are irrelevant, unlike in the v3 API.)
This is not a solution of the problem but I think this is a good way to achieve the goal. On site http://embedded-lab.com/blog/post-data-google-sheets-using-esp8266/ I found how to update spreadsheet using Google Apps Script. This is an example with GET method. I will try to show you POST method with JSON format.
How to POST:
Create Google Spreadsheet, in the tab Tools > Script Editor paste following script. Modify the script by entering the appropriate spreadsheet ID and Sheet tab name (Line 27 and 28 in the script).
function doPost(e)
{
var success = false;
if (e != null)
{
var JSON_RawContent = e.postData.contents;
var PersonalData = JSON.parse(JSON_RawContent);
success = SaveData(
PersonalData.Name,
PersonalData.Age,
PersonalData.Phone
);
}
// Return plain text Output
return ContentService.createTextOutput("Data saved: " + success);
}
function SaveData(Name, Age, Phone)
{
try
{
var dateTime = new Date();
// Paste the URL of the Google Sheets starting from https thru /edit
// For e.g.: https://docs.google.com/---YOUR SPREADSHEET ID---/edit
var MyPersonalMatrix = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/---YOUR SPREADSHEET ID---/edit");
var MyBasicPersonalData = MyPersonalMatrix.getSheetByName("BasicPersonalData");
// Get last edited row
var row = MyBasicPersonalData.getLastRow() + 1;
MyBasicPersonalData.getRange("A" + row).setValue(Name);
MyBasicPersonalData.getRange("B" + row).setValue(Age);
MyBasicPersonalData.getRange("C" + row).setValue(Phone);
return true;
}
catch(error)
{
return false;
}
}
Now save the script and go to tab Publish > Deploy as Web App.
Execute the app as: Me xyz#gmail.com,
Who has access to the app: Anyone, even anonymous
Then to test you can use Postman app.
Or using UWP:
private async void Button_Click(object sender, RoutedEventArgs e)
{
using (HttpClient httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(#"https://script.google.com/");
httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("utf-8"));
string endpoint = #"/macros/s/---YOUR SCRIPT ID---/exec";
try
{
PersonalData personalData = new PersonalData();
personalData.Name = "Jarek";
personalData.Age = "34";
personalData.Phone = "111 222 333";
HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(personalData), Encoding.UTF8, "application/json");
HttpResponseMessage httpResponseMessage = await httpClient.PostAsync(endpoint, httpContent);
if (httpResponseMessage.IsSuccessStatusCode)
{
string jsonResponse = await httpResponseMessage.Content.ReadAsStringAsync();
//do something with json response here
}
}
catch (Exception ex)
{
}
}
}
public class PersonalData
{
public string Name;
public string Age;
public string Phone;
}
To above code NuGet Newtonsoft.Json is required.
Result:
If your feed is public and you are using api key, make sure you are throwing a http GET request.In case of POST request, you will receive this error.
I faced same.
Getting data using
Method: spreadsheets.getByDataFilter has POST request

windows 8 store FTP

I'm building a windows store application in VB.net, and when I try to get the certification, so I can publish it in the store, it fails the API test, because it doesn't accept the fact that I used AlexPilotti's FTPSClient dll.
The only thing I have to do is to upload a small video to the ftp server. Pretty simple, right? It's working properly, both in PC and Tablet, the only problem is the certification.
I had to use AlexPilotti's FTPSClient dll because "ftpwebrequest" is gone from Windows Store.
So, I wonder if there is anything else I can try, maybe a windows store compatible dll?
I have tried BackgroundTransfer, but apparently it only works with HTTP and HTTPS, not FTP.
I've been trying to find an answer for a few days now, but what I find never seems to work.
Thanks in advance!
Found this example by searching but didn't test it. Google is a programmers best friend.
Public Async Function FTP_Uploader(ftpURL As String, filename As String, username As String, password As String, UploadText As String) As Task(Of Boolean)
Try
Dim request As WebRequest = WebRequest.Create(ftpURL + "/" + filename)
request.Credentials = New System.Net.NetworkCredential(username.Trim(), password.Trim())
request.Method = "STOR"
Dim buffer As Byte() = Encoding.UTF8.GetBytes(UploadText)
Dim requestStream As Stream = Await request.GetRequestStreamAsync()
Await requestStream.WriteAsync(buffer, 0, buffer.Length)
Await requestStream.FlushAsync()
Return True
Catch ex As Exception
Return False
End Try End Function

Can somebody give me an example of getting the content of a page from a URL in vb.net for windows 8?

I am very new to vb/.net and I'm trying to do something that I can do easily in classic vb. I want to get the source html for a webpage from the URL.
I'm using vb.net in Visual Studio Express for Windows 8.
I've read loads of stuff that talk about HttpWebRequest, but I can't get it to work properly.
I did at one point have it returning the html header, but I want to content of the page. Now, I can't even get it back to giving me the header. Ultimately, I want to process the html returned which I'll do (to begin with) the old-fashioned way and process the returned html as a string, but for now I'd like to just get the page.
The code I've got is:
Dim URL As String = "http://www.crayola.com/"
Dim request As System.Net.HttpWebRequest = System.Net.HttpWebRequest.Create(New Uri(URL))
txtHTML.Text = request.GetRequestStreamAsync().ToString()
Can anyone help me with an example to get me going please?
You're trying to use an Async method in a synchronous way, which won't make any sense. If you're using .NET 4.5, you can try marking the calling method with Async and then using the Await keyword when calling GetRequestStreamAsync.
Public Sub MyDownloaderMethod()
Dim URL As String = "http://www.crayola.com/"
Dim request As System.Net.HttpWebRequest
= System.Net.HttpWebRequest.Create(New Uri(URL))
' Use the Await keyword wait for the async task to complete.
Dim response = request.GetResponseAsync()
txtHTML.Text = response.GetResponseStream().ToString()
End Function
See the following MSDN article for more information on async programming with the Await keyword: http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx
Edit
You are receiving your error because you're trying to get the Request stream (what you send the server), and what you really want is the Response stream (what the server sends back to you). I've updated my code to get the WebResponse from your WebRequest and then retrieve the stream from that.
Public Shared Function GetWebPageString(ByVal address As Uri) As String
Using client As New Net.WebClient()
Return client.DownloadString(address)
End Using
End Function
There is also DownloadStringAsync if you don't want to block
request.GetRequestStreamAsync() is probably not a method. I think you're cribbing code from a site where someone wrote their own add-on methods to HttpWebRequest. Try request.GetResponse() to return a response object, then in the response object you can inspect the stream and convert it to text if you need to.
This worked for me in VB.Net 4.5
Public Async Sub GetHTML()
Dim PageHTML as string
Dim client As New HttpClient
Dim getStringTask As Task(Of String) = client.GetStringAsync(PageURL)
PageHTML = Await getStringTask
MsgBox(PageHTML)
End Sub