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

Connect a .NET MAUI Application to Zoho CRM

This guide will show you how to connect a .NET MAUI application to Zoho CRM using dotConnect for Zoho CRM, a high-performance ADO.NET provider by Devart. You'll learn how to set up OAuth authentication, create a connection, and perform basic data operations like reading, inserting, and deleting Zoho CRM records — all using standard ADO.NET classes.

Why dotConnect for Zoho CRM?

  • Provides native ADO.NET support with full access to Zoho CRM entities.
  • Enables seamless OAuth 2.0 integration for secure authentication.
  • Offers cross-platform compatibility, including .NET MAUI apps.
  • Simplifies Zoho CRM integration through SQL-based access.

Prerequisites

Before starting, ensure you have the following prerequisites in place:

  • Visual Studio 2022: The IDE we use. If you don't have it on your computer, go to the official website to download and install it. We'll use the Community edition.
  • dotConnect for Zoho CRM: A feature-rich ADO.NET provider with Entity Framework, NHibernate, and EF Core support. For installation instructions, refer to the next section.
  • Access to a Zoho CRM account: Required for API access and OAuth credentials.

Download and activate dotConnect for Zoho CRM

30-day free trial version

Download and install dotConnect for Zoho CRM directly on your machine, or use the Devart.Data.Zoho NuGet package.

No license key is required — 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.

License details and the activation key

To activate a connection in your application, add the activation key to the connection string.

Create a .NET project

1. Open your IDE, select Create a new project > .NET MAUI App and click Next.

2. Name your project, for example, ZohoMAUI, specify its location, and click Next

3. To create the project, click Create.

4. In the Solution Explorer, right-click the created project and select Manage NuGet Packages.

5. On the Browse tab, search for the Devart.Data.Zoho package and install it. Optionally, you can run this command:

dotnet add package Devart.Data.Zoho

Check Zoho CRM objects

1. To connect to Zoho CRM using the built-in Data Explorer, navigate to Tools > Connect to Database.

Connect to Zoho CRM

2. Then, select the Zoho CRM data source, enter a Zoho domain, and click Web Login.

Select the Zoho CRM data source

3. Log in to your Zoho account and grant access to your Zoho CRM organization.

Grant access

4. After that, select the tables and fields you want to work with, and retrieve the data.

Grant access

Get Zoho CRM tokens

OAuth tokens are required to authenticate and connect to Zoho CRM. For more details, refer to the Zoho CRM official documentation.

1. To interact with the Zoho API, you need to obtain a token that grants access to the client service. To do this, go to the Zoho API Console and sign in using your Zoho account credentials.

2. Click Add Client and select Self Client.

3. Fill in the Scope and Scope Description fields.

Fill in the fields

4. To get the code, click Create.

Generated code

5. Copy the generated code, paste it into the appropriate field in the Zoho Console, and click Send. The Refresh Token will be generated automatically.

Paste the generated code

Establish the connection

In this section, you can find sample code to set up and connect to Zoho CRM, which you can use as is or modify according to your needs.

The following parameters require values:

  • Domain
  • API Version
  • Client ID
  • Client Secret
  • Refresh Token
  • License Key

The code looks as follows; replace the placeholders with your valid Zoho CRM credentials.

string domain = "crm.zoho.com";
string clientId = "**********";
string clientSecret = "**********";
string refreshToken = "**********";
string licenseKey = "**********";

string connectionString = $"Domain={domain};API Version=v2;Client Id={clientId};Client Secret={clientSecret};Refresh Token={refreshToken};License Key={licenseKey}";

Read Zoho CRM data

Now, let's see how to retrieve and display data from Zoho CRM.

Create the AppConfig class

Create a new class file named AppConfig.cs in your project, and add the following code to it:

namespace ZohoMAUI
{
    public static class AppConfig
    {
        public static string Domain { get; } = "crm.zoho.eu";
        public static string ClientId { get; } = "**********";
        public static string ClientSecret { get; } = "**********";
        public static string RefreshToken { get; } = "**********";
        public static string LicenseKey { get; } = "**********";

