<<

Building a mobile enterprise application with .Forms, Docker, MVVM and .NET Core Gill Cleeren @gillcleeren – www.snowball.be

Kliant. Nice to meet you.

Kliant provides hands-on in-depth advanced software development training that is customized/tailored to your specific requirements

Our instructors are experienced developers, LA – Atlanta - London renowned subject matter experts and respected authors Your contact: Eric Swanson – [email protected] Upcoming virtual courses

• Developing cross-platform apps with C# using Xamarin • 2 Day • March 1-2

• Mastering ASP.NET Core 2 MVC • 2 Day • March 26-27

Some seats still available! Agenda

• Overall application structure • The Xamarin application architecture • MVVM • Dependency Injection • Loose-coupled Messaging • Navigation • Service communication • Testing • Backend architecture • .NET Core-based Microservices • Docker The Solution Structure Client apps Backend in Docker host

Xamarin.Forms Microservice 1 mobile app Product catalog

HTML web Microservice 2 MVC app front-end Ordering

Microservice 3 SPA Identity DEMO Looking at the Solution Structure & the Finished Application The Xamarin application architecture MVVM MVVM

• Architectural pattern • Based on data binding and commanding • Popular for testable and maintainable XAML applications What we all did when we were young…

Write code in code-behind… Lots of it.

View

XAML

Code-Behind Data Model Event Handlers Writing testable code however, is becoming the norm. Finally. Courtesy of MVVM.

View

XAML

Code-Behind

Data-binding Change and commands notification View Model

State + Data Model Operations Benefits of MVVM

• Testable • Developers and designers can work independently • A new XAML view can be added on top of the view models without problems • Changes can be made in view model without risking issues with the model Functionalities of the View

View User interface

MyPage.xaml Window, Page or user control Simple MyPage.xaml.cs No business logic Sample View Code

Glue between view and Model Expose state and operations View Model Testable No UI elements Sample View Model Code

public class LoginViewModel : INotifyPropertyChanged { public string UserName { get; set; }

public string Password { get; set; }

public ICommand SignInCommand => new Command(async () => await SignInAsync());

} Functionalities of the Model

Data model - services Model Return data DEMO Looking at the Model in the application Responding to changes in the (view) model

• Handled through INotifyPropertyChanged interface • PropertyChanged raised for changes of view model or model property value changes • (View)Model property changes • Calculated properties • Raise event at the end of a method that makes changes to the property value • Don’t raise PropertyChanged when the value didn’t change • Don’t raise PropertyChanged from the constructor • Don’t raise PropertyChanged in a loop BindableObject

public abstract class ExtendedBindableObject : BindableObject { public void RaisePropertyChanged(Expression> property) { var name = GetMemberInfo(property).Name; OnPropertyChanged(name); }

private MemberInfo GetMemberInfo(Expression expression) { ... } } DEMO Looking at the ViewModels and the Views Commanding

• Action is defined in one place and can be called from multiple places in the UI • Available through ICommand interface • Defines Execute() and CanExecute() • Can create our own or use built-in commands The ICommand Interface

public interface ICommand { event EventHandler CanExecuteChanged; bool CanExecute(object parameter); void Execute(object parameter); } Exposing Operations on the View Model

public class LoginViewModel : ViewModelBase { public ICommand SignInCommand => new Command(async () => await SignInAsync());

public ICommand RegisterCommand => new Command(Register); } Binding Your Commands in the View

Behaviors

• Command property available only on ButtonBase-derived controls • Other controls and interactions only possible through “behaviours” • Use of an attached behaviour • Use of a Xamarin.Forms behaviour EventToCommandBehavior

public class EventToCommandBehavior : BindableBehavior { protected override void OnAttachedTo(View visualElement) { ... }

} Using EventToCommandBehavior

Using TapGestureRecognizer

DEMO Commanding Done Right Who Knows Who?

View View Model Model Linking the View and the View Model

View-First View Model-First View-First (from XAML)

View First (from code)

public LoginView() { InitializeComponent(); BindingContext = new LoginViewModel(); } The View Model Locator

View View 1 Model 1

View View 2 View Model Model 2 Locator

View View n Model n DEMO The ViewModel Locator Dependency Injection Dependency Injection

• Type of inversion of control (IoC) • Another class is responsible for obtaining the required dependency • Results in more loose coupling • Container handles instantiation as well as lifetime of objects • Autofac is commonly used • Many others exist Dependency Injection

