Save Big on Cyber Monday! Up to 40% Off
ends in   {{days}}
Days
{{timeFormat.hours}}
:
{{timeFormat.minutes}}
:
{{timeFormat.seconds}}

How to Connect Your .NET MAUI Application to QuickBooks Online

Integrating QuickBooks Online (QBO) into your .NET MAUI application enables easy access to financial data, facilitating efficient management of accounting tasks within your cross-platform app. This guide provides a step-by-step approach to establish a secure connection between your .NET MAUI application and QBO using dotConnect for QuickBooks Online.

Why dotConnect for QuickBooks Online?

dotConnect for QuickBooks Online is a robust ADO.NET provider that facilitates direct access to QBO data through standard ADO.NET or Entity Framework Core interfaces. It simplifies data integration by eliminating the need to understand the complexities of the QBO API, offering:

  • Easy integration: Connect to QBO using familiar ADO.NET classes.
  • Entity Framework Core support: Make full use of LINQ queries and ORM capabilities.
  • Secure authentication: Utilize OAuth 2.0 for secure data access.
  • Cross-platform compatibility: Ideal for .NET MAUI applications targeting multiple platforms.

Prerequisites

What you will need for this tutorial:

  • Visual Studio: Our IDE of choice. If you do not have it on your machine, go to the official website to download and install it. We will be using the Community version, so you can get it as well.
  • dotConnect for QuickBooks Online: A feature-rich ADO.NET provider with EF Core, Dapper, and NHibernate support.
  • QuickBooks Online Account: An active QBO account to access your financial data.

Download and activate dotConnect for QuickBooks Online

30-day free trial

Download and install dotConnect for QuickBooks Online directly on your machine, or install the Devart.Data.QuickBooks NuGet package.

No license key is required, and you can start exploring the product immediately.

Full version

After purchasing the full version, go to your profile's Licenses page. Choose your product and click Details. Here, you'll find the license details and the Activation Key.

To activate a connection in your application, add the License Key to your connection string.

License details and the Activation Key

Set up a QuickBooks workspace and create an app

Go to Intuit Developer, log in to your account, and create a new workspace if you don't have one.

Workspace for a new project


Next, create a new app in your workspace.

Apps in the test workspace


Enter the name of your app.

Details about your new app


Once your app is ready, you will be able to get the credentials required for the connection.

Your app is ready for testing

Get QuickBooks credentials

Now you can proceed to your OAuth 2.0 Playground. Select your workspace and app.

Get authorization code


Next, you will see your Client ID and Client Secret. Click Get authorization code.

OAuth keys


You will be prompted to approve the connection to your application. To do that, click Connect.

Connect to the app


Next, click Get tokens.

Get OAuth 2.0 token from auth code


And finally, the last thing you will need to get connected is the refresh token.

Refresh access token

For more detailed guidance, we suggest you visit Intuit's official Get started documentation page.

Create a .NET project

  1. Open your IDE. We will use Visual Studio. Select Create a new MAUI project.
  2. Name your project; for example, QBOMAUI.
  3. In Solution Explorer, right-click the project and select Manage NuGet Packages.
  4. Search for and install the following packages: Devart.Data.QuickBooks

Or run the following command in the terminal:

dotnet add package Devart.Data.QuickBooks
                    

Verify data source objects using Data Explorer

To connect to QuickBooks using the built-in Data Explorer, right-click Data connections and select Add connection.

Add connection

Select QuickBooks Online as the data source, select Web Login to get credentials, and click Test Connection.

Test connection

If the test connection is successful, click OK.

Once connected, you can browse tables, execute queries, and manage data directly in Data Explorer.

Account table

Create a connection

After taking the previous steps, you will have everything you need to establish a connection. Here is the sample code that will help you connect to QuickBooks Online. Complete it with the following credentials: Client Id, Company Id, Client Secret, Refresh Token, and License Key. Additionally, set Sandbox to true if you are using the sandbox application type.

Add a configuration file or class to store your credentials:

For simplicity, you can add a static class to store these credentials.

public static class QuickBooksConfig {
  public static string ClientId = "YOUR_CLIENT_ID";
  public static string ClientSecret = "YOUR_CLIENT_SECRET";
  public static string RefreshToken = "YOUR_REFRESH_TOKEN";
  public static string RealmId = "YOUR_REALM_ID";
  public static string LicenseKey = "**********";
}
                    

