ScriptManager is not declared - err msg - vb.net

I've this class and it gave me an error name 'ScriptManager is not declared'
Public NotInheritable Class ResponseHelper
Private Sub New()
End Sub
Public Shared Sub Redirect(ByVal response As HttpResponse, ByVal url As String, ByVal target As String, ByVal windowFeatures As String)
If ([String].IsNullOrEmpty(target) OrElse target.Equals("_self", StringComparison.OrdinalIgnoreCase)) AndAlso [String].IsNullOrEmpty(windowFeatures) Then
response.Redirect(url)
Else
Dim page As Page = DirectCast(HttpContext.Current.Handler, Page)
If page Is Nothing Then
Throw New InvalidOperationException("Cannot redirect to new window outside Page context.")
End If
url = page.ResolveClientUrl(url)
Dim script As String
If Not [String].IsNullOrEmpty(windowFeatures) Then
script = "window.open(""{0}"", ""{1}"", ""{2}"");"
Else
script = "window.open(""{0}"", ""{1}"");"
End If
script = [String].Format(script, url, target, windowFeatures)
ScriptManager.RegisterStartupScript(page, GetType(Page), "Redirect", script, True)
End If
End Sub
End Class
This code from this link:
http://weblogs.asp.net/infinitiesloop/archive/2007/09/25/response-redirect-into-a-new-window-with-extension-methods.aspx
I've been 8 hours trying to figure out how to open a new page and send parameters to it. And found this code , and 6 hours trying to apply it but nothing.
Thanks.

You need Ajax to be installed to access the Scriptmanager.
Use Page.ClientScript.RegisterStartupScript instead.
If you want a solution that works whether AJAX is available or not, have a look at this link.

Try put the full name space before scirptmananger, System.UI.Web.ScriptManager.RegisterStartupScript(...)

Related

Async download function, how to do it? VB.NET

