How to write an Async Sub in VB.NET? - vb.net

Public Class LoginManager
Implements ILoginManager
Private ReadOnly _iLoginRepository As ILoginRepository
Public Sub New()
_iLoginRepository = New LoginRepository()
End Sub
Public Async Sub InsertFailedLoginAttempt(failedLoginAttempt As FailedLogin) Implements ILoginManager.InsertFailedLoginAttempt
'Example of the S in Solid (Single Repsonsibilty)
'Need to call these method async. But await errors
_iLoginRepository.InsertFailedLoginAttemptAsync(failedLoginAttempt)
_iLoginRepository.InsertFailedLoginAttemptIntoLoginMasterAsync(failedLoginAttempt)
End Sub
End Class
Repsoitory Interface:
Public Interface ILoginRepository
Function IsUserAuthenticatedAsync(ByVal cID As String, ByVal password As String, ByVal IsExternalUser As Boolean) As Task(Of Boolean)
Sub InsertFailedLoginAttemptAsync(ByVal failedLoginAttempt As FailedLogin)
Sub InsertFailedLoginAttemptIntoLoginMasterAsync(ByVal failedLoginAttempt As FailedLogin)
End Interface
Repository Implementation:
Public Class LoginRepository
Implements ILoginRepository
Public ReadOnly _applicationDBContext As New ApplicationDBContext()
Public Async Sub InsertFailedLoginAttemptAsync(failedLoginAttempt As FailedLogin) Implements ILoginRepository.InsertFailedLoginAttemptAsync
Using _applicationDBContext
_applicationDBContext.RepFailedLogins.Add(failedLoginAttempt)
Await _applicationDBContext.SaveChangesAsync()
End Using
End Sub
Public Async Sub InsertFailedLoginAttemptIntoLoginMasterAsync(failedLoginAttempt As FailedLogin) Implements ILoginRepository.InsertFailedLoginAttemptIntoLoginMasterAsync
Using _applicationDBContext
_applicationDBContext.RepFailedLoginMasters.Add(failedLoginAttempt)
Await _applicationDBContext.SaveChangesAsync()
End Using
End Sub
''' <summary>
''' Determine whether a user is authenticated, be it an internal or external user
''' I have condensed two methods into one
''' </summary>
''' <param name="cID"></param>
''' <param name="password"></param>
''' <param name="IsExternalUser"></param>
''' <returns></returns>
Public Async Function IsUserAuthenticatedAsync(cID As String, password As String, IsExternalUser As Boolean) As Task(Of Boolean) Implements ILoginRepository.IsUserAuthenticatedAsync
If (IsExternalUser And String.IsNullOrEmpty(password)) Then
Throw New ArgumentNullException("External user requires password")
End If
Dim user As Chaser
Dim toRet As Boolean
Using _applicationDBContext
'Two ways to use LINQ
'First is LINQ Lambda sybntax(little harder to read)
user = Await _applicationDBContext.Chasers.Where(Function(x) x.CID = cID).FirstOrDefaultAsync()
'Second is LINQ Query syntax(looks more like SQL just more verbose
'user = From x In _applicationDBContext.Chasers
' Where x.CID = cID
' Select x
End Using
If IsNothing(user) Then
toRet = False
ElseIf Not IsExternalUser And Not IsNothing(user) Then
toRet = True
ElseIf IsExternalUser And user.Hash_Password = password Then
toRet = True
End If
Return toRet
End Function
End Class
I'm trying to call the InsertFailedLoginAttemptAsync repository method in my manager. It is an async method but I am unable to await the method. How can I make this method awaitable?
I believe it has something to do with the interface and not making it an async method like in C# but I'm unable to do this.

Subs should not be async. Event handlers are the only exception to that rule. You await Task which can only be returned from a Function. If the intention is to make that interface async then all the members need to be functions that return a Task or its derivative.
Async is something that bubbles all the way through when used. That said the ILoginManager along with the ILoginRepository should be refactored (if possible) to follow the proper syntax.
Reference: Async/Await - Best Practices in Asynchronous Programming