We are going to use our project to illustrate the READ, INSERT, and DELETE operations.

Read QuickBooks data

The following example retrieves and displays customer data from QuickBooks Online.

Define the data model

First, define a model class to represent the data you want to display. For example, let's create a Customer class:

public class Customer {
  public string Id {
    get;
    set;
  }
  public string DisplayName {
    get;
    set;
  }
  public string PrimaryPhone_FreeFormNumber {
    get;
    set;
  }
  public string PrimaryEmailAddr_Address {
    get;
    set;
  }
  public string BillAddr_City {
    get;
    set;
  }
  public string Balance {
    get;
    set;
  }
}
                    

Add a new class for QuickBooks data access

Create a new class named QuickBooksService.cs. This class is responsible for handling the connection to QuickBooks Online and retrieving customer data.

using System.Collections.Generic;
using Devart.Data.QuickBooks;

namespace QBOMAUI {
  public class QuickBooksService {
    private string connectionString;

    public QuickBooksService() {
      connectionString = "Sandbox=true;" +
        "Client Id=**********;" +
        "Company Id=**********;" +
        "Client Secret=**********;" +
        "Refresh token=**********;" +
        "License key=**********;";
    }

    public (bool IsConnected, string ErrorMessage) CheckConnectionStatus() {
      try {
        using (QuickBooksConnection connection = new QuickBooksConnection()) {
          connection.ConnectionString = connectionString;
          connection.Open();
          return (true, string.Empty);
        }
      } catch (System.Exception ex) {
        return (false, ex.Message);
      }
    }

    public List GetCustomers() {
      List customers = new List();

      using (QuickBooksConnection connection = new QuickBooksConnection()) {
        connection.ConnectionString = connectionString;
        connection.Open();

        string query = "SELECT Id, DisplayName, PrimaryPhone_FreeFormNumber, PrimaryEmailAddr_Address, BillAddr_City, Balance FROM Customer ORDER BY Id DESC LIMIT 10;";

        using (QuickBooksCommand command = new QuickBooksCommand(query, connection)) {
          using (QuickBooksDataReader reader = command.ExecuteReader()) {
            while (reader.Read()) {
              customers.Add(new Customer {
                Id = reader["Id"]?.ToString() ?? "N/A",
                DisplayName = reader["DisplayName"]?.ToString() ?? "N/A",
                PrimaryPhone_FreeFormNumber = reader["PrimaryPhone_FreeFormNumber"]?.ToString() ?? "N/A",
                PrimaryEmailAddr_Address = reader["PrimaryEmailAddr_Address"]?.ToString() ?? "N/A",
                BillAddr_City = reader["BillAddr_City"]?.ToString() ?? "N/A",
                Balance = reader["Balance"]?.ToString() ?? "N/A"
              });
            }
          }
        }
      }

      return customers;
    }
  }
}
                    

The connectionString variable contains the necessary credentials and settings to connect to QuickBooks Online. This includes parameters like Sandbox, Client Id, Company Id, Client Secret, Refresh Token, and License Key.

CheckConnectionStatus method

Attempts to open a connection using the QuickBooksConnection class. It returns a tuple indicating whether the connection was successful and an error message if it wasn't.

GetCustomers method

Opens a connection, executes a SQL query to retrieve Customer data, and maps the results to a list of Customer objects.

Use the QuickBooksService in your MAUI page

Modify your MainPage.xaml.cs to use QuickBooksService. This class is the code-behind for the MainPage.xaml file. It handles the logic for displaying data and managing user interactions on the main page of the application.

using Microsoft.Maui.Controls;
using System.Collections.Generic;

namespace QBOMAUI {
  public partial class MainPage : ContentPage {
    private QuickBooksService quickBooksService;

    public MainPage() {
      InitializeComponent();
      quickBooksService = new QuickBooksService();
      CheckConnectionAndLoadData();
    }

    private async void CheckConnectionAndLoadData() {
      var (isConnected, errorMessage) = quickBooksService.CheckConnectionStatus();
      if (isConnected) {
        ConnectionStatusLabel.Text = "Connected to QuickBooks Online";
        ConnectionStatusLabel.TextColor = Colors.Green;
        List customers = quickBooksService.GetCustomers();
        CustomersCollectionView.ItemsSource = customers;
      } else {
        ConnectionStatusLabel.Text = $"Connection failed: {errorMessage}";
        ConnectionStatusLabel.TextColor = Colors.Red;
        await DisplayAlert("Error", $"Failed to connect to QuickBooks Online: {errorMessage}", "OK");
      }
    }
  }
}
                    

