DownloadStringAsync to get a text string? - vb.net

I am trying to create a Windows Phone 7.1 application, basically a currency converter. I am using DownloadStringAsync method to get a short string containing the exchange rate from a specific website. I tested in Visual Studio 2010, DownloadString worked just fine. But not for the phone application. What do I need to do here? I can't really make much sense of it.
Partial Public Class MainPage
Inherits PhoneApplicationPage
Dim webClient As New System.Net.WebClient
Dim a As String
Dim b As String
Dim result As String = Nothing
' Constructor
Public Sub New()
InitializeComponent()
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
a = "USD"
b = "GBP"
webClient = New WebClient
Dim result As String = webClient.DownloadStringAsync(New Uri("http://rate-exchange.appspot.com/currency?from=" + a + "&to=" + b) as String)
TextBox1.Text = result
End Sub
End Class

A few things wrong here:
DownloadStringAsync does not return a value (void method in C# terms)
You need to handle the DownloadStringCompleted event for WebClient variable. You can get the result in the event handler.
You can change your code to something like this to get the above to work:
Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
a = "USD"
b = "GBP"
webClient = New WebClient
'Add the event handler here
AddHandler webClient.DownloadStringCompleted, AddressOf webClient_DownloadStringCompleted
Dim url As String = "http://rate-exchange.appspot.com/currency?from=" & a & "&to=" & b
webClient.DownloadStringAsync(New Uri(url))
End Sub
Private Sub webClient_DownloadStringCompleted(ByVal sender as Object,ByVal e as DownloadStringCompletedEventArgs)
TextBox1.Text = e.result
End Sub

Just use DownloadStringTaskAsync:
Using WebClient As WebClient = New WebClient
Return Await WebClient.DownloadStringTaskAsync(New Uri(myurl))
End Using

Related

Download PDF using WebView2 cookie

I'm trying to download a PDF using WebView2.
I can login on the browser but then i would like to download a PDF using WebClient.
But this returns me to the login screen.
Both WebView browsers use the same UserDataFolder.
I would like to download the PDF using the cookie settings used in the WebView2 browser.
Below is a sample that i'm using, but i don't know how to use it.
I believe i'm on the right track...
Private Sub WV_CoreWebView2Ready1(sender As Object, e As EventArgs) Handles WebView_Browser1.CoreWebView2InitializationCompleted
WebView_Browser1.CoreWebView2.AddWebResourceRequestedFilter("*", CoreWebView2WebResourceContext.All)
AddHandler WebView_Browser1.CoreWebView2.WebResourceRequested, AddressOf CoreWebView2_WebResourceRequested
End Sub
Private Sub CoreWebView2_WebResourceRequested(ByVal sender As Object, ByVal e As CoreWebView2WebResourceRequestedEventArgs)
e.Request.Headers.SetHeader("Cookie", XXXXX) <<< i don't know how to use this
Dim addedDate = e.Request.Headers.GetHeader("Cookie")
End Sub
Private Async Sub WebView_Browser2_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs) Handles WebView_Browser2.NavigationCompleted
Dim url As String = pathtourl
Dim fileName As String = "pdf.pdf"
Dim webClient As WebClient = New WebClient()
webClient.Headers.Add(HttpRequestHeader.Cookie, WebView_Browser2.Cookie) <<< use cookie here to login?
webClient.DownloadFileAsync(New Uri(url, UriKind.Absolute), fileName)
End Sub
It would be great i somebody can help me with this!
Thanks!
Update
Dim LoginCookie As String
Private Sub WV_CoreWebView2Ready1(sender As Object, e As EventArgs) Handles WebView_Browser1.CoreWebView2InitializationCompleted
WebView_Browser1.CoreWebView2.AddWebResourceRequestedFilter("*", CoreWebView2WebResourceContext.All)
AddHandler WebView_Browser1.CoreWebView2.WebResourceRequested, AddressOf CoreWebView2_WebResourceRequested
AddHandler WebView_Browser1.CoreWebView2.WebResourceResponseReceived, AddressOf CoreWebView2_WebResourceResponseReceived
End Sub
Private Sub CoreWebView2_WebResourceResponseReceived(ByVal sender As Object, ByVal e As CoreWebView2WebResourceResponseReceivedEventArgs)
LoginCookie = e.Request.Headers.GetHeader("Login")
End Sub
Private Async Sub WebView_Browser2_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs) Handles WebView_Browser2.NavigationCompleted
Dim url As String = pathtourl
Dim fileName As String = "pdf.pdf"
Dim webClient As WebClient = New WebClient()
webClient.Headers.Add(HttpRequestHeader.Cookie, LoginCookie)
webClient.DownloadFileAsync(New Uri(url, UriKind.Absolute), fileName)
End Sub
The Webclient accepts the cookie to be webClient.Headers.Add(HttpRequestHeader.Cookie, "CITY=NY") like this.
But the e.Request.Headers.GetHeader("Login") doesn't get me the cookie.
Again thank you for looking!
You can use this to get the cookies in C# similar pattern for VB.NET
List<CoreWebView2Cookie> cookieList = await WebBrowser.CoreWebView2.CookieManager.GetCookiesAsync(CurrentAddress);
Then loop through to get the string values you are looking for
for (int i = 0; i < cookieList.Count; ++i)
{
CoreWebView2Cookie cookie = TopicWebBrowser.CoreWebView2.CookieManager.CreateCookieWithSystemNetCookie(cookieList[i].ToSystemNetCookie());
cookieResult.Append($"\n{cookie.Name} {cookie.Value} {(cookie.IsSession ? "[session cookie]" : cookie.Expires.ToString("G"))}");
}