Fixed via Nkosi's reply:
Interface:
Public Interface ILoginRepository
Function IsUserAuthenticatedAsync(ByVal cID As String, ByVal password As String, ByVal IsExternalUser As Boolean) As Task(Of Boolean)
Function InsertFailedLoginAttemptAsync(ByVal failedLoginAttempt As FailedLogin) As Task
Function InsertFailedLoginAttemptIntoLoginMasterAsync(ByVal failedLoginAttempt As FailedLogin) As Task
End Interface
Manager method:
Public Async Function InsertFailedLoginAttempt(failedLoginAttempt As FailedLogin) As Task Implements ILoginManager.InsertFailedLoginAttempt
'Example of the S in Solid (Single Repsonsibilty)
Await _iLoginRepository.InsertFailedLoginAttemptAsync(failedLoginAttempt)
Await _iLoginRepository.InsertFailedLoginAttemptIntoLoginMasterAsync(failedLoginAttempt)
End Function

Related

"This method is not implemented by this class.": SoapHttpClientProtocol

I have two calls to my server application. One is normal Invoke method and another is InvokeAsync method. We are using HttpWebRequestCompressed code as well with request.Headers.Add("Accept-Encoding", "gzip, deflate").
Invoke method
<System.Web.Services.Protocols.SoapDocumentMethodAttribute("://abc.com/myApp/WS/OpenAllSupplier", RequestNamespace:="://abc.com/myApp/WS", ResponseNamespace:="://abc.com/myApp/WS", Use:=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle:=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)> _
Public Function OpenAllSupplier() As dsSupplier
Dim results() As Object = Me.Invoke("OpenAllSupplier", New Object(-1) {})
Return CType(results(0),dsSupplier)
End Function
Invoke Async method
Public Overloads Sub OpenSupplierAsync(ByVal buCode As String, ByVal buType As String, ByVal userState As Object)
If (Me.OpenSupplierOperationCompleted Is Nothing) Then
Me.OpenSupplierOperationCompleted = AddressOf Me.OnOpenSupplierOperationCompleted
End If
Me.InvokeAsync("OpenSupplier", New Object() {buCode, buType}, Me.OpenSupplierOperationCompleted, userState)
End Sub
Private Sub OnOpenSupplierOperationCompleted(ByVal arg As Object)
If (Not (Me.OpenSupplierCompletedEvent) Is Nothing) Then
Dim invokeArgs As System.Web.Services.Protocols.InvokeCompletedEventArgs = CType(arg,System.Web.Services.Protocols.InvokeCompletedEventArgs)
RaiseEvent OpenSupplierCompleted(Me, New OpenSupplierCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState))
End If
End Sub
WebRequest Class
Partial Public Class BusinessUnits
Inherits System.Web.Services.Protocols.SoapHttpClientProtocol
Protected Overrides Function GetWebRequest(ByVal uri As Uri) As System.Net.WebRequest
Try
'System.Net.HttpWebRequest.Create(uri) '
Dim request As HttpWebRequest = CType(MyBase.GetWebRequest(uri), HttpWebRequest)
request.Headers.Add("Accept-Encoding", "gzip, deflate")
Return New HttpWebRequestCompressed(request)
Catch ex As Exception
End Try
End Function
End Class
In HttpWebRequestCompressed class
Public Class HttpWebRequestCompressed
Inherits System.Net.WebRequest
Dim request As HttpWebRequest
Public Sub New(ByVal request As WebRequest)
Me.request = CType(request, HttpWebRequest)
End Sub
Public Overrides Function GetResponse() As WebResponse
Return New HttpWebResponseDecompressed(Me.request)
End Function
Public Overrides Function GetRequestStream() As Stream
Return New GZipStream(Me.request.GetRequestStream(), CompressionMode.Compress)
End Function
GetRequestStream executes only when Invoke method calls.
Invoke method is working as expected and no issues.
On Invoke Async the call is not going to Server, and we are getting error in client side as,
"This method is not implemented by this class."
What exactly I am missing here in Async call? Unable to get the method invoke in server only when Async call is happening.
Thank you for supporting.
Regards
Sangeetha

CodeAccessSecurityAttribute derived class throwing System.TypeLoadException (Failure has occurred while loading a type)

