Building a mobile enterprise application with Xamarin ... · application with Xamarin.Forms,...

Post on 18-Jul-2018

255 views 4 download

transcript

Building a mobile enterprise application with Xamarin.Forms,

Docker, MVVM and .NET CoreGill Cleeren

@gillcleeren – www.snowball.be

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

Our instructors are experienced developers, renowned subject matter experts and respected authors

Your contact: Eric Swanson – eswanson@kliant.com

Kliant. Nice to meet you.

LA – Atlanta - London

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

Backend in Docker hostClient apps

Xamarin.Formsmobile app

HTML web front-end

SPA

Microservice 1Product catalog

Microservice 2Ordering

Microservice 3Identity

MVC app

DEMOLooking 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.

Data Model

View

XAML

Code-BehindEvent Handlers

Writing testable code however, is becoming the norm. Finally. Courtesy of MVVM.

Data Model

View

XAML

Code-Behind

View Model

State + Operations

Change notification

Data-binding and commands

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

User interface

Window, Page or user control

Simple

No business logic

Functionalities of the View

View

MyPage.xaml

MyPage.xaml.cs

Sample View Code

<Entry Text="{Binding UserName.Value, Mode=TwoWay}"> </Entry>

<LabelText="{Binding UserName.Errors,Converter={StaticResource FirstValidationErrorConverter}" />

<ListViewIsVisible="{Binding Campaigns.Count, Converter={StaticResource

CountToBoolConverter}}"ItemsSource="{Binding Campaigns}"

Glue between view and Model

Expose state and operations

Testable

No UI elements

Functionalities of the View Model

View Model

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());

}

ModelData model - services

Return data

Functionalities of the Model

DEMOLooking 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<T>(Expression<Func<T>> property){

var name = GetMemberInfo(property).Name;OnPropertyChanged(name);

}

private MemberInfo GetMemberInfo(Expression expression){

...}

}

DEMOLooking 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 ICommandinterface

• 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

<ToolbarItem

Command="{Binding SettingsCommand}"

Text="Settings">

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.Formsbehaviour

public class EventToCommandBehavior : BindableBehavior<View>{

protected override void OnAttachedTo(View visualElement){ ... }

}

EventToCommandBehavior

Using EventToCommandBehavior

<ListViewItemsSource="{Binding Orders}"><ListView.Behaviors>

<behaviors:EventToCommandBehaviorEventName="ItemTapped"Command="{Binding OrderDetailCommand}"EventArgsConverter="{StaticResource ItemTappedEventArgsConverter}" />

</ListView.Behaviors></ListView>

Using TapGestureRecognizer

<StackLayout ><Label Text="SETTINGS"/><StackLayout.GestureRecognizers><TapGestureRecognizer

Command="{Binding SettingsCommand}"NumberOfTapsRequired="1" />

</StackLayout.GestureRecognizers></StackLayout>

DEMOCommanding Done Right

Who Knows Who?

View ModelView Model

View Model-FirstView-First

Linking the View and the View Model

View-First (from XAML)

<ContentPage><ContentPage.BindingContext>

<local:LoginViewModel/></ContentPage.BindingContext>

</ContentPage>

View First (from code)

public LoginView(){

InitializeComponent();BindingContext = new LoginViewModel();

}

The View Model Locator

ViewModelLocator

View Model 1

View Model 2

View Model n

View 1

View 2

View n

DEMOThe 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

IContainerProfileViewModel 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<NavigationService>().As<INavigationService>().SingleInstance();builder.RegisterType<DialogService>().As<IDialogService>();

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<INavigationService>();

DEMOWorking 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

Data Model

View

XAML

Code-Behind

Data Model

View

XAML

Code-Behind

Message

View Model

State + OperationsView Model

State + Operations

View

XAML

Code-Behind

MessageMessaging Center

(XF)

View Model

State + Operations

Publish messages

Subscribe to messages

Messaging Center

• Implements pub-sub model for us already

• Built-in in Xamarin.Forms

• Multicast supported

• Based on strings (not always perfect)

DEMOWorking 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

basic 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<TViewModel>() where TViewModel : ViewModelBase;

Task NavigateToAsync<TViewModel>(object parameter) where TViewModel : ViewModelBase;

Task RemoveLastFromBackStackAsync();

Task RemoveBackStackAsync();}

DEMOAdding 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 Servicepublic async Task<ObservableCollection<CatalogItem>> GetCatalogAsync(){UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint);

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

CatalogRoot catalog = await _requestProvider.GetAsync<CatalogRoot>(uri);

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

return catalog?.Data.ToObservableCollection();}elsereturn new ObservableCollection<CatalogItem>();

}

Using the RequestProvider

public async Task<TResult> GetAsync<TResult>(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<TResult>(serialized, _serializerSettings));

return result;}

Action in the Controller in the Microservice[HttpGet][Route("[action]")]public async Task<IActionResult> Items([FromQuery]int pageSize = 10, [FromQuery]intpageIndex = 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<CatalogItem>(pageIndex, pageSize, totalItems, itemsOnPage);

return Ok(model);}

DEMOAccessing 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 behaviorof that unit of work.From The Art of Unit Testing, Roy Osherove

Unit testing

• Block of code that needs to be tested

• Public API

• Isolated

• Fast

• Refactor with confidence

• Automated

• Independent• Dependency injection will help here

IOrderService

OrderServiceMockOrderService

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

DEMOUnit Testing

Backend architecture

ASP.NET Core

.NET Core

“.NET Core is a general purpose development platform maintained by Microsoft 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

DEMOLooking 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 part of the application• Single area of functionality

• Each microservice has its own database• Allows for full decoupling

• Consistency is eventual

• Can be improved using application events• Service bus

Microservice 1Product catalog

Microservice 2Ordering

Microservice 3Identity

DEMOContainerization

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 CoreGill Cleeren

@gillcleeren – www.snowball.be