Skip to content

12.02 Auxiliary C# Classes (XAMARIN)

chempkovsky edited this page Jul 10, 2021 · 24 revisions
  • Before generating the user interface for the very first View, all auxiliary interfaces, enums, helper classes, services, custom user controls must be in place and ready for use. The list of auxiliary files includes "Home", "Page not found", "Access Denied", "Paginator" user controls, global settings service, declaration of some global routed events and routed commands and so on.

  • It’s time to note that the order of generated files is extremely important. For instance, some classes may reference others. It means that referenced files must be generated before referencing files. And this is why CS2WPF Forms project file is used by the Wizards. The information about each generated file (file type, file name, file place and so on) is saved into CS2WPF Forms project file.

  • The second point relates to script types. All scripts are divided into two large sets:

    • The first one consists of the context level scripts. These scripts are used to generate interfaces, classes, services that are used across the Views and application level components.
    • The second set consists of the View level scripts. They are scripts that are used to generate the code for the given view. For instance, Edit form for one View is not applicable for another one because of captions, validations and so on.
  • These two large sets are organized as follows:

    • Scripts with a range of 00000-00999 are context level scripts.
    • Scripts with a range of 01000-99999 are view level scripts
  • To Generate AUXILIARY C# classes

    • Run Visual Studio and Open “XamarinDemo” solution

"CommonInterfacesClassLibrary"-project

  • Step 1
    • Right click "CommonInterfacesClassLibrary"-project node and select "Wpf Form Wizard"-menu
    • Click "Next"-button

picture

  • Step 2
    • Select "Dm02Context"-project
    • Select "LitDbContext"-DbContext
    • Click "Next"-button

picture

  • Step 3
    • Select "==context==" in the combo
    • Click "Next"-button

picture

  • Step 4
    • Click "batch processing"-button

picture

  • Step 5
    • Select "00000-ContextLevelCommonInterfacesBatch.Xamarin.json"-item
    • Click "Start"-button
    • After generation finished make sure that "Error"-panel is empty
    • Close Wizard's dialogs
    • Rebuild "ModelInterfacesClassLibrary"-project

picture

"CommonServicesPrismModule"-project

  • Repeat steps 1-5 for "CommonServicesPrismModule"-project and "00010-ContextLevelCommonServicesModuleBatch.Xamarin.json"

"CommonCustomControlLibrary"-project

  • Repeat steps 1-5 for "CommonCustomControlLibrary"-project and "00020-ContextLevelCustomControlLibraryBatch.Xamarin.json"

"CommonUserControlLibrary"-project

  • Repeat steps 1-5 for "CommonUserControlLibrary"-project and "00030-ContextLevelCommonUserControlLibraryBatch.Xamarin.json"

"CommonServicesPrismModule"-project again

  • Repeat steps 1-5 for "CommonServicesPrismModule"-project and "00040-ContextLevelCommonServicesModuleBatch.Xamarin.json"

"PrismDemoApp"-project

  • Repeat steps 1-5 for "PrismDemoApp"-project and "00050-ContextLevelPrismAppBatch.Xamarin.json"

"PrismDemoApp.Android"-project

  • Repeat steps 1-5 for "PrismDemoApp.Android"-project and "00060-ContextLevelPrismAppBatch.Xamarin.Android.json"

"PrismDemoApp.iOS"-project

  • Repeat steps 1-5 for "PrismDemoApp.iOS"-project and "00060-ContextLevelPrismAppBatch.Xamarin.iOS.json"

"PrismDemoApp.UWP"-project

  • Repeat steps 1-5 for "PrismDemoApp.UWP"-project and "00060-ContextLevelPrismAppBatch.Xamarin.UWP.json"

Setup Prism IMoule for CommonServicesPrismModule