ProfileViewModel IContainer OrderService

IOrderService Dependency Injection

public class ProfileViewModel : ViewModelBase {

private IOrderService _orderService;

public ProfileViewModel(IOrderService orderService) { _orderService = orderService; } } Advantages of using Dependency Injection • Better testability through easy way of using mock versions • Higher maintainability by making it easy to add new classes • Central location • Dependencies don’t affect the class that uses them • Classes don’t need to manage their dependencies • It’s handled for them • They add complexity • Not always a good idea for small apps… Container registration

• Happens at application startup

builder.RegisterType().As().SingleInstance(); builder.RegisterType().As(); Resolving dependencies

• If the requested type can’t be found, an exception is thrown • If a type is requested that registered as singleton, we always will get back the same instance • A new instance will only be created once, the first time it’s requested • Otherwise, a new instance will always be returned

NavigationService = ViewModelLocator.Resolve(); DEMO Working with Dependency Injection Loose-coupled Messaging View Model communication

View Model View Model

View Model View Model

View Model View Model

View Model View Model Messaging Center built-in in Xamarin.Forms View View XAML XAML Code- Code- Behind Behind

View Model View Model Data Model State + Operations Data Model State + Operations Message

Publish messages View XAML

Subscribe to Code- Behind messages

View Model Messaging Center (XF)Message State + Operations Messaging Center

• Implements pub-sub model for us already • Built-in in Xamarin.Forms • Multicast supported • Based on strings (not always perfect) DEMO Working with Messages and the Messaging Center Navigation Navigation and MVVM

• Navigation isn’t always easy to include in an MVVM scenario • No tight-coupling can be introduced • Who is responsible for navigation? View Model? View? • How can we pass parameters during navigation?

• Xamarin.Forms comes with INavigation interface • Will be wrapped as it’s too for real-life scenarios Our Own NavigationService

• Must be registered in the Dependency Injection system public interface INavigationService { ViewModelBase PreviousPageViewModel { get; }

Task InitializeAsync();

Task NavigateToAsync() where TViewModel : ViewModelBase;

Task NavigateToAsync(object parameter) where TViewModel : ViewModelBase;

Task RemoveLastFromBackStackAsync();

Task RemoveBackStackAsync(); } DEMO Adding Navigation Service communication Take some REST

• REST: Representational State Transfer • Based on open HTTP standards • Open for all types of applications • Works with Resources • We’ll send requests to access these resources • URI and HTTP method are used for this • Results in HTTP Status code • 200, 404… based on result of request Communicating with a REST API

• Apps will typically use services for making the data request • Are responsible for communication with the actual API • Controllers on API microservices return DTOs • Are transferred to the application • App can use HttpClient class • Works with JSON • Returns HttpResponseMessage after receiving a request • Can then be read and parsed • Json.NET Loading data from the service

public override async Task InitializeAsync(object navigationData) { IsBusy = true; Products = await _productsService.GetCatalogAsync(); Brands = await _productsService.GetCatalogBrandAsync(); Types = await _productsService.GetCatalogTypeAsync(); IsBusy = false; } Using the Data Service public async Task> GetCatalogAsync() { UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint);

builder.Path = "api/v1/catalog/items"; string uri = builder.ToString();

CatalogRoot catalog = await _requestProvider.GetAsync(uri);

if (catalog?.Data != null) { ServicesHelper.FixCatalogItemPictureUri(catalog?.Data);

return catalog?.Data.ToObservableCollection(); } else return new ObservableCollection(); } Using the RequestProvider

