Adding a sign in page

In order to add sign in capabilities to our app, we need to create a new Page and a new ViewModel. The ViewModel will be pretty straightforward, containing just a single command that handles signing in to Facebook via the IAuthService, passing the received Facebook token to the Azure backend service through the ITripLogDataService, and then storing the Azure access token in local settings.

Note

There are a couple of ways to tap into the local storage platform-specific APIs to store settings. One way is to roll your own, similar to how we did the location service: creating a core interface that is implemented uniquely per platform. Another alternative is to leverage a plugin or other third party component that has been published. In this section, we will use a plugin called Settings Plugin for Xamarin and Windows, available on NuGet as Xam.Plugins.Settings by James Montemagno. There are also several other types of plugins made available by members of the Xamarin community at https://github.com/xamarin/plugins.

  1. Add the Xam.Plugins.Settings NuGet package to the core library and each of the platform-specific projects, and update the Settings helper class in the core library according to the package's readme file to include a string setting named TripLogApiAuthToken.
  2. Create a new class that inherits from BaseViewModel named SignInViewModel in the ViewModels folder in the core library:
    public class SignInViewModel : BaseViewModel
    { }
  3. Update the SignInViewModel with a constructor that takes in an INavService, IAuthService, and ITripLogDataService parameter:
    public class SignInViewModel : BaseViewModel
    {
        readonly IAuthService _authService;
        readonly ITripLogDataService _tripLogService;
    
        public SignInViewModel (INavService navService,
    IAuthService authService,
    ITripLogDataService tripLogService)
            :base(navService)
        {
            _authService = authService;
            _tripLogService = tripLogService;
        }
    }
  4. Next, add a new ICommand property named SignInCommand to the SignInViewModel along with its execute Action:
    public class SignInViewModel : BaseViewModel
    {
        // ...
    
        ICommand _signInCommand;
        public ICommand SignInCommand {
            get {
                return _signInCommand
    ?? (_signInCommand = new Command (async () => await ExecuteSignInCommand ()));
            }
        }
    
        async Task ExecuteSignInCommand()
        {
            // TODO: Update with your Facebook Client Id
            await _authService.SignInAsync (
    "YOUR_FACEBOOK_CLIENTID",
                new Uri ("https://m.facebook.com/dialog/oauth"),
                new Uri ("https://triplog.azurewebsites.net/.auth/login/facebook/callback"),
                tokenCallback: async t => {
    
                    // Use Facebook token to get Azure auth token
                    var response = await _tripLogService.GetAuthTokenAsync ("facebook", t);
    
                    // Save auth token in local settings
                    Helpers.Settings.TripLogApiAuthToken = response.AuthenticationToken;
    
                    // Navigate to Main
                    await NavService.NavigateTo<MainViewModel> ();
                    await NavService.RemoveLastView ();
                },
                errorCallback: e => {
                    // TODO: Handle invalid authentication here
                });
        }
    }
  5. Override the BaseViewModel Init method to clear the navigation back stack anytime the SignInViewModel is loaded:
    public override async Task Init (){await NavService.ClearBackStack ();}
  6. Update the TripLogCoreModule to add SignInViewModel to the IoC container:
    public class TripLogCoreModule : NinjectModule
    {
        public override void Load ()
        {
            // ViewModels
            Bind<SignInViewModel> ().ToSelf();
            Bind<MainViewModel> ().ToSelf ();
            Bind<DetailViewModel> ().ToSelf ();
            Bind<NewEntryViewModel> ().ToSelf ();
    
            // ...
        }
    }
  7. Update the TripLogCoreModule to account for the updated TripLogApiDataService constructor and pass in the auth token stored in local settings:
    var tripLogService = new TripLogApiDataService (
    new Uri("https://<your-service-name>.azurewebsites.net"),
    Helpers.Settings.TripLogApiAuthToken);
    

Next, we need to create the actual sign in page, which we will use with the SignInViewModel as its data context.

  1. Create a new page in the Views folder in the core library named SignInPage:
    public class SignInPage : ContentPage
    { }
  2. Update the constructor of the SignInPage to add a button that is bound to SignInViewModel's SignInCommand:
    public class SignInPage : ContentPage
    {
        public SignInPage ()
        {
            Padding = 20;
    
            var facebookButton = new Button {
                BackgroundColor = Color.FromHex("#455c9f"),
                TextColor = Color.White,
                Text = "Sign in with Facebook"
            };
            facebookButton.SetBinding (Button.CommandProperty, "SignInCommand");
    
            var mainLayout = new StackLayout {
                VerticalOptions = LayoutOptions.Center,
                Children = { facebookButton }
            };
    
            Content = mainLayout;
        }
    }
  3. Next, register the SignInPage and SignInViewModel mapping in the navigation service in the TripLogNavModule:
    public class TripLogNavModule : NinjectModule
    {
        // ...
        public override void Load ()
        {
            var navService = new XamarinFormsNavService ();
            navService.XamarinFormsNav = _xfNav;
    
            // Register view mappings
            navService.RegisterViewMapping (typeof(SignInViewModel), typeof(SignInPage));
            navService.RegisterViewMapping (typeof(MainViewModel), typeof(MainPage));
            navService.RegisterViewMapping (typeof(DetailViewModel), typeof(DetailPage));
            navService.RegisterViewMapping (typeof(NewEntryViewModel), typeof(NewEntryPage));
    
            Bind<INavService> ().ToMethod (x => navService)
                       .InSingletonScope ();
        }
    }

Finally, we need to make two minor adjustments to the app so that users will go directly to the SignInPage if an auth token does not exist in local settings.

  1. First, add a public bool property to the App class that indicates if an auth token is present by checking the Settings helper class:
    public bool IsSignedIn {
        get {
          return
             !string.IsNullOrWhiteSpace (Helpers.Settings.TripLogApiAuthToken);
        }
    }
  2. Next, update the Init method of the MainViewModel to forward the user to the SignInViewModel if the IsSignedIn property is false:
    public override async Task Init ()
    {
        if (!((App)Application.Current).IsSignedIn)
            await NavService.NavigateTo<SignInViewModel> ();
        else
            LoadEntries ();
    }

Now, when the app is launched for the first time and an auth token is not present in the local settings, you will see the SignInPage. Clicking the sign in button will launch the Xamarin.Auth dialog prompting for Facebook credentials and permission to grant access to the TripLog app, as shown in the following screenshots. Upon successfully authenticating with Facebook, you should be automatically brought to the MainPage and the list of the Entry objects will be loaded from the API.

Adding a sign in page
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.77.208