Calls CheckConnectionStatus to verify the connection. If successful, it updates the UI to reflect the connection status and loads customer data into CollectionView. If the connection fails, it displays an error message.

Update MainPage.xaml

Modify your MainPage.xaml to use CollectionView to display the customers. This file defines the user interface of the main page using XAML. It specifies how data should be displayed and how the UI should look.

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="QBOMAUI.MainPage">

  <StackLayout>
    <Label x:Name="ConnectionStatusLabel"
           Text="Checking connection..."
           TextColor="Gray"
           FontAttributes="Italic"
           Margin="0,10,0,15" />

    <Label Text="Customers Table" FontAttributes="Bold" Margin="0,0,0,5" />

    <!-- Header Row -->
    <Grid Padding="5" ColumnDefinitions="*,*,*,*,*" Margin="0,0,0,5">
      <Label Text="Display Name" FontAttributes="Bold" Grid.Column="0" />
      <Label Text="Primary Phone" FontAttributes="Bold" Grid.Column="1" />
      <Label Text="Primary Email" FontAttributes="Bold" Grid.Column="2" />
      <Label Text="Bill Address City" FontAttributes="Bold" Grid.Column="3" />
      <Label Text="Balance" FontAttributes="Bold" Grid.Column="4" />
    </Grid>

    <CollectionView x:Name="CustomersCollectionView" ItemsSource="{Binding Customers}" VerticalOptions="FillAndExpand">
      <CollectionView.ItemTemplate>
        <DataTemplate>
          <Grid Padding="5" ColumnDefinitions="*,*,*,*,*">
            <!-- Display Name -->
            <Label Grid.Column="0" Text="{Binding DisplayName}" FontSize="16" />

            <!-- Primary Phone -->
            <Label Grid.Column="1" Text="{Binding PrimaryPhone_FreeFormNumber}" FontSize="16" />

            <!-- Primary Email -->
            <Label Grid.Column="2" Text="{Binding PrimaryEmailAddr_Address}" FontSize="16" />

            <!-- Bill Address City -->
            <Label Grid.Column="3" Text="{Binding BillAddr_City}" FontSize="16" />

            <!-- Balance -->
            <Label Grid.Column="4" Text="{Binding Balance}" FontSize="16" />
          </Grid>
        </DataTemplate>
      </CollectionView.ItemTemplate>
    </CollectionView>
  </StackLayout>
</ContentPage>
                    

ConnectionStatusLabel: A label that displays the current connection status to QuickBooks Online.

Customers Table Header: A grid that serves as a header row for the customers table, displaying column names like Name, Phone, Email, City, and Balance.

CollectionView: This one is named CustomersCollectionView, and it displays the list of customers. It uses DataTemplate to define how each customer should be rendered within a grid.

Data Binding: CollectionView is bound to the Customer property, which is populated with data from QuickBooksService.

Once you successfully connect your application to QuickBooks Online, you will be able to fetch and manage your data.

string connectionString = "Sandbox=true;" +
                         "Client Id=**********;" +
                         "Company Id=**********;" +
                         "Client Secret=**********;" +
                         "Refresh token=**********;" +
                         "License key=**********;";
                    

This is what our entire application code looks like.

using System;
using System.Data;
using Devart.Data.QuickBooks;