I am working on coronavirus statistics dashboard as university project, and I have some problems with asynchronous source data download from sites with statistics.
Well, I failed to understand how to do it myself.
I tried to create my own class with function what will create multiple async web requests
and then wait until they all finished, then return results of all these requests.
Imports System.Net.WebClient
Imports System.Net
Public Class AsyncDownload
Private result As New Collection
Private Sub DownloadCompletedHander(ByVal sender As Object, ByVal e As System.Net.DownloadStringCompletedEventArgs)
If e.Cancelled = False AndAlso e.Error Is Nothing Then
Dim myString As String = CStr(e.Result)
result.Add(myString, sender.Headers.Item("source"))
End If
End Sub
Public Function Load(sources As Array, keys As Array) As Collection
Dim i = 0
Dim WebClients As New Collection
While (i < sources.Length)
Dim newClient As New WebClient
newClient.Headers.Add("source", keys(i))
newClient.Headers.Add("sourceURL", sources(i))
AddHandler newClient.DownloadStringCompleted, AddressOf DownloadCompletedHander
WebClients.Add(newClient)
i = i + 1
End While
i = 1
For Each client As WebClient In WebClients
Dim url As String = client.Headers.Item("sourceURL")
client.DownloadStringAsync(New Uri(url))
Next
While (result.Count < WebClients.Count)
End While
Return result
End Function
End Class
And it is used in:
Dim result As New Collection
Private Sub test() Handles Me.Load
Dim downloader As New CoronaStatisticsGetter.AsyncDownload
result = downloader.Load({"https://opendata.digilugu.ee/covid19/vaccination/v3/opendata_covid19_vaccination_total.json"}, {"Nationalwide Data"})
End Sub
It should work like:
I create a new instance of my class.
Calling function Load of this class
Funciton Load creates instances of System.Net.WebClient for each url and adds as handler DownloadCompletedHander
Function Load goes calls DownloadStringAsync of each client
Function Load waits in While loop until result collection items count is not as big as number of url on input
If item count in result is same as urls number that means what everything is downloaded, so it breaks loop and returns all requested data
The problem is that it doesn't work, it just endlessly remain in while loop, and as I see using debug collection result is not updated (its size is always 0)
Same time, when I try to asynchronously download it without using my class, everything works fine:
Private Sub Download() 'Handles Me.Load
Dim wc As New System.Net.WebClient
wc.Headers.Add("source", "VaccinationByAgeGroup")
AddHandler wc.DownloadStringCompleted, AddressOf DownloadCompletedHander
wc.DownloadStringAsync(New Uri("https://opendata.digilugu.ee/covid19/vaccination/v3/opendata_covid19_vaccination_agegroup.json"))
End Sub
Could somebody tell me please why it is not working and where is the problem?
The following shows how one can use System.Net.WebClient with Task to download a string (ie: data) from a URL.
Add a project reference (System.Net)
VS 2019:
In VS menu, click Project
Select Add reference...
Select Assemblies
Check System.Net
Click OK
Create a class (name: DownloadedData.vb)
Public Class DownloadedData
Public Property Data As String
Public Property Url As String
End Class
Create a class (name: HelperWebClient.vb)
Public Class HelperWebClient
Public Async Function DownloadDataAsync(urls As List(Of String)) As Task(Of List(Of DownloadedData))
Dim allTasks As List(Of Task) = New List(Of Task)
Dim downloadedDataList As List(Of DownloadedData) = New List(Of DownloadedData)
For i As Integer = 0 To urls.Count - 1
'set value
Dim url As String = urls(i)
Debug.WriteLine(String.Format("[{0}]: Adding {1}", i, url))
Dim t = Task.Run(Async Function()
'create new instance
Dim wc As WebClient = New WebClient()
'await download
Dim result = Await wc.DownloadStringTaskAsync(url)
Debug.WriteLine(url & " download complete")
'ToDo: add desired code
'add
downloadedDataList.Add(New DownloadedData() With {.Url = url, .Data = result})
End Function)
'add
allTasks.Add(t)
Next
For i As Integer = 0 To allTasks.Count - 1
'wait for a task to complete
Dim t = Await Task.WhenAny(allTasks)
'remove from List
allTasks.Remove(t)
'write data to file
'Note: The following is only for testing.
'The index in urls won't necessarily correspond to the filename below
Dim filename As String = System.IO.Path.Combine("C:\Temp", String.Format("CoronavirusData_{0:00}.txt", i))
System.IO.File.WriteAllText(filename, downloadedDataList(i).Data)
Debug.WriteLine($"[{i}]: Filename: {filename}")
Next
Debug.WriteLine("all tasks complete")
Return downloadedDataList
End Function
End Class
Usage:
Private Async Sub btnRun_Click(sender As Object, e As EventArgs) Handles btnRun.Click
Dim helper As HelperWebClient = New HelperWebClient()
Dim urls As List(Of String) = New List(Of String)
urls.Add("https://opendata.digilugu.ee/covid19/vaccination/v3/opendata_covid19_vaccination_total.json")
urls.Add("https://api.covidtracking.com/v2/states.json")
urls.Add("https://covidtrackerapi.bsg.ox.ac.uk/api/v2/stringency/date-range/2020-01-01/2022-03-01")
urls.Add("http://covidsurvey.mit.edu:5000/query?age=20-30&gender=all&country=US&signal=locations_would_attend")
Dim downloadedDataList = Await helper.DownloadDataAsync(urls)
Debug.WriteLine("Complete")
End Sub
Resources:
How do I wait for something to finish in C#?
How should Task.Run call an async method in VB.NET?
VB.net ContinueWith

Checkpoints in functions VB.NET