Open the "CommonServicesPrismModuleModule.cs"-file of CommonServicesPrismModule-project and and two lines of code into the body of "RegisterTypes()"-method. Make sure that "RegisterTypes()"-method is as follows

        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            //these two lines are added 
            //////////////////
            CommonInterfacesClassLibrary.AppGlblSettingsSrvc.IAppGlblSettingsService s = new AppGlblSettingsSrvc.AppGlblSettingsService();
            containerRegistry.RegisterInstance<CommonInterfacesClassLibrary.AppGlblSettingsSrvc.IAppGlblSettingsService>(s);
            //////////////////

            containerRegistry.Register<CommonInterfacesClassLibrary.AppGlblLoginSrvc.IAppGlblLoginService, CommonServicesPrismModule.AppGlblLoginSrvc.AppGlblLoginService>();
            containerRegistry.RegisterDialog<CommonServicesPrismModule.UserControls.ColumnSelectorDlgUserControl, CommonServicesPrismModule.ViewModels.ColumnSelectorDlgViewModel>("ColumnSelectorDlg");
            containerRegistry.RegisterDialog<CommonServicesPrismModule.UserControls.MessageDlgUserControl, CommonServicesPrismModule.ViewModels.MessageDlgViewModel>("MessageDlg");
            Prism.Mvvm.ViewModelLocationProvider.Register<CommonServicesPrismModule.Views.AccessDeniedPage, CommonServicesPrismModule.ViewModels.AccessDeniedPageViewModel>();
            containerRegistry.RegisterForNavigation<CommonServicesPrismModule.Views.AccessDeniedPage, CommonServicesPrismModule.ViewModels.AccessDeniedPageViewModel>("AccessDeniedPage");
            Prism.Mvvm.ViewModelLocationProvider.Register<CommonServicesPrismModule.UserControls.AccessDeniedUserControl, CommonServicesPrismModule.ViewModels.AccessDeniedViewModel>();
            containerRegistry.RegisterForRegionNavigation<CommonServicesPrismModule.UserControls.AccessDeniedUserControl, CommonServicesPrismModule.ViewModels.AccessDeniedViewModel>("AccessDeniedUserControl");
            containerRegistry.Register<Xamarin.Forms.ContentView, CommonServicesPrismModule.UserControls.AccessDeniedUserControl>("AccessDeniedUserControl");
            Prism.Mvvm.ViewModelLocationProvider.Register<CommonServicesPrismModule.Views.PageNotFoundPage, CommonServicesPrismModule.ViewModels.PageNotFoundPageViewModel>();
            containerRegistry.RegisterForNavigation<CommonServicesPrismModule.Views.PageNotFoundPage, CommonServicesPrismModule.ViewModels.PageNotFoundPageViewModel>("PageNotFoundPage");
            Prism.Mvvm.ViewModelLocationProvider.Register<CommonServicesPrismModule.UserControls.PageNotFoundUserControl, CommonServicesPrismModule.ViewModels.PageNotFoundViewModel>();
            containerRegistry.RegisterForRegionNavigation<CommonServicesPrismModule.UserControls.PageNotFoundUserControl, CommonServicesPrismModule.ViewModels.PageNotFoundViewModel>("PageNotFoundUserControl");
            containerRegistry.Register<Xamarin.Forms.ContentView, CommonServicesPrismModule.UserControls.PageNotFoundUserControl>("PageNotFoundUserControl");
            Prism.Mvvm.ViewModelLocationProvider.Register<CommonServicesPrismModule.Views.HomePage, CommonServicesPrismModule.ViewModels.HomePageViewModel>();
            containerRegistry.RegisterForNavigation<CommonServicesPrismModule.Views.HomePage, CommonServicesPrismModule.ViewModels.HomePageViewModel>("HomePage");
            Prism.Mvvm.ViewModelLocationProvider.Register<CommonServicesPrismModule.Views.RegisterUserPage, CommonServicesPrismModule.ViewModels.RegisterUserPageViewModel>();
            containerRegistry.RegisterForNavigation<CommonServicesPrismModule.Views.RegisterUserPage, CommonServicesPrismModule.ViewModels.RegisterUserPageViewModel>("RegisterUserPage");
            Prism.Mvvm.ViewModelLocationProvider.Register<CommonServicesPrismModule.Views.LoginUserPage, CommonServicesPrismModule.ViewModels.LoginUserPageViewModel>();
            containerRegistry.RegisterForNavigation<CommonServicesPrismModule.Views.LoginUserPage, CommonServicesPrismModule.ViewModels.LoginUserPageViewModel>("LoginUserPage");
            Prism.Mvvm.ViewModelLocationProvider.Register<CommonServicesPrismModule.Views.LogoutUserPage, CommonServicesPrismModule.ViewModels.LogoutUserPageViewModel>();
            containerRegistry.RegisterForNavigation<CommonServicesPrismModule.Views.LogoutUserPage, CommonServicesPrismModule.ViewModels.LogoutUserPageViewModel>("LogoutUserPage");
            Prism.Mvvm.ViewModelLocationProvider.Register<CommonServicesPrismModule.Views.ChngpswdUserPage, CommonServicesPrismModule.ViewModels.ChngpswdUserPageViewModel>();
            containerRegistry.RegisterForNavigation<CommonServicesPrismModule.Views.ChngpswdUserPage, CommonServicesPrismModule.ViewModels.ChngpswdUserPageViewModel>("ChngpswdUserPage");
        }

