A team from Microsoft, a Xamarin-expert MVP, and our colleagues from Captio met up to migrate the original Captio app developed in Xamarin Classic to the new Xamarin.Forms. This joint team also created a new back-end architecture in Azure to avoid some system downtimes that the application used to experience—especially at the end of the month when usage peaks. In addition, the team was able to incorporate an innovative feature into the final product by using Azure Notification Hubs.

Core team:

The objective of this collaboration, which was supported by one of our MVPs, was essential to change the whole application to Xamarin.Forms by optimizing the architecture and coaching the whole developer team about Xamarin best practices. We can say that after one week of a hackfest, and some extra help from our MVP, the goal was achieved. Now, all the developers at Captio are able to work with the same technology on the front-end layer, and they can now customize the appearance of the application for some of their clients, depending on the customer’s needs, and therefore improving usability. They have also reduced the total amount of code, equalized the appearance in all platforms, and reduced the complexity of their daily work (by deleting useless patterns and using Model-View-ViewModel by default). Regarding the back end, some functionality has been migrated to a worker role, and push notifications have been added to the app.

Key technologies:

  • Xamarin.Forms
  • Push notification / Notification Hubs
  • OpenCV
  • Service Bus
  • Worker roles

Customer profile

Captio is a 5-year-old company headquartered in Spain that developed an application that enables companies and employees to have better control of their travel expenses. The Captio app integrates the expense management process into a single, paperless workflow, eliminating the need for manual tasks while helping to prevent fraud. It can detect duplicate expenses, verify movements of business credit cards, and apply customized business rules for each company. Captio also wants to use machine learning to predict uncommon cases in daily usage situations.

The solution falls under the financial vertical market, but Captio’s customers are from many other verticals such as banking, insurance, healthcare, telecommunications, engineering, food and beverage, and more. We started working with Captio some years ago when it was one of our most successful startups inside our BizSpark Plus program in Spain, and we are still continuously working closely with their team through our ISV program. We can proudly say that every time we mention a success story in BizSpark, Captio comes up. It is, without a doubt, a leading application in the digital transformation field—not only in Spain but also in South America.

Problem statement

Captio built its first app version with Phone Gap five years ago, but was not very happy with the results. Its capabilities were available on other devices in almost every case, and some of them were not as good as native. Moreover, performance was not as good as the Captio team expected it to be. That is why, later, they decided to develop the application again.

This time they created three native applications—with the help of some partners—for the three most-used platforms: Android, iPhone and Windows Phone. With this approach, performance and capabilities met their expectations, but it resulted in the maintenance of the three apps independently, which increased their costs and development efforts.

It was only a matter of time until the CEO heard about Xamarin and its biggest advantage: They can share the logic layer code among their applications, saving maintenance costs while the application remains native. They tried it and the results were good, so they started rebuilding the application on Classic Xamarin.

On the other hand, even though the back end of Captio was hosted in Azure, they couldn’t auto-scale because they had a monolithic architecture that was mainly constructed by virtual machines, and they experienced downtimes, especially at month’s end when usage peaks.

Solutions, steps, and delivery

Our proposal

  • Change their Xamarin Classic app to Xamarin.Forms.
  • Add some functionality to improve the UX. For example:
    • No need to use the lateral menu if users only want to take a photo; the button has been moved to the main screen.
    • The picture will automatically be cropped (improved image - capture process).
    • Users will be able to select a picture from their gallery.
  • Migrate some functionality from Azure IaaS to PaaS (migrating some heavy process to a service that can auto-scale).
  • Adding Azure Redis Cache in the back end and in the administration web.


  • Reduced the amount of code, so it is easier to maintain and enhances developer’s productivity.
  • New look and feel with a better user experience, simplifying the users’ processes.
  • Equalized the appearance in all platforms, and increased efficiency on UI testing with Xamarin Test Cloud.
  • Reduced the complexity (deleting useless patterns and using MVVM by default), which lowers the possibility of introducing bugs.
  • Easier to customize the appearance of the application for some customers, depending on their client’s needs.
  • Improved image-capture process, automating some manual steps like image cropping.
  • Migrated OCR reading into a worker role, isolating it and improving its scalability.
  • Added push notifications to the app to get real-time information about the state of the user’s expenses.

From Xamarin Classic to Xamarin.Forms

As a cross-platform UI API, Xamarin.Forms enables developers to create and share user interfaces across iOS, Android, and Windows Phone. At the same time, they have the option to use native controls of each mobile platform while creating the user interface. Thus, it becomes easier for them to customize the user interface look and feel for individual mobile platforms.

Xamarin Classic to Xamarin Forms

Equalized appearance in all platforms:

Eq. Appearance

Understanding the utility of the app and its data flow

The Captio app enables companies and their employees to have better control of their expenses and the discovery of new savings opportunities. It automatically extracts the data from the receipts and invoices that users capture with their smartphone, so they’ll never have to type expenses manually again. Captio integrates the expense management process into a single, paperless workflow, eliminating the need for manual tasks and helping to prevent fraud.

Ticket reading

Users can easily generate reports with their smartphones and see charts and graphs to understand more about their expenses. The app classifies expenses automatically to make management of travel expenses easier by applying categories and offering customizable fields. It enables greater efficiency by automatizing several tasks such as supervision, bank card reconciliation, and managing forward payments, allows managers to analyze their team’s expenses from different perspectives, and can automatically check that each expense complies with company policy. Captio is easy to use: simple and hassle-free for the people traveling and those who supervise them.

