Silverlight Navigation and Logon Forms

The asynchronous nature of SL makes certain style of programming difficult.

Let’s say some one navigated to your Silverlight page and you wish to present a logon form if they are not logged in.

You might try this on the OnNavigatedTo event handler

  If WebContext.Current.User.IsAuthenticated Then
      New LoginUI.LoginRegistrationWindow.Show()
  End If

However, this turns out to be wrong because the WebContext.Current.Authentication.IsBusy, if “Keep me logged in” was checked, then the login form shouldn’t be shown.

With a little help from David Poll’s article on NavigationService.Refresh(), the following works reasonably well.

Public Class SecuredPage
    Inherits Page

    Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs)
        MyBase.OnNavigatedTo(e)
        AddHandler WebContext.Current.Authentication.LoggedIn, AddressOf Authentication_LoggedIn
        AddHandler WebContext.Current.Authentication.LoggedOut, AddressOf Authentication_LoggedOut
        AddHandler CType(App.Current, App).UserLoaded, AddressOf Authentication_UserLoaded
    End Sub

    Protected Overrides Sub OnNavigatedFrom(ByVal e As System.Windows.Navigation.NavigationEventArgs)
        MyBase.OnNavigatedFrom(e)
        RemoveHandler WebContext.Current.Authentication.LoggedIn, AddressOf Authentication_LoggedIn
        RemoveHandler WebContext.Current.Authentication.LoggedOut, AddressOf Authentication_LoggedOut
        RemoveHandler CType(App.Current, App).UserLoaded, AddressOf Authentication_UserLoaded
    End Sub

    Protected Sub CheckPermissionUI()

        If WebContext.Current.Authentication.IsBusy Then Exit Sub

        If Not WebContext.Current.User.IsAuthenticated Then
            Dim loginWindow As New LoginUI.LoginRegistrationWindow()
            loginWindow.Show()
            Exit Sub
        End If

        Dim roleRequired As String = ""
        If Not IsAuthorized(roleRequired) Then
            ErrorWindow.CreateNew(String.Format("Sorry. To access this, you have to be one of the {0}", roleRequired))
        End If

    End Sub

    ''' <summary>
    ''' If user is not authorized, check the RoleRequired parameter for the role required.
    ''' </summary>
    ''' Output. Use this for displaying helpful error messages.
    ''' True if user is authorized
    '''
    Protected Overridable Function IsAuthorized(ByRef RoleRequired As String) As Boolean
        RoleRequired = "Administrators"
        Return WebContext.Current.User.IsInRole(RoleRequired)
    End Function

    Private Sub Authentication_UserLoaded( _
        ByVal sender As Object, _
        ByVal operation As ServiceModel.DomainServices.Client.ApplicationServices.LoadUserOperation)

        CheckPermissionUI()

    End Sub

    Private Sub Authentication_LoggedIn(ByVal sender As Object, ByVal e As System.ServiceModel.DomainServices.Client.ApplicationServices.AuthenticationEventArgs)
        NavigationService.Refresh()
    End Sub

    Private Sub Authentication_LoggedOut(ByVal sender As Object, ByVal e As System.ServiceModel.DomainServices.Client.ApplicationServices.AuthenticationEventArgs)

        ' TODO: either navigate to a logout page
        ' NavigationService.Navigate(New Uri("Logged Out.xaml", UriKind.Relative))

        ' Or disable controls on the form

    End Sub

End Class

You’ll also need to add the following to your App.xaml.vb

Public Event UserLoaded(ByVal sender As Object, ByVal operation As LoadUserOperation)
Private Sub Application_UserLoaded(ByVal operation As LoadUserOperation)
    RaiseEvent UserLoaded(Me, operation)
End Sub

I still couldn’t get NavigationService.Navigate to work. Any code samples you can share?


About this entry