How to download multiple URLs at the same time?

Public Class Form1
For i As Integer = 0 To RichTextBox1.Lines.Length - 1
wreq=System.Net.WebRequest.Create("i th Internet address")
wreq.AutomaticDecompression = Net.DecompressionMethods.GZip
wres = wreq.GetResponse
Dim s As System.IO.Stream = wres.GetResponseStream
Dim sr As New System.IO.StreamReader(s)
html = sr.ReadToEnd
s = html.Split(";")
'here is other codes
Next
End Class
this is part of my program.
When I use this, it takes a long time for everyone to download. How can I download all the addresses at the same time?
I found the following code on the internet enter code here to do this, but I do not know how to use it in the my program. Please help. Thank you.
Imports System.Threading.Tasks
Imports System.Net
Imports System.IO
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
'Start a background task so as not to freeze up the UI.
Me.BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim files As String() 'Get file paths.
'Download multiple files simultaneously.
Parallel.ForEach(files,
Sub(f) Call New WebClient().DownloadFile(f,
Path.Combine("local folder here",
Path.GetFileName(f))))
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
MessageBox.Show("All files downloaded")
End Sub
End Class
Take a look on this. Might be a good start (part of your code implemented on each method).
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim urls() As String = RichTextBox1.Lines.Select(Function(url) Trim(url))
Parallel.ForEach(urls, Sub(f)
If Not String.IsNullOrEmpty(f) Then
DownloadAsync(f)
End If
End Sub)
End Sub
Function DownloadAsync(URL As String) As Task(Of Boolean)
Try
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Dim html As String = ""
Dim result As Boolean
Dim request As HttpWebRequest = HttpWebRequest.Create(URL)
request.AutomaticDecompression = DecompressionMethods.GZip
request.Timeout = 500
request.Method = "GET"
request.UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0"
Using response As Task(Of WebResponse) = request.GetResponseAsync
If response.Result IsNot Nothing Then
Using ioStream As IO.Stream = response.Result.GetResponseStream
Using sr As New System.IO.StreamReader(ioStream)
html = sr.ReadToEnd
Dim s() As String = html.Split(";"c)
For Each sl In s
Debug.WriteLine(sl)
Next
End Using
result = True
End Using
End If
End Using
Return Task.FromResult(result)
Catch ex As Exception
Debug.WriteLine(ex.Message)
End Try
Return Task.FromResult(False)
End Function

Passing data through form with showdialog but without closing event