public async Task GetAsync(string uri, string token = "") { HttpClient httpClient = CreateHttpClient(token); HttpResponseMessage response = await httpClient.GetAsync(uri);

await HandleResponse(response); string serialized = await response.Content.ReadAsStringAsync();

TResult result = await Task.Run(() => JsonConvert.DeserializeObject(serialized, _serializerSettings));

return result; } Action in the Controller in the Microservice [HttpGet] [Route("[action]")] public async Task Items([FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0) { var totalItems = await _catalogContext.CatalogItems.LongCountAsync();

var itemsOnPage = await _catalogContext.CatalogItems .OrderBy(c => c.Name) .Skip(pageSize * pageIndex) .Take(pageSize) .ToListAsync();

itemsOnPage = ChangeUriPlaceholder(itemsOnPage);

var model = new PaginatedItemsViewModel( pageIndex, pageSize, totalItems, itemsOnPage);

return Ok(model); } DEMO Accessing Remote Data Unit Testing Testing is REALLY needed

• Different devices • Network • Performance • Different resolutions • Different OS versions A unit test is an automated piece of code that invokes a unit of work in the system and then checks a single assumption about the behavior of that unit of work.

From The Art of Unit Testing, Roy Osherove Unit testing

• Block of code that needs to be tested

• Public API IOrderService • Isolated • Fast • Refactor with confidence • Automated MockOrderService OrderService • Independent • Dependency injection will help here Why we need unit tests?

• Find bugs • No fear to break something when making changes • Improve code quality • Code documentation Structure of a unit test

• Arrange • Act • Assert DEMO Unit Testing Backend architecture ASP.NET Core .NET Core

“.NET Core is a general purpose development platform maintained by and the .NET community on GitHub. It is cross-platform, supporting Windows, macOS and Linux, and can be used in device, cloud, and embedded/IoT scenarios.”

source: https://docs.microsoft.com/en-us/dotnet/articles/core ASP.NET Core

“ASP.NET Core is a new open-source and cross-platform framework for building modern cloud based internet connected applications, such as web apps, IoT apps and mobile backends.” source: https://docs.microsoft.com/en-us/aspnet/core ASP.NET Core

• Built on top of .NET Core • Lightweight • Cross-platform • Windows, Mac & Linux

 Easy in combination with Docker and Microservices What does ASP.NET Core bring us then?

• Unification between MVC and Web API • Dependency Injection • Modular HTTP request pipeline • Based on NuGet • Cloud-ready • IIS or self-host • Open source • Community focus • Cross-platform • New tooling • Better integration of client-side frameworks • Command-line support Containerized Microservices Monoliths

• Client-server often results in tiered applications • Specific technology used per tier • Known as monolithic applications • Often have tight coupling between components in each tier • Components can’t be scaled easily • Testing individual components might also be hard Monoliths

• Not being able to scale can be issue for cloud readiness • All layers typically are required • Scaling is cloning the entire application onto multiple machines Monolithic applications Enter microservices

• Microservices are easier for deployment and development • Better agility • Better combination with cloud • App will be decomposed into several components • Components together deliver app functionality • Microservice = small app, independent concern • Have contracts to communicate with other services • Typical microservices • Shopping cart • Payment system • Inventory system Enter microservices

• Can scale out independently • If an area requires more processing power, can be scaled out separately • Other parts can remain the same • Scale-out can be instantaneous • Web front-end for handling more incoming traffic Enter microservices

• Microservices manage their own data • Locally on the server on which they run • Avoid network overhead • Faster for processing • Even eliminate need for caching • Support for independent updates • Faster evolution • Rolling updates, onto subset of instances of single service support rollback Benefits of using microservices • Small • Evolve easily • Scale-out independently • Isolate issues to the faulty microservice • Can use latest and greatest • Not constrained to using older technologies Disadvantages of microservices • Partitioning a real application is hard • Complex • Intercommunication between services • Eventual consistency • Atomic transactions often not supported • Deployment (initial) might be harder • Direct client-to-microservice communication might not be a good idea DEMO Looking at the Microservices “Containerization is an approach to software development in which an application and its versioned set of dependencies, plus its environment configuration abstracted as deployment manifest files, are packaged together as a container image, tested as a unit, and deployed to a host operating system” Adding containers to the mix • Container is isolated, resource controlled and portable operating environment • Applications in containers run without touching resources of host or other containers • Acts like a VM or physical machine • Work great in combination with microservices • Docker is most commonly used approach here What’s a container really?

• Container runs an operating system • Contains file system • Can be accessed over the network like a real machine/VM • Contain the application (and dependencies) • In general, require less resources to run than regular VMs • Allow for easy and fast scale-up by adding new containers Adding containers to the mix Using Docker to host the microservices

• Each container hosts a separate Microservice 1 part of the application Product catalog • Single area of functionality • Each microservice has its own database • Allows for full decoupling Microservice 2 • Consistency is eventual Ordering • Can be improved using application events • Service bus

Microservice 3 Identity DEMO Containerization Summary

• MVVM is the go-to standard for building enterprise-level Xamarin.Forms apps • .NET Core is a good choice for building microservices • Docker helps with deployment of microservices Thanks!

Building a mobile enterprise application with Xamarin.Forms, Docker, MVVM and .NET Core Gill Cleeren @gillcleeren – www.snowball.be