I have a function that check validity of inserted data of a form, and in this function I have to ask some confirmation from user, and this confirmation need to be asked outside of the function, so if I hit one of this confirmations, I create the message and send out the validation function, user confirms or not and the function would called again
so here is the problem: I need to put some checkpoints in my function so when I call the validation function I jump to that checkpoint with the selected confirmation from user and run the validation function from that checkpoint
1: is this possible at all?
2: any ideas to do this?
Edit 1: I'm doing this validation in my business layer and can not show any message boxes from there, I just create the message and return it to the UI layer and the answer get from the user and function call again with this answer but I don't want to run the function from beginning and need to run it from where I left
Public Class BL
Private Queue As Queue(Of String)
Public Sub New()
Dim checkpoints = New String(){"CheckPoint1","CheckPoint2","CheckPoint3"}
checkpoints.ToList.ForEach(Function(item) <b>Queue.Enqueue(item)</b>)
End Sub
Public Function Func(ByVal res As Response,ParamArray ByVal params As String()) As Response
Dim response As Response
Dim chk = Queue.Dequeue()
GoTo chk
CheckPoint1:
'Do some stuff
response = New Response(Response.ResponseType.Message,"Are you sure you wanna do this?")
Return response
CheckPoint2:
If(res.Type = Response.ResponseType.ResponseBack)
Dim r As DialogResult = Convert.ChangeType([Enum].Parse(GetType(DialogResult),res.Message),GetType(DialogResult))
If (r= DialogResult.OK)
'Do stuffs on DialogResult.Yes
Else
'Do stuffs on DialogResult.No
End If
'Do other stuffs with database
End If
' Do other stuff
response = New Response(Response.ResponseType.Message,"You should do this!!OK?")
Return response
CheckPoint3:
'Do stuff like CheckPoint1
End Function
End Class
Public Class Response
Friend Enum ResponseType
Message
Result
ResponseBack
None
End Enum
Friend Message As String
Friend Type As ResponseType
Friend Sub New(ByVal type As ResponseType,msg As String)
Message=msg
Type= type
End Sub
End Class
Public Class Form1
Public Sub New()
' This call is required by the designer.
InitializeComponent()
Dim BL As New BL()
' Add any initialization after the InitializeComponent() call.
Dim rese As Response
Do
rese =BL.Func(Nothing)
BL.Func(new Response(Response.ResponseType.ResponseBack,if(MessageBox.Show(rese.Message).ToString())))
Loop Until rese.Type <> Response.ResponseType.Result
MessageBox.Show(if(rese.Message="True","OK","ERROR"))
End Sub
End Class
This is not an objective answer but could help. You need some sort of class that contains question and answers. Your validation class would return a list of question (are you sure?).
Class ValidationOutput
ValidationId
Message
Result
End Class
After calling your validation function, you get a list of validation that need extra information from the user. This can be handle outside of the validation function. When you get the extra information, call the validation again and pass the same list as parameter. When validating, look at the list to see if all the extra information needed is there.
I believe your business logic should not deal with user interactions and split to two parts.
However, if you prefer this way, you can use callbacks. Define a delegate parameter for your validation/business method and call that delegate when you need confirmation. According to return value continue to save operation or not.
You can check link below for delegate passing to a method.
https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/delegates/how-to-pass-procedures-to-another-procedure
This should work for you:
Public Class BL
Private Queue As Queue(Of String)
Private _checkpoints As Dictionary(Of String, Func(Of Response, Response)) = New Dictionary(Of String, Func(Of Response, Response)) From
{
{ "CheckPoint1", Function (res) New Response(Response.ResponseType.Message, "Are you sure you wanna do this?") },
{ "CheckPoint2", Function (res)
If (res.Type = Response.ResponseType.ResponseBack)
Dim r As DialogResult = CType(Convert.ChangeType([Enum].Parse(GetType(DialogResult), res.Message), GetType(DialogResult)), DialogResult)
If (r = DialogResult.OK)
'Do stuffs on DialogResult.Yes
Else
'Do stuffs on DialogResult.No
End If
'Do other stuffs with database
End If
' Do other stuff
Return New Response(Response.ResponseType.Message, "You should do this!!OK?")
End Function
},
{ "CheckPoint3", Function (r) New Response(Response.ResponseType.Message, "Are you sure you wanna do this?") }
}
Public Sub New()
_checkpoints.ToList().ForEach(Sub(item) Queue.Enqueue(item.Key))
End Sub
Public Function Func(ByVal res As Response, ParamArray ByVal params As String()) As Response
Dim chk = Queue.Dequeue()
Return _checkpoints(chk).Invoke(res)
End Function
End Class
Basically this creates a Dictionary(Of String, Func(Of Response, Response)) that maps a String to a Func(Of Response, Response) that returns the Response that you want.
There would be a couple of variations on this that might suit you better, but perhaps you could let me know if this does the job or not for you and I could suggest other options if need be.

delay sending mail with Exchange Web Services (EWS) Managed API