namespace QuickBooksConsoleApp
{
  class Program
  {
    static void Main(string[] args)
    {
      // Define the connection string
      string connectionString = "Sandbox=true;" +
                              "Client Id=**********;" +
                              "Company Id=**********;" +
                              "Client Secret=**********;" +
                              "Refresh token=**********;" +
                              "License key=**********;";

      try
      {
        // Initialize the QuickBooks connection
        using (QuickBooksConnection quickBooksConnection = new QuickBooksConnection())
        {
          quickBooksConnection.ConnectionString = connectionString;

          // Open the connection
          quickBooksConnection.Open();

          Console.WriteLine("Connected to QuickBooks Online successfully.");

          // Define the SQL query to fetch data from the Account table
          string query = "SELECT Id, Name, FullyQualifiedName, Description FROM Account";

          // Create a command object
          using (QuickBooksCommand command = new QuickBooksCommand(query, quickBooksConnection))
          {
            // Execute the command and get a data reader
            using (QuickBooksDataReader reader = command.ExecuteReader())
            {
              // Check if data exists
              if (reader.HasRows)
              {
                Console.WriteLine("Fetching Account data:");
                Console.WriteLine("--------------------------------------------------");

                // Loop through the data
                while (reader.Read())
                {
                  string id = reader["Id"]?.ToString() ?? "N/A";
                  string name = reader["Name"]?.ToString() ?? "N/A";
                  string fullyQualifiedName = reader["FullyQualifiedName"]?.ToString() ?? "N/A";
                  string description = reader["Description"]?.ToString() ?? "N/A";

                  Console.WriteLine($"Id: {id}");
                  Console.WriteLine($"Name: {name}");
                  Console.WriteLine($"FullyQualifiedName: {fullyQualifiedName}");
                  Console.WriteLine($"Description: {description}");
                  Console.WriteLine("--------------------------------------------------");
                }
              }
              else
              {
                Console.WriteLine("No data found in the Account table.");
              }
            }
          }

          // Close the connection
          quickBooksConnection.Close();
          Console.WriteLine("Connection closed.");
        }
      }
      catch (Exception ex)
      {
        Console.WriteLine("An error occurred:");
        Console.WriteLine(ex.Message);
      }

      Console.WriteLine("Press any key to exit.");
      Console.ReadKey();
    }
  }
}
                    

Once you successfully connect your application to QuickBooks Online, you will be able to fetch and manage your data.

Home page

Insert new data

Add a method to QuickBooksService.cs to insert a new customer:

public bool InsertCustomer(string displayName, string primaryPhone, string primaryEmail, string billAddrCity, string balance)
{
  try
  {
    using (QuickBooksConnection connection = new QuickBooksConnection())
    {
      connection.ConnectionString = connectionString;
      connection.Open();

      string query = "INSERT INTO Customer (DisplayName, PrimaryPhone_FreeFormNumber, PrimaryEmailAddr_Address, BillAddr_City) VALUES (:DisplayName, :PrimaryPhone, :PrimaryEmail, :BillAddrCity)";

      using (QuickBooksCommand command = new QuickBooksCommand(query, connection))
      {
        command.Parameters.Add("DisplayName", DbType.String).Value = string.IsNullOrEmpty(displayName) ? DBNull.Value : displayName;
        command.Parameters.Add("PrimaryPhone", DbType.String).Value = string.IsNullOrEmpty(primaryPhone) ? DBNull.Value : primaryPhone;
        command.Parameters.Add("PrimaryEmail", DbType.String).Value = string.IsNullOrEmpty(primaryEmail) ? DBNull.Value : primaryEmail;
        command.Parameters.Add("BillAddrCity", DbType.String).Value = string.IsNullOrEmpty(billAddrCity) ? DBNull.Value : billAddrCity;

        int rowsAffected = command.ExecuteNonQuery();
        return rowsAffected > 0;
      }
    }
  }
  catch
  {
    return false;
  }
}
                    

Modify MainPage.xaml.cs

Add a method to MainPage.xaml.cs to handle the insertion of a new customer. You can also add a button in your XAML to trigger this method.

private async void OnInsertCustomerClicked(object sender, EventArgs e)
{
  string displayName = "New Customer Name";
  string primaryPhone = "1234567890";
  string primaryEmail = "[email protected]";
  string billAddrCity = "City Name";
  string balance = "100.00";

  bool isInserted = quickBooksService.InsertCustomer(displayName, primaryPhone, primaryEmail, billAddrCity, balance);

  if (isInserted)
  {
    await DisplayAlert("Success", "Customer inserted successfully", "OK");
    CheckConnectionAndLoadData(); // Refresh the data
  }
  else
  {
    await DisplayAlert("Error", "Failed to insert customer", "OK");
  }
}
                    

Added the OnInsertCustomerClicked method to handle the insertion of a new customer and refresh the data.

Update MainPage.xaml

Add a button to your MainPage.xaml to trigger the insertion of a new customer:

<Button Text="Insert New Customer"
        Clicked="OnInsertCustomerClicked"
        Margin="0,0,0,10"
        WidthRequest="200" />
                    