I have a first form (form_notice_hashtag) called like this:
Public Sub afficher_hashtag(hashtag As String, plateforme_hashtag As String)
Dim form_notice_hashtag_1 As New form_notice_hashtag
form_notice_hashtag_1.StartPosition = FormStartPosition.CenterScreen
form_notice_hashtag_1.Show()
End Sub
In form_notice_hashtag_1, i have a button calling a 2nd form (form_recherche_thesaurus) like this:
Private Sub hashtag_thesaurus_search_button_Click(sender As Object, e As EventArgs) Handles hashtag_thesaurus_search_button.Click
Dim form_recherche_thesaurus_1 As New form_recherche_thesaurus With {
.StartPosition = FormStartPosition.Manual,
.Location = New Point(Me.Left + Me.Width, Me.Top)
}
form_recherche_thesaurus_1.ShowDialog(Me)
End Sub
In form_recherche_thesaurus, i have a datagridview listing some words. The user can select one word, then by clicking a button in form_recherche_thesaurus, the word which will be added to a textbox in form_notice_hashtag
Private Sub thesaurus_ok_button_Click(sender As Object, e As EventArgs) Handles thesaurus_ok_button.Click
Dim list_terms_array As String()
Select Case Owner.Name.ToString
Case "form_notice_hashtag"
list_terms_array = Split(Remove_Duplicates_From_Strings_With_SemiColon(form_notice_hashtag.hashtag_descripteurs_txtbox.Text & ";" & selected_term), ";")
form_notice_hashtag.hashtag_descripteurs_txtbox.Text = (String.Join(";", list_terms_array.Where(Function(s) Not String.IsNullOrEmpty(s))))
End Select
End Sub
I used a select because this mechanism would be used in the same way with other forms than form_notice_hashtag.
Problem: the textbox in form_notice_hashtag is not filled with the selected keywords. I guess it's because of the way form_notice_hashtag is called.
I can't use the solution as explained here Send values from one form to another form because i understood (maybe badly) that this solution works only if the 2nd form (form_recherche_thesaurus in my case) is closed (i.e closing was the trigger) which i don't want.
How can I proceed?
Thanks to jmcilhinney and this page of his blog, here is the solution that allows to transfer several data from a called form (form_recherche_thesaurus) to a calling form (form_notice_hashtag) without closing the called form .
Public Class form_notice_hashtag
Private WithEvents form_recherche_thesaurus_1 As form_recherche_thesaurus
Private selected_thesaurus_term As String
Private Sub form_recherche_thesaurus_1_TextBoxTextChanged(sender As Object, e As EventArgs) Handles form_recherche_thesaurus_1.TextBoxTextChanged
Dim list_terms_array As String() = Split(Remove_Duplicates_From_Strings_With_SemiColon(Me.hashtag_descripteurs_txtbox.Text & ";" & form_recherche_thesaurus_1.selected_term), ";")
Me.hashtag_descripteurs_txtbox.Text = (String.Join(";", list_terms_array.Where(Function(s) Not String.IsNullOrEmpty(s))))
End Sub
Private Sub hashtag_thesaurus_search_button_Click(sender As Object, e As EventArgs) Handles hashtag_thesaurus_search_button.Click
Dim form_recherche_thesaurus_1 As New form_recherche_thesaurus With {
.StartPosition = FormStartPosition.Manual,
.Location = New Point(Me.Left + Me.Width, Me.Top)
}
If Me.form_recherche_thesaurus_1 Is Nothing OrElse Me.form_recherche_thesaurus_1.IsDisposed Then
Me.form_recherche_thesaurus_1 = New form_recherche_thesaurus With {
.StartPosition = FormStartPosition.Manual,
.Location = New Point(Me.Left + Me.Width, Me.Top)
}
Me.form_recherche_thesaurus_1.Show()
End If
Me.form_recherche_thesaurus_1.Activate()
End Sub
End Class
Public Class form_recherche_thesaurus
Public Event TextBoxTextChanged As EventHandler
Private term_thesaurus As String
Public Property selected_term() As String
Get
Return term_thesaurus
End Get
Set(ByVal value As String)
term_thesaurus = value
End Set
End Property
Private Sub thesaurus_ok_button_Click(sender As Object, e As EventArgs) Handles thesaurus_ok_button.Click
Dim list_terms_array As String()
Me.selected_term = Me.thesaurus_search_results_datagrid.Item(0, Me.thesaurus_search_results_datagrid.CurrentRow.Index).Value
Me.DialogResult = DialogResult.OK
RaiseEvent TextBoxTextChanged(Me, EventArgs.Empty)
End Sub

The GUI is not moving properly