        public static string ConnectionString =>
            $"Domain={Domain};API Version=v2;Client Id={ClientId};Client Secret={ClientSecret};Refresh Token={RefreshToken};License Key={LicenseKey}";
    }
}

Implement the code to connect to Zoho CRM

Open MainPage.xaml.cs and add this code to handle the button click event and load data from Zoho CRM.

using Devart.Data.Zoho;
using System.Collections.ObjectModel;

namespace ZohoMAUI {

  public partial class MainPage: ContentPage {
    public ObservableCollection<Account> Accounts 
    {
      get;
      set;
    }

    public MainPage() 
    {
      InitializeComponent();
      Accounts = new ObservableCollection<Account>();
      AccountsListView.ItemsSource = Accounts;
      InitializeDataAsync();
    }

    private async void InitializeDataAsync() 
    {
      if (await CheckConnection()) 
      {
        LoadAccounts();
      }
    }

    private async Task<bool> CheckConnection() 
    {
      try 
     {
        using(var connection = new ZohoConnection(AppConfig.ConnectionString)) 
        {
          await Task.Run(() => connection.Open());
          ConnectionStatusLabel.Text = "Successful connection";
          return true;
        }
      } catch (Exception ex) 
      {
        await DisplayAlert("Connection Error", $"Failed to connect: {ex.Message}", "OK");
        return false;
      }
    }

    private void LoadAccounts() 
    {
      try 
      {
        using(var connection = new ZohoConnection(AppConfig.ConnectionString)) 
        {
          connection.Open();
          var command = new ZohoCommand("SELECT \"Account Name\", Phone, Website, \"Account Type\" FROM Accounts", connection);
          var reader = command.ExecuteReader();

          while (reader.Read() && Accounts.Count < 10) 
          {
            Accounts.Add(new Account 
          {
              Account_Name = reader["Account Name"].ToString(),
                Phone = reader["Phone"].ToString(),
                Website = reader["Website"].ToString(),
                Account_Type = reader["Account Type"].ToString()
            });
          }
        }
      } catch (Exception ex) {
        DisplayAlert("Error", ex.Message, "OK");
      }
    }
  }

  public class Account {
    public string Account_Name {
      get;
      set;
    }
    public string Phone {
      get;
      set;
    }
    public string Website {
      get;
      set;
    }
    public string Account_Type {
      get;
      set;
    }
  }

}

The CheckConnection method checks whether a connection to Zoho CRM can be established and informs the user of the result. The LoadAccounts method retrieves account data from Zoho CRM and populates ObservableCollection < Account >.

Set up the main page

To add the button that tests the connection and displays the data, open MainPage.xaml and paste the following code.

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ZohoMAUI.MainPage">
                        <StackLayout>
                        <Label x:Name="ConnectionStatusLabel" TextColor="Green" FontSize="Medium" HorizontalOptions="Center" />
                        <ListView x:Name="AccountsListView">
                        <ListView.ItemTemplate>
                        <DataTemplate>
                        <ViewCell>
                        <Grid Padding="10">
                        <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                        <Label Grid.Column="0" Text="{Binding Account_Name}" FontAttributes="Bold" />
                        <Label Grid.Column="1" Text="{Binding Phone}" />
                        <Label Grid.Column="2" Text="{Binding Website}" />
                        <Label Grid.Column="3" Text="{Binding Account_Type}" />
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

Grid Layout: Grid inside DataTemplate is configured with four columns. Each of them takes an equal share of the width. This creates a table-like layout with four columns.

Data Binding: Each Label in Grid is bound to a property of the Account class and displays the data in the respective columns.

Connection Status: ConnectionStatusLabel displays the connection status in green if the connection is successful.

Once you have connected your application to Zoho CRM, you can fetch and manage your data.

Fetch the data

Insert new data