A button was added to trigger the insertion of a new customer.

Let's test it.

Insert new customer

Click Insert New Customer.

Customer inserted successfully

Check the new customer record.

Customers table

Delete records

To add a method for removing a record and include a red Delete button in each row of CollectionView, you'll need to follow these steps:

Add a Remove method to QuickBooksService.cs

First, add a method to QuickBooksService.cs to handle the deletion of a customer:

public bool RemoveCustomer(string customerId)
{
  try
  {
    using (QuickBooksConnection connection = new QuickBooksConnection())
    {
      connection.ConnectionString = connectionString;
      connection.Open();

      string query = "DELETE FROM Customer WHERE Id = :CustomerId";

      using (QuickBooksCommand command = new QuickBooksCommand(query, connection))
      {
        command.Parameters.Add("CustomerId", DbType.String).Value = customerId;

        int rowsAffected = command.ExecuteNonQuery();
        return rowsAffected > 0;
      }
    }
  }
  catch
  {
    return false;
  }
}
                    

Modify MainPage.xaml.cs to handle the deletion

Add a method to handle the deletion of a customer in MainPage.xaml.cs:

private async void OnDeleteCustomerClicked(object sender, EventArgs e)
{
  if (sender is Button button && button.CommandParameter is string customerId)
  {
    bool isRemoved = quickBooksService.RemoveCustomer(customerId);

    if (isRemoved)
    {
      await DisplayAlert("Success", "Customer removed successfully", "OK");
      CheckConnectionAndLoadData(); // Refresh the data
    }
    else
    {
      await DisplayAlert("Error", "Failed to remove customer", "OK");
    }
  }
}
                    

Update MainPage.xaml to include a Delete button

Modify the grid and CollectionView in MainPage.xaml to include a Delete button in each row:

<!-- Header Row -->
<Grid Padding="5" ColumnDefinitions="*,*,*,*,Auto" Margin="0,0,0,5">
  <Label Text="Display Name" FontAttributes="Bold" Grid.Column="0" />
  <Label Text="Primary Phone" FontAttributes="Bold" Grid.Column="1" />
  <Label Text="Primary Email" FontAttributes="Bold" Grid.Column="2" />
  <Label Text="Bill Address City" FontAttributes="Bold" Grid.Column="3" />
  <Label Text="Action" FontAttributes="Bold" Grid.Column="4" />
</Grid>

<CollectionView x:Name="CustomersCollectionView" ItemsSource="{Binding Customers}" VerticalOptions="FillAndExpand">
  <CollectionView.ItemTemplate>
    <DataTemplate>
      <Grid Padding="5" ColumnDefinitions="*,*,*,*,Auto">
        <!-- Display Name -->
        <Label Grid.Column="0" Text="{Binding DisplayName}" FontSize="16" />

        <!-- Primary Phone -->
        <Label Grid.Column="1" Text="{Binding PrimaryPhone_FreeFormNumber}" FontSize="16" />

        <!-- Primary Email -->
        <Label Grid.Column="2" Text="{Binding PrimaryEmailAddr_Address}" FontSize="16" />

        <!-- Bill Address City -->
        <Label Grid.Column="3" Text="{Binding BillAddr_City}" FontSize="16" />

        <!-- Delete Button -->
        <Button Grid.Column="4" Text="Delete" TextColor="White" BackgroundColor="Red"
                CommandParameter="{Binding Id}"
                Clicked="OnDeleteCustomerClicked" />
      </Grid>
    </DataTemplate>
  </CollectionView.ItemTemplate>
</CollectionView>
                    

A red Delete button is added to each row in CollectionView. The button's CommandParameter is set to the customer's ID, and it triggers the OnDeleteCustomerClicked method when clicked.

Let's run our application and try to delete New Customer Name.

Customer removed successfully

Now let's check the deleted row after reloading.

Customers table

Conclusion

By following this guide, you've successfully integrated QuickBooks Online into your .NET MAUI application using dotConnect for QuickBooks Online. This setup enables data access and manipulation directly from your cross-platform app. For advanced scenarios, consider exploring dotConnect's support for EF Core and ORM features.

dotConnect for QuickBooks

Get an enhanced ORM-enabled data provider and develop .NET applications working with QuickBooks data quickly and easily!

Discover the ultimate capabilities of dotConnect for QuickBooks Online Download free trial