My issue is I cannot seem to put a delay on sending the item (have tried 2 minutes through to 2 days, no luck).
The mail itself sends immediately and without fail - it's just the delay that doesn't work? any help would be appreciated.
Note -
I have been using this as an example for most of my code.
I am using exchange 2010 SP2
The mail sends fine, just no delay
Public Class Mail
Private Const DEFERREDSENDTIMEFLAG As Integer = 16367
Public Shared ReadOnly Property EXCHANGESERVICEURL As String
Get
Return ConfigurationManager.AppSettings("EXCHANGESERVICEURL")
End Get
End Property
Public Shared ReadOnly Property DOMAINNAME As String
Get
Return ConfigurationManager.AppSettings("DOMAINNAME")
End Get
End Property
Public Shared ReadOnly Property EXCHANGEUSERNAME As String
Get
Return ConfigurationManager.AppSettings("EXCHANGEUSERNAME")
End Get
End Property
Public Shared ReadOnly Property EXCHANGEPASSWORD As String
Get
Return ConfigurationManager.AppSettings("EXCHANGEPASSWORD")
End Get
End Property
Public Shared ReadOnly Property EXCHANGEVERSION As ExchangeVersion
Get
Return CType(System.Enum.Parse(GetType(ExchangeVersion), ConfigurationManager.AppSettings("EXCHANGEVERSION")), ExchangeVersion)
End Get
End Property
Public Shared Sub SendMessage(ByVal fromAddress As String, ByVal toAddress() As String, ByVal ccAddress() As String, ByVal bccAddress() As String, ByVal subject As String, ByVal body As String, ByVal minutesDelay As Integer)
ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf ValidateCertificate)
Dim service As New ExchangeService(EXCHANGEVERSION)
service.Credentials = New WebCredentials(EXCHANGEUSERNAME, EXCHANGEPASSWORD, DOMAINNAME)
service.Url = New Uri(EXCHANGESERVICEURL)
Dim Message As New Microsoft.Exchange.WebServices.Data.EmailMessage(service)
'set delay send time
If minutesDelay > 0 Then
Dim sendTime As String = DateTime.Now.AddMinutes(minutesDelay).ToUniversalTime().ToString()
Dim PR_DEFERRED_SEND_TIME As New ExtendedPropertyDefinition(DEFERREDSENDTIMEFLAG, MapiPropertyType.SystemTime)
Message.SetExtendedProperty(PR_DEFERRED_SEND_TIME, sendTime)
End If
Message.From = fromAddress
If toAddress IsNot Nothing Then
For Each t As String In toAddress
Message.ToRecipients.Add(t)
Next
End If
If ccAddress IsNot Nothing Then
For Each t As String In ccAddress
Message.CcRecipients.Add(t)
Next
End If
If bccAddress IsNot Nothing Then
For Each t As String In bccAddress
Message.BccRecipients.Add(t)
Next
End If
Message.Subject = subject
Message.Body = body
Message.SendAndSaveCopy() 'save means make sure it's saved in the sent items folder
'message.Attachments
End Sub
Private Shared Function ValidateCertificate(sender As Object, certificate As X509Certificate, chain As X509Chain, sslPolicyErrors As SslPolicyErrors) As Boolean
Return True
End Function
End Class
I would suggest you used the typed variable rather then converting the Date-time to a string (like the example does) and then sending it. eg just use
Message.SetExtendedProperty(PR_DEFERRED_SEND_TIME, DateTime.Now.AddMinutes(minutesDelay).ToUniversalTime())
The library is designed to deal with typed variables but you can see the difference in the POST using a String vs Typed variable if you enable tracing eg
<t:ExtendedProperty>
<t:ExtendedFieldURI PropertyTag="16367" PropertyType="SystemTime"/>
<t:Value>2016-05-10T03:20:16.000</t:Value>
</t:ExtendedProperty>
vs
<t:ExtendedProperty>
<t:ExtendedFieldURI PropertyTag="16367" PropertyType="SystemTime"/>
<t:Value>2016-10-05T03:12:30.067Z</t:Value>
</t:ExtendedProperty>
You could also fix the string but using the typed varible makes more sense with that change you sample run fine for me.

Calling sub in different class not working right