To add functionality for creating a new account and refreshing the table, add a button to your UI and implement the logic to insert a new account into the Zoho CRM database. After adding the account, display an alert to inform the user of the status, then refresh the data to update the table.

1. In MainPage.xaml, paste this code after ListView to include the button for adding a new account.

<Button Text="Add Test Account" Clicked="OnAddAccountClicked" WidthRequest="200" Padding="0,10" />

2. In MainPage.xaml.cs, update the code-behind to include logic for adding a new account and refreshing the data.

using Devart.Data.Zoho;
using System.Collections.ObjectModel;

namespace ZohoMAUI
{

    public partial class MainPage : ContentPage
    {
        public ObservableCollection<Account> Accounts
        {
            get;
            set;
        }

        public MainPage()
        {
            InitializeComponent();
            Accounts = new ObservableCollection<Account>();
            AccountsListView.ItemsSource = Accounts;
            InitializeDataAsync();
        }

        private async void InitializeDataAsync()
        {
            if (await CheckConnection())
            {
                LoadAccounts();
            }
        }

        private async Task<bool> CheckConnection()
        {
            try
            {
                using (var connection = new ZohoConnection(AppConfig.ConnectionString))
                {
                    await Task.Run(() => connection.Open());
                    ConnectionStatusLabel.Text = "Successful connection";
                    return true;
                }
            }
            catch (Exception ex)
            {
                await DisplayAlert("Connection Error", $"Failed to connect: {ex.Message}", "OK");
                return false;
            }
        }

        private async void OnAddAccountClicked(object sender, EventArgs e)
        {
            try
            {
                using (var connection = new ZohoConnection(AppConfig.ConnectionString))
                {
                    connection.Open();
                    var command = new ZohoCommand(
                      "INSERT INTO Accounts (\"Account Name\", Phone, Website, \"Account Type\") " +
                      "VALUES (:Account_Name, :Phone, :Website, :Account_Type)", connection);

                    // Add parameters for the test data
                    command.Parameters.Add(new ZohoParameter { ParameterName = ":Account_Name", Value = "Test Account" });
                    command.Parameters.Add(new ZohoParameter { ParameterName = ":Phone", Value = "123-456-7890" });
                    command.Parameters.Add(new ZohoParameter { ParameterName = ":Website", Value = "http://testaccount.com" });
                    command.Parameters.Add(new ZohoParameter { ParameterName = ":Account_Type", Value = "Test Type" });

                    int rowsAffected = command.ExecuteNonQuery();
                    if (rowsAffected > 0)
                    {
                        await DisplayAlert("Success", "Account added successfully!", "OK");
                        await LoadAccounts();
                    }
                    else
                    {
                        await DisplayAlert("Error", "No rows were affected.", "OK");
                    }
                }
            }
            catch (Exception ex)
            {
                await DisplayAlert("Error", $"Failed to add account: {ex.Message}", "OK");
            }
        }

private async Task LoadAccounts()
        {
            try
            {
                using (var connection = new ZohoConnection(AppConfig.ConnectionString))
                {
                    connection.Open();
                    var command = new ZohoCommand("SELECT \"Account Name\", Phone, Website, \"Account Type\" FROM Accounts", connection);
                    var reader = command.ExecuteReader();

                    await MainThread.InvokeOnMainThreadAsync(() => Accounts.Clear());
                    while (reader.Read() && Accounts.Count < 10)
                    {
                        var account = new Account
                        {
                            Account_Name = reader["Account Name"].ToString(),
                            Phone = reader["Phone"].ToString(),
                            Website = reader["Website"].ToString(),
                            Account_Type = reader["Account Type"].ToString()
                        };
                        await MainThread.InvokeOnMainThreadAsync(() => Accounts.Add(account));
                    }
                }
            }
            catch (Exception ex)
            {
                await DisplayAlert("Error", ex.Message, "OK");
            }
        }

    }