Setup App.xaml.cs for PrismDemoApp

Open "App.xaml.cs"-file of PrismDemoApp-project and modify "ConfigureModuleCatalog()" method as follows

using Prism;
using Prism.Ioc;
using Prism.Modularity;
using Prism.Regions.Adapters;
using Xamarin.Forms;
using Xamarin.Essentials.Interfaces;
using Xamarin.Essentials.Implementation;
using PrismDemoApp.Views;
using PrismDemoApp.ViewModels;
using CommonUserControlLibrary.UserControls;
using PrismDemoApp.Classes;
using CommonServicesPrismModule;
using ModelServicesPrismModule;
using FeatureServicesPrismModule;

namespace PrismDemoApp {
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    
    public partial class App
    {
        public App(IPlatformInitializer initializer)
            : base(initializer)
        {
        }

        protected override async void OnInitialized()
        {
            InitializeComponent();
            await NavigationService.NavigateAsync($"/MainFlyoutPage/NavigationPage/HomePage");
        }
        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterRegionServices(configureAdapters: OnconfigureAdapters);
            containerRegistry.RegisterSingleton<IAppInfo, AppInfoImplementation>();
            containerRegistry.RegisterForNavigation<NavigationPage>();
            containerRegistry.RegisterForNavigation<MainFlyoutPage, MainFlyoutPageViewModel>();
        }
        private void OnconfigureAdapters(RegionAdapterMappings obj)
        {
            obj.RegisterMapping<ProxyUserControl, ProxyUserControlRegionAdapter>();
        }
        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
        {
            moduleCatalog.AddModule<CommonServicesPrismModuleModule>();
            //////////////////////////////////////////
            // these two lines are added to the method
            moduleCatalog.AddModule<ModelServicesPrismModuleModule>();
            moduleCatalog.AddModule<FeatureServicesPrismModuleModule>();
            //////////////////////////////////////////
            
        }

    }
}

Set PrismDemoApp.UWP as startup project

picture

Set Configuration Manager

Open "Configuration Manager"

picture

Add "Build" and "Deploy" items as shown below

picture

Run PrismDemoApp.UWP

Rebuild all front end projects and run PrismDemoApp.

picture

Click "Register"-menu item. Click "Home"-navigation menu again.

picture

Setup PrismDemoApp.Android as startup

Run PrismDemoApp.Android

Rebuild all front end projects and run PrismDemoApp.

picture

Setup CommonServicesPrismModule and Dm04WebApp projects for conversation

Click Dm04WebApp root node to get project properties visible. Copy SSL URL into clipboard.

picture

Open "CommonServicesPrismModule/AppGlblSettingsSrvc/AppGlblSettingsService.cs"-file of the CommonServicesPrismModule-project. Modify GetWebApiPrefix() and GetSecurityWebApiPrefix() by resetting URLs.

        ...
        public string GetWebApiPrefix(string ViewName)
        {
            string rslt = "";
            if(!string.IsNullOrEmpty(ViewName))
            {
                rslt = "https://localhost:44358/";
            }
            return rslt;
        }
        public string GetSecurityWebApiPrefix()
        {
            return "https://localhost:44358/";
        }
        ...

Install MS SQL Server anywhere in your network or virtual environment. Get "sa"-password, network name of the SQL server and the port (if necessary). Open Web.config-file of Dm04WebApp-project and modify "DefaultConnection"-settings. Here is example:

  ... 
  <connectionStrings>
    <add name="DefaultConnection" 
        connectionString="Data Source=SVR2016SQL2017;Initial Catalog=AspNetDbWebApplicationXamarinDemoSecurity;Persist Security Info=True;User ID=sa;Password=sa_PASSWORD_HERE" 
        providerName="System.Data.SqlClient" />
  </connectionStrings>
  ... 

Note: You will have different "Data Source"-property in your development invoronment.

For Dm04WebApp set "Always Start when debuging"=true

picture

The front and back ends are ready to register user, login, logout, change password operations.

  • Rebuild CommonServicesPrismModule-project
  • Run Dm04WebApp.UWP (Dm04WebApp will be started automatically)
  • Click "Register User"-menu
  • enter [User name]="testuser@gmail.com"
  • enter [Password]="Qq?1234"
  • enter [Confirm password]="Qq?1234"
  • Click Ok