App Workflow

The dataflow starts when the user takes a picture of the receipt with his or her mobile phone:

Taking Picture

One of the updates introduced in the Azure infrastructure is isolating the process of uploading the picture: Now it’s saved as a blob object into Azure Storage.

Data WorkFlow

Once the ticket has been uploaded as a blob object, a worker role is notified through an Azure Queue. The message of the queue includes the blob object ID.

Once the worker role receives the message, it accesses the blob and runs an OCR process over the image to extract the data of the ticket. Once the worker role does the OCR reading, it stores the data extracted in Azure SQL Database.

OCR Reading

Once the image has been read, data is automatically updated. Now, the expense category and the information about the ticket can be modified.

New and improved version

In the previous version, the first screen the user sees when opening the application is a menu with no further instructions or usage guidance. In addition, the first time the app is opened, it must load some features and synchronize the data, which requires time, delaying the user experience.


The first time the newer app is opened, while it loads data and synchronizes the user information, an added progress screen allows the progression of the procedure to be visualized, with sometimes-amusing text such as “Cleaning the objective of the camera” or “Loading the film roll.”

Wizard / usage guide

In the new version, a usage guide of three images explains concisely how to use the application.

User guide

Just use it!

Use it!

After that, the first screen the user sees is a simple design: just a button to take an expense picture.

First screen

Custom fields

Custom fields can be added to some categories. For instance, in the demo, when the expense is categorized as “Restaurant,” “Number of diners” has been added as a new field. This new feature allows companies to customize the data required for the different categories according to their compliance policies.

Custom fields


An automatic trimming of the photo has been added. The edge of the ticket is detected and the photo is cropped so that only the important part of the picture is saved. This change improves the image capturing process and speeds it up (user interaction is no longer required), while optimizing the Azure Storage needs because the image size will be smaller.


In the app’s previous version, the use of the camera was different for each platform. They had a different implementation to access the Android APIs and iPhone APIs camera.

The current implementation uses the Media Plugin. This is a simple cross-platform plugin to take photos and video or pick them from a gallery of shared code. We easily developed the image-cropping functionality because the new Media Plugin is really easy to use.


Once the picture is taken, it is uploaded to a Blob storage. The OCR reading is made by a worker role. The data extracted from the OCR reading is saved in a SQL Database.


We also added Redis Cache. The app back end uses Redis to maintain user state information enabling a seamless autoscaling of the back-end solution, and is also used for caching the most-used values from the database to increase the speed of the queries. This architecture benefits the app users by having a faster app enhancing the API queries performance, and ensures high availability of the service by adapting the number of back-end instances dynamically depending on the actual users’ pressure.


Original architecture:

Original Architecture

New distributed architecture:

new Architecture

Testing and structural improvements

  • We have drastically improved code coverage and the quality of unit testing.
    • The unified API allowed better and easier functionality testing: Since the codebase shares much more code than before, tests must be written only once.
    • Furthermore, other factors like the MVVM pattern enforce a separation of the XAML UI (the View) from the underlying data (the Model) and the UI logic. This pattern makes the testing easier as well.
    • We used the Xamarin.UITests testing framework that can be used in Xamarin.iOS and Xamarin.Android; it is an automated UI acceptance testing framework.
    • Xamarin also provides awesome UI testing with the Xamarin.TestCloud service, which is a cloud-based solution that provides tools that enable automated UI acceptance testing of mobile applications across hundreds of different devices.
  • Increasing the amount of shared code:

    During the hackfest, most of the developers learned a new skill - XAML + C# - that complements their previous knowledge and experience in iOS/XCode or Android/Java. Because they are now sharing the same codebase, they can also share the backlog, increasing the team agility and capability to develop for all the platforms, while before they were siloed by technology.

    The Xamarin Classic application had about 10,000 lines of code written in different languages for each specific platform (Java and XML, XCode, or XAML), mostly written in the UI layer. Now, in the new version using Xamarin.Forms, we achieved a big reduction in the UI codebase, from 10,000 lines to about 4,000 lines of shared code plus about 1,500 lines written in native technologies. Sharing the code improves the code maintenance and testability, and provides a uniform user experience across platforms.

  • Xamarin.Forms has strong support for advanced development tooling and process control such as unit testing, mocking, dependency injection, and inversion of control.

General lessons

  • Android development with Java is slower. Maybe not the development itself, but the process of deploying to the emulator or to the real test device is slower than deploying using Android Studio, especially to real devices.

  • When required, developers can use native UI controls and renders if the out-of-the-box functionality for a given platform does not feel right. However, in this specific scenario, Captio did not have a lot of animations and didn’t require native UI controls behavior nor complex screens.

  • Although many people are concerned about Xamarin.Forms performance, the fact is that in our tests, it was very close to the native platforms and even faster in some scenarios. In fact, in some tests, our application in Xamarin.Forms is much faster than the same action in Xamarin Classic. We tested specifically the scrollview in the ticket’s view and a vertical “stack” layout view to the scrollview in emulator (KitKat 4.4 XXHDPI Phone) and device (LG G3, model: LG-D855, SO: KitKat 4.4.2). We detected with these tests that the average of 10 tests in Xamarin.Forms is approximately three time faster than in Xamarin Classic.

Additional resources