    public class Account
    {
        public string Account_Name
        {
            get;
            set;
        }
        public string Phone
        {
            get;
            set;
        }
        public string Website
        {
            get;
            set;
        }
        public string Account_Type
        {
            get;
            set;
        }
    }

}

The OnAddAccountClicked method is called when the Add Test Account button is clicked. It inserts a new account into the Zoho CRM database using test data.

ZohoCommand is an SQL command for inserting a new account and utilizes parameters to specify the values. The parameter names correspond to the field names in the database.

Alert and Refresh: After adding the account, an alert is displayed to inform the user, and the LoadAccounts method is called to refresh the data in the table.

This setup allows users to add a new test account and see the updated table immediately.

To run the application, click Add Test Account.

Run the application

You should see such a notification.

Added account

Click OK to reload the page and verify that the account has been added.

Added account

Delete records

To add the button for deleting each row in the ListView, modify the DataTemplate and handle the button's click event to remove the corresponding account.

1. Update MainPage.xaml to include the button in each row of the ListView:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ZohoMAUI.MainPage">
                        <StackLayout>
                        <Label x:Name="ConnectionStatusLabel" TextColor="Green" FontSize="Medium" HorizontalOptions="Center" />
                        <ListView x:Name="AccountsListView">
                        <ListView.ItemTemplate>
                        <DataTemplate>
                        <ViewCell>
                        <Grid Padding="10">
                        <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
                        <Label Grid.Column="0" Text="{Binding Account_Name}" FontAttributes="Bold" />
                        <Label Grid.Column="1" Text="{Binding Phone}" />
                        <Label Grid.Column="2" Text="{Binding Website}" />
                        <Label Grid.Column="3" Text="{Binding Account_Type}" />
                        <Button Grid.Column="4" Text="Delete" Clicked="OnDeleteAccountClicked" CommandParameter="{Binding .}" />
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
                        <Button Text="Add Test Account" Clicked="OnAddAccountClicked" WidthRequest="200" Padding="0,10" />
    </StackLayout>
</ContentPage>

CommandParameter is set to the current account and allows the event handler to access the account data.

2. In MainPage.xaml.cs, modify the code to implement the logic for deleting accounts.

private async void OnDeleteAccountClicked(object sender, EventArgs e)
{
    var button = (Button)sender;
    var account = (Account)button.CommandParameter;

    try
    {
        using (var connection = new ZohoConnection(AppConfig.ConnectionString))
        {
            await Task.Run(() => connection.Open());
            var command = new ZohoCommand(
                "DELETE FROM Accounts WHERE \"Account Name\" = :Account_Name", connection);
            command.Parameters.Add(new ZohoParameter
            {
                ParameterName = ":Account_Name",
                Value = account.Account_Name
            });

            int rowsAffected = await Task.Run(() => command.ExecuteNonQuery());
            if (rowsAffected > 0)
            {
                await DisplayAlert("Success", "Account deleted successfully!", "OK");
                await LoadAccounts();
            }
            else
            {
                await DisplayAlert("Error", "No rows were affected.", "OK");
            }
        }
    }
    catch (Exception ex)
    {
        await DisplayAlert("Error", $"Failed to delete account: {ex.Message}", "OK");
    }
}

The OnDeleteAccountClicked method is called when the delete button is clicked. It retrieves the account associated with the button and executes an SQL command to delete the account from the database. After deletion, it refreshes the data to update the ListView.

Let's test the added logic. Click Delete next to Test Account.

Delete the test account

You should see a notification that confirms the successful deletion.

Deleted test account

Click OK to verify the result.

Check the result

Conclusion

Integration of Zoho CRM into a .NET MAUI application is straightforward with dotConnect for Zoho CRM. With ADO.NET, you can authenticate securely with OAuth, access CRM modules using SQL, and perform real-time read, insert, and delete operations — without writing any HTTP request logic.

dotConnect for Zoho CRM

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

Discover the ultimate capabilities of dotConnect for Zoho CRM Download free trial