picture

As a result: Error message will be shown

picture

Stop debuging and copy the second URL "http://localhost:52157/" into "GetWebApiPrefix" and "GetSecurityWebApiPrefix"-methods. The second URL is not "https"-address.

        ...
        public string GetWebApiPrefix(string ViewName)
        {
            string rslt = "";
            if(!string.IsNullOrEmpty(ViewName))
            {
                rslt = "http://localhost:52157/";
            }
            return rslt;
        }
        public string GetSecurityWebApiPrefix()
        {
            return "http://localhost:52157/";
        }
        ...
  • Run Dm04WebApp.UWP (Dm04WebApp will be started automatically)
  • Click "Register User"-menu
  • enter [User name]="testuser@gmail.com"
  • enter [Password]="Qq?1234"
  • enter [Confirm password]="Qq?1234"
  • Click Ok
  • after susccess you will be redirected to the "Home"-page

Check if the user has been registered

With "SQL Management studion" execute thee following SQL-script:

SELECT * FROM [AspNetDbWebApplicationXamarinDemoSecurity].[dbo].[AspNetUsers]

The result is on the picture below

picture

For now Login with PrismDemoApp and "testuser@gmail.com" and password "Qq?1234". After login you will be redirected to the "Home"-page without exceptions. (Nobody knows where the best place to show logined user name. This is why the username is not shown).

Localhost and Android-emulator

It is know, that virtual machines are used for the emulators. So, "Localhost" will not be useful in all cases.

  • Run Dm04WebApp.Android (Dm04WebApp will be started automatically)
  • enter [User name]="androidTest@gmail.com"
  • enter [Password]="Qq?1234"
  • enter [Confirm password]="Qq?1234"
  • Click Ok

picture We expect this result. We should use IP-addresses.

Modify GetWebApiPrefix and GetSecurityWebApiPrefix methods and modify applicationhost.config-file

  • At first, we modified "AppGlblSettingsService.cs"-file of the CommonServicesPrismModule-project
        ...
        public string GetWebApiPrefix(string ViewName)
        {
            string rslt = "";
            if(!string.IsNullOrEmpty(ViewName))
            {
                if (Device.RuntimePlatform == Device.Android)
                {
                
                    rslt = "http://10.0.2.2:52157/";  
                }
                else
                {
                    return "http://localhost:52157/";
                }
            }
            return rslt;
        }
        public string GetSecurityWebApiPrefix()
        {
            if (Device.RuntimePlatform == Device.Android)
            {
                return "http://10.0.2.2:52157/"; // 
            } else
            {
                return "http://localhost:52157/";
            }
        
        }
        ...
  • At second, we added one additional binding to applicationhost.config-file:

picture

                <bindings>
                    <binding protocol="https" bindingInformation="*:44358:localhost" />
                    <binding protocol="http" bindingInformation="*:52157:localhost" />
                    <binding protocol="http" bindingInformation="*:52157:127.0.0.1" />
                </bindings>

After changing bindings

  • Run Dm04WebApp only
  • check if all bindings are active

picture

  • on the picture below it is shown that we have only one binding

picture

  • open the folder
%TEMP%\iisexpress
  • open very last log-file

picture

  • Rebuild Dm04WebApp and start Dm04WebApp again. All is the same.
  • Restart Visual Studio as ADMIN
  • Rebuild and start Dm04WebApp.
  • check if all bindings are active

picture

We just detected the direction of how to set up the development environment. To run Visual Studion as Admin is not a very good idea. Run PowerShell as admin and execute two commands.

netsh http add urlacl url=http://127.0.0.1:52157/ user=everyone
netsh http add urlacl url=http://localhost:52157/ user=everyone

Restart Visual Studion (do not use as Admin). Start Dm04WebApp. Make sure all bindings are active.

picture

Repeat registration with Android App and check the result

  • Run Dm04WebApp.Android (Dm04WebApp will be started automatically)
  • Click "Register User"-menu item
  • enter [User name]="androidTest@gmail.com"
  • enter [Password]="Qq?1234"
  • enter [Confirm password]="Qq?1234"
  • Click Ok
  • here is a result picture

The last possible issue

  • When you start development (i.e. generate application code) and test the result, you may receive the following error:

picture

  • To fix the issue, make sure that
    • "Newtonsoft.Json"-package is identical on the server side and on the client side of the project

picture

  • Do the same for "EntityFramework"-package on the server side

  • Rebuild server side projects. Here is a result:

picture

Clone this wiki locally