I have custom attribute applied to CRUD repository methods to control access:
Public Class SecureDbContextGenericRepository(Of TEntity As Class, TContext As DbContext)
Inherits DbContextGenericRepository(Of TEntity, TContext)
Public Sub New(connectionService As IConnectionService)
MyBase.New(connectionService)
End Sub
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
Public Overrides Sub Delete(ParamArray entities() As TEntity)
MyBase.Delete(entities)
End Sub
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
Public Overrides Sub Insert(ParamArray entities() As TEntity)
MyBase.Insert(entities)
End Sub
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataReader)>
Public Overrides Function [Select](Optional predicate As Func(Of TEntity, Boolean) = Nothing) As IList(Of TEntity)
Return MyBase.Select(predicate)
End Function
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
Public Overrides Sub Update(ParamArray entities() As TEntity)
MyBase.Update(entities)
End Sub
End Class
This is implementation of attribute:
Public Class EmployeeRoleRequirementAttribute
Inherits CodeAccessSecurityAttribute
Public Sub New(action As SecurityAction)
MyBase.New(action)
End Sub
Public Overrides Function CreatePermission() As IPermission
Return New EmployeeRolePermission(_EmployeeRoles)
End Function
Public Property EmployeeRoles As EmployeeRoles
End Class
<Flags>
Public Enum EmployeeRoles As Integer
DataReader = 0
DataWriter = 1
End Enum
And permission:
Public Class EmployeeRolePermission
Implements IPermission
Public Sub New(employeeRoles As EmployeeRoles)
_EmployeeRoles = employeeRoles
End Sub
Public Function Copy() As IPermission Implements IPermission.Copy
Return New EmployeeRolePermission(_EmployeeRoles)
End Function
Public Sub Demand() Implements IPermission.Demand
Dim principal = DirectCast(Thread.CurrentPrincipal, ProductionAssistantPrincipal)
If Not principal.IsInRole(_EmployeeRoles) Then
Throw New SecurityException(String.Format(My.Resources.EmployeeRoleNotFound,
principal.Identity.Name,
_EmployeeRoles.ToString()))
End If
End Sub
Public Sub FromXml(e As SecurityElement) Implements ISecurityEncodable.FromXml
Throw New NotImplementedException()
End Sub
Public Function Intersect(target As IPermission) As IPermission Implements IPermission.Intersect
Return New EmployeeRolePermission(_EmployeeRoles And DirectCast(target, EmployeeRolePermission).EmployeeRoles)
End Function
Public Function IsSubsetOf(target As IPermission) As Boolean Implements IPermission.IsSubsetOf
Return _EmployeeRoles.HasFlag(DirectCast(target, EmployeeRolePermission).EmployeeRoles)
End Function
Public Function ToXml() As SecurityElement Implements ISecurityEncodable.ToXml
Throw New NotImplementedException()
End Function
Public Function Union(target As IPermission) As IPermission Implements IPermission.Union
Return New EmployeeRolePermission(_EmployeeRoles Or DirectCast(target, EmployeeRolePermission).EmployeeRoles)
End Function
Public ReadOnly Property EmployeeRoles As EmployeeRoles
End Class
Every time one of the CRUD methods are reached, TypeLoadException is thrown. I really dont know cause of this, but if I remove attributes from CRUD methods, everything works fine.
This seems to be due to the enum-valued property on the attribute (see https://connect.microsoft.com/VisualStudio/feedback/details/596251/custom-cas-attributes-with-an-enum-property-set-cause-a-typeloadexception for details). To work around this issue, you could use a string-valued property on the attribute and cast to an enum either in the property setter or just before creating the permission. (Personally, I'd probably opt for the former in the interests of enabling early validation, but ymmv...)
Another workaround is making attribute property of type, which is used in Enum, in this case Integer.
Public Class EmployeeRoleRequirementAttribute
Inherits CodeAccessSecurityAttribute
Public Sub New(action As SecurityAction)
MyBase.New(action)
End Sub
Public Overrides Function CreatePermission() As IPermission
Return New EmployeeRolePermission(CType(_RequiredEmployeeRoles, EmployeeRoles))
End Function
Public Property RequiredEmployeeRoles As Integer
End Class
<Flags>
Public Enum EmployeeRoles As Integer
DataReader = 0
DataWriter = 1
End Enum
Then you dont need to use String, which does not allow easy combining of flags when attribute is used:
<EmployeeRoleRequirement(SecurityAction.Demand, RequiredEmployeeRoles:=EmployeeRoles.DataReader Or EmployeeRoles.DataWriter)>
Sub SecuredMethod()
End Sub

Mvvm. Textbox never change with System.Threading.Thread.Sleep

I want change a textbox value, but this code doesn't work. I see only the last value.
If you want to help me copy and paste the code .
Thanks a lot
This is XAML
<TextBox HorizontalAlignment="Left" Height="46"
Margin="4,4,4,4" VerticalAlignment="Top" Width="162"
Text="{Binding Path=Msg,
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
This is VB code.
Imports System.Threading
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System
Class MainWindow
Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
Dim x As New Abc
Me.DataContext = x
End Sub
End Class
Public Class Abc
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private Sub OnPropertyChanged(ByVal info As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
End Sub
Protected Sub OnNotifyPropertyChanged(propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Private Property _Msg As String
Public Property Msg As String
Get
Return _Msg
End Get
Set(value As String)
_Msg = value
OnPropertyChanged("Msg")
End Set
End Property
Private m_ButtonCommand As ICommand
Public Property ButtonCommand() As ICommand
Get
Return m_ButtonCommand
End Get
Set(value As ICommand)
m_ButtonCommand = value
End Set
End Property
Public Sub displayMessage(ByVal param As Object)
Msg = "How"
System.Threading.Thread.Sleep(1000)
Msg = "Are"
System.Threading.Thread.Sleep(1000)
Msg = "you"
System.Threading.Thread.Sleep(1000)
Msg = "?"
System.Threading.Thread.Sleep(1000)
End Sub
Private Function CandisplayMessage(ByVal param As Object) As Boolean
Return True
End Function
Public Sub New()
m_ButtonCommand = New DelegateCommand(AddressOf displayMessage, AddressOf CandisplayMessage)
End Sub
End Class
Public Class DelegateCommand
Implements ICommand
Private m_canExecute As Func(Of Object, Boolean)
Private m_executeAction As Action(Of Object)
Private m_canExecuteCache As Boolean
Public Event CanExecuteChanged(ByVal sender As Object, ByVal e As System.EventArgs) Implements ICommand.CanExecuteChanged
Public Sub New(ByVal executeAction As Action(Of Object), ByVal canExecute As Func(Of Object, Boolean))
Me.m_executeAction = executeAction
Me.m_canExecute = canExecute
End Sub
Public Function CanExecute(ByVal parameter As Object) As Boolean Implements ICommand.CanExecute
Dim temp As Boolean = m_canExecute(parameter)
If m_canExecuteCache <> temp Then
m_canExecuteCache = temp
RaiseEvent CanExecuteChanged(Me, New EventArgs())
End If
Return m_canExecuteCache
End Function
Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute
m_executeAction(parameter)
End Sub
End Class
.............................................
When you use Thread.Sleep on UI Thread you block the UI thread, So nothing can happen in UI. If you want to show a 1 second wait after each message you have two choices.
1 - Using the Delay command in an Async method. https://msdn.microsoft.com/en-us/library/hh194873(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-4
2 - Using a dispatcher frame, which can let the dispatcher work while your method waits. http://www.codeproject.com/Articles/152137/DispatcherFrame-Look-in-Depth
Unfortunately I'm not a VB programmer, But the code in c# would be like this.
Async Sample:
public Task displayMessage(object param){
Msg = "How";
await Task.Delay(1000);
Msg = "Are";
await Task.Delay(1000);
Msg = "you";
await Task.Delay(1000);
Msg = "?";
await Task.Delay(1000);
}
DispatcherFrame sample:
public void displayMessage(object param){
Msg = "How";
Wait(1000);
Msg = "Are";
Wait(1000);
Msg = "you";
Wait(1000);
Msg = "?";
Wait(1000);
}
public void Wait(int sleep)
{
var dFrame = new DispatcherFrame();
ThreadPool.QueueUserWorkItem(state => {
Thread.Sleep(sleep);
dFrame.Continue = false;
});
Dispatcher.PushFrame(dFrame);
}

AsyncCallback of BackgroundWorker Webservice reference Function

I am trying to build a new class from where I can call functions with a background worker from a web service in a windows Phone 8.1 silverlight app.
calling page
LoginPage.xaml.vb
Partial Public Class LoginPage
Private sub Logon()
WebServiceHelper.a(WebServiceHelper.Functions.Logon)
LoginFinish()
End Sub
End Class
WebserviceHelper
WebServiceHelper.vb
Public Class WebServiceHelper
Public Shared Sub a(ByVal _Task As Functions)
If _Task = Functions.Logon Then
_Service.BeginLogonWindowsPhone(usr, pass, New AsyncCallback(AddressOf ResultBackGroundTask), result)
End If
End Sub
Public Shared Sub ResultBackGroundTask(ByVal result As Object)
If _Task = Functions.Logon Then
ResultObject = result
End If
End Sub
End Class
The problem is when I call webservice.a() the AsyncCallback ResultBackGroundTask doesn’t fire in time. Instead LoginFinish is called resulting in an error because the resultobject isn’t initialized yet.
I've tried:
Task.Factory.FromAsync(_Service.BeginLogonWindowsPhone, ResultBackGroundTask, usr, pass, Nothing)
But I get an error:
Argument not specified for parameter 'asyncState' of
'Public Function BeginLogonWindowsPhone(userName As String, password As String, callback As System.AsyncCallback, asyncState As Object) As System.IAsyncResult'.
The function I try to call is:
<System.ServiceModel.OperationContractAttribute(AsyncPattern:=true, Action:="http://test.com/LogonWindowsPhone", ReplyAction:="*"), _
System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults:=true)> _
Function BeginLogonWindowsPhone(ByVal userName As String, ByVal password As String, ByVal callback As System.AsyncCallback, ByVal asyncState As Object) As System.IAsyncResult
This function is automatically generated in the webservice reference.
I use the Webservice to connect with the clients database, for security reasons.

Nested class & readonly properties

Outside the class I'd like to be able to access CCTV.Camera.Brightness property as ReadOnly, but methods within the CCTV class should be able to modify the Brightness property. Please can you advise on how to achieve this?
I think I need to add an Interface that exposes some properties and hides others, but I'm not sure of the implementation. [Note the constructor and main sub are obviously contrived for this example and testing].
Public Class CCTV
Public Class Camera
Public Property Name as String
Public Property Brightness as Integer
End Class
Dim cameras as New Dictionary(Of String, Camera)
Public Sub New()
Dim cam As New Camera
cam.Name = "driveway"
cam.Brightness = 5
cameras.Add(cam.Name, cam)
End Sub
Public Sub ChangeBrightness(value as Integer)
cameras("driveway").Brightness = value
End Sub
End Class
Sub main()
Dim MyCCTV = new CCTV
MyCCTV.ChangeBrightness(10)
if MyCCTV("driveway").Brightness = 10 then Console.Write("Brightness is 10")
End Sub
Get getter and the setter of a property can have different accessibility modifiers. In this case you want Brightness to be readable by everybody but only the code you trust should be able to write it. You do so like this:
Public Class Camera
Private _brightness As Integer
Public Property Brightness As Integer
Get
Return _brightness
End Get
Friend Set(value As Integer)
_brightness = Value
End Set
End Property
'' etc...
End Class
Note the added Friend keyword, it limits access to the code in the same project that Camera class is a part of. It can also be Private or Protected if you want to limit access to only code inside the Camera class or its derived classes.
no interface is need in this case.You simply have to create your property as readonly.when you set the property as readonly assume that the value will stored within a private variable and at that point should be better pass it or to a method or to the subnew using overloads methods let me show you an example:
Public Class CCTV
Public Class Camera
Private _Name As String
Public Property Name() As String
Get
Return _Name
End Get
Set(ByVal value As String)
_Name = value
End Set
End Property
Private _Brightness As String
Public ReadOnly Property Brightness() As String
Get
Return _Brightness
End Get
End Property
''' <summary>
''' Defautl sub new method
''' </summary>
''' <remarks></remarks>
Sub New()
End Sub
''' <summary>
''' second overload
''' </summary>
''' <param name="cameraName"></param>
''' <param name="brightness"></param>
''' <remarks></remarks>
Sub New(ByVal cameraName As String, ByVal brightness As Integer)
Me.Name = cameraName
Me._Brightness = brightness
End Sub
''' <summary>
''' Change brigthness
''' </summary>
''' <param name="value"></param>
''' <remarks></remarks>
Public Sub setUpCameraBrightness(ByVal value As Integer)
'take care to use private varibale so it will reflcet changes into propetry readonly
Me._Brightness = value
End Sub
End Class
Dim cameras As New Dictionary(Of String, Camera)
Public Sub New()
'two differnet approach
'first overaload:
Dim cam As New Camera()
cam.Name = "yourcamname"
cam.setUpCameraBrightness(10)
cameras.Add(cam.Name, cam)
''second approch declarative value:
Dim cam2 As New Camera("yourcamname", 10)
cameras.Add(cam2.Name, cam2)
End Sub
Public Sub ChangeBrightness(value As Integer)
cameras("driveway").setUpCameraBrightness(100)
End Sub
End Class
Sub main()
Dim MyCCTV = New CCTV
MyCCTV.ChangeBrightness(10)
If MyCCTV("driveway").Brightness = 10 Then Console.Write("Brightness is 10")
End Sub