I'm doing a little widget that shows the price of bitcoin using Binance API here
I'm not using Json format as I Just need to parse one string, eventhough I know many of you will say to use json. Anyway, I want to keep the software as simple as possible, but there is a little problem.
I'm downloading the source with webclient and Updating it using a timer.
I think I'm doing a mistake creating every time the new webclient because when I want to move the form, Is not properly mooving even if its not freezing.
The code I'm using is:
Private Sub webclientbtc()
Dim wc As New Net.WebClient
Dim WBTC As IO.Stream = Nothing
wc.Encoding = Encoding.UTF8
WBTC = wc.OpenRead("https://api.binance.com/api/v1/ticker/24hr?symbol=BTCEUR")
Dim btc As String
Using rd As New IO.StreamReader(WBTC)
btc = rd.ReadToEnd
End Using
'---------BTC PRICE---------'
Dim textBefore As String = """lastPrice"":"""
Dim textAfter As String = ""","
Dim startPosition As Integer = btc.IndexOf(textBefore)
startPosition += textBefore.Length
Dim endPosition As Integer = btc.IndexOf(textAfter, startPosition)
Dim textFound As String = btc.Substring(startPosition, endPosition - startPosition)
Dim dNumber As Double = Val(textFound.ToString)
Label1.Text = dNumber.ToString("n2")
'-------------------------------------'
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
webclientbtc()
End Sub
Timer interval is on 1000 ms, which is great to keep me update.
Any idea on how I can avoid the creations of new webclient at every update?
Thanks
Simplified, and using TAP:
Private wc as New WebClient()
Private Async Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim s = Await wc.DownloadStringTaskAsync("https://api.binance.com/api/v1/ticker/24hr?symbol=BTCEUR")
Dim d = JsonConvert.DeserializeObject(Of Dictionary(Of String, String))(s)
Label1.Text = d("lastPrice")
End Sub
You need to reference newtonsoft json package and imports it, as well as imports system.collections.generic
If the answer by Caius Jard is too good, you can avoid the use of a JSON deserialiser by using a regex:
Imports System.Net
Imports System.Text.RegularExpressions
Public Class Form1
Dim tim As New Timer()
Private Async Sub UpdateBtc(sender As Object, e As EventArgs)
' temporarily disable the timer in case the web request takes a long time
tim.Enabled = False
' using New Uri() makes sure it is a proper URI:
Dim url = New Uri("https://api.binance.com/api/v1/ticker/24hr?symbol=BTCEUR")
Dim rawJson As String
Using wb As New WebClient()
rawJson = Await wb.DownloadStringTaskAsync(url)
End Using
Dim re = New Regex("""lastPrice"":\s*""([0-9.-]+)""")
Dim lastPrice = re.Match(rawJson)?.Groups(1)?.Value
Dim p As Decimal
lblLastPrice.Text = If(Decimal.TryParse(lastPrice, p), p.ToString("N2"), "Fetch error.")
tim.Enabled = True
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
UpdateBtc(Nothing, EventArgs.Empty)
tim.Interval = 3000
AddHandler tim.Tick, AddressOf UpdateBtc
tim.Start()
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If tim IsNot Nothing Then
tim.Stop()
RemoveHandler tim.Tick, AddressOf UpdateBtc
tim.Dispose()
End If
End Sub
End Class
There's no need to re-use the WebClient, creating it is not what is taking up the time.
I prefer to instantiate timers myself: there is no requirement to do so.
It is better to use descriptive names for controls: "Label1" tells you nothing.

How to wait for get request without freezing client

I have a simple button which sends a get request to retrieve a txt file on my website. Problem is it freezes the application while retrieving the info. How can I make it so the application doesn't freeze while waiting for the result?
Private Sub cmd_ClickMe_Click(sender As Object, e As EventArgs) Handles cmd_ClickMe.Click
Dim request As String = String.Format("http://www.*****/database/test.txt")
Dim webClient As New System.Net.WebClient
Dim result As String = webClient.DownloadString(request)
MessageBox.Show(result)
End Sub
I've also tried the following but it doesn't work (says "webClient.DownloadStringAsync(myUri)" does not produce a value:
Private Sub cmd_ClickMe_Click_1(sender As Object, e As EventArgs) Handles cmd_ClickMe.Click
Dim request As String = String.Format("http://www.****.com/database/test.txt")
Dim webClient As New System.Net.WebClient
Dim myUri As Uri = New Uri(request)
Dim result As String = webClient.DownloadStringAsync(myUri)
MessageBox.Show(result)
End Sub
Use DownloadStringAsync(Uri) instead of the DownloadString(uri).
The DownloadStringAsync method does not block the calling thread.
Here is an example how to use it:
Dim wc As New WebClient
' Specify that you get alerted
' when the download completes.
AddHandler wc.DownloadStringCompleted, AddressOf AlertStringDownloaded
Dim uri As New Uri("http:\\changeMe.com") 'Pass the URL to here. This is just an example
wc.DownloadStringAsync(uri)
End Sub
Public Shared Sub AlertStringDownloaded(ByVal sender As Object, ByVal e As DownloadStringCompletedEventArgs)
' If the string request went as planned and wasn't cancelled:
If e.Cancelled = False AndAlso e.Error Is Nothing Then
Dim myString As String = CStr(e.Result) 'Use e.Result to get the String
MessageBox.Show(myString)
End If
End Sub