I am creating a browser in VB.Net using Cefsharp. I created a custom LifeSpanHandler to handle Popup windows, but when I try to call a Public Sub in a different class, it is not giving the expected output.
I created my LifeSpanHandler using the following code:
Public Class LifeSpanHandler
Implements ILifeSpanHandler
Public Event PopupRequest As Action(Of String)
Public Function OnBeforePopup(browser As IWebBrowser, sourceUrl As String, targetUrl As String, ByRef x As Integer, ByRef y As Integer, ByRef width As Integer, ByRef height As Integer) As Boolean Implements ILifeSpanHandler.OnBeforePopup
RaiseEvent PopupRequest(targetUrl)
My.Settings.newpage = targetUrl
Call Form1.IntNewTab()
Return True
End Function
Public Sub OnBeforeClose(browser As IWebBrowser) Implements ILifeSpanHandler.OnBeforeClose
End Sub
End Class
And then I have browser.LifeSpanHandler = New LifeSpanHandler where it is Initialized. (With browser being CefSharp.WinForms.ChromiumWebBrowser)
I save the targetURL in My.Settings.newpage, then when the browser is initialized, it opens to that URL. In a different class (and a different Form), I have this code:
Public Sub IntNewTab()
Dim tab As New TabPage
Dim newtab As New tabs
newtab.Show()
newtab.Dock = DockStyle.Fill
newtab.TopLevel = False
tab.Controls.Add(newtab)
Me.CustomTabControl1.TabPages.Add(tab)
Me.PictureBox1.Location = New System.Drawing.Point(PictureBox1.Location.X + 150, 3)
My.Settings.newpage = My.Settings.homepage
Me.CustomTabControl1.SelectedTab = tab
End Sub
Which is the code to add a new tab. But in my LifeSpanHandler, when I Call Form1.IntNewTab(), the browser freezes out of focus. The window is grayed out (meaning it's out of focus) and I can't drag it around, and it stays on top of everything else, and I can't interact with any part of the browser.
To test something else out, I added a button to Form1 with the exact code from IntNewTab, and when I click on it, it opens a new tab to the specified page like normal. I also tried leaving the button visible, and OnBeforePopup adding Form1.Button1.PerformClick, but that did not work either. Anyone else have experience with doing this, or have any suggestions?
Edit:
I added the following codes to my browser to try and get rid of the default instance (the best I understood it):
To Form1:
Module Program
Friend frmMain As Form1
End Module
In Form1_Load:
`frmMain = Me`
Then I added this code in the LifeSpanHandler to reflect the changes:
Dim mainFrm = New Form1()
mainFrm.IntNewTab()
And that did not work. It just kept freezing out of focus like before. I also tried adding frmMain.IntNewTab() (the code that is in Form1_Load), and it still did not work.

How to call a public function from another form

Frm1 contains the code for validation of textbox:
Public Function AlphabeticalOnly(ByVal Str As String) As Boolean
Dim pattern As String = "^[a-zA-Z\s]+$"
Dim reg As New Regex(pattern)
If reg.IsMatch(Str) = False Then
MsgBox(Str & " is invalid! Please enter alphabetical characters only!", MsgBoxStyle.Critical, "Error")
End If
Return reg.IsMatch(Str)
End Function
Because there're quite an amount of validations, I don't want to repeat all the code again in the other forms.
Private Sub btnDone_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDone.Click
If AlphabeticalOnly(txtName.Text) = False Then
Exit Sub
End If
...
End Sub
I tried the code above in another form, but the error list shows that AlphabeticalOnly is not declared.
Is there anything that I need to add to my code?
First of all, don't put the function on a form. If it's common code shared by all forms, put it in its own class file.
Second, this common code shouldn't be prompting the user with a message box. This function should just perform the logic and nothing more. (This also makes the function easier to unit test.) Then allow the consuming code (in this case a form) to interact with the user. (Especially since the current implementation checks the match twice, which isn't necessary.)
Since this function doesn't rely on object state, you can make it Shared. Something like this:
Public Class CommonFunctions
Public Shared Function IsAlphabeticalOnly(ByVal Str As String) As Boolean
Dim pattern As String = "^[a-zA-Z\s]+$"
Dim reg As New Regex(pattern)
Return reg.IsMatch(Str)
End Function
End Class
Then on your forms you can invoke that function:
If CommonFunctions.IsAlphabeticalOnly(txtName.Text) = False Then
MsgBox(Str & " is invalid! Please enter alphabetical characters only!", MsgBoxStyle.Critical, "Error")
End If