Docs Menu

.NET (Xamarin) Tutorial

On this page

MongoDB Realm provides a .NET SDK that allows you to create a multi-platform mobile application with Xamarin and C#. This tutorial illustrates the creation of a "Task Tracker" application that allows users to:

  • Register their email as a new user account.
  • Sign in to their account with their email and password (and sign out later).
  • View a list of projects they are a member of.
  • View, create, modify, and delete tasks in projects.
  • View a list of team members in their project.
  • Add and remove team members to their project.

This tutorial should take around 30 minutes.

Note
Check Out the Quick Start

If you prefer to explore on your own rather than follow a guided tutorial, check out the .NET Quick Start. It includes copyable code examples and the essential information that you need to set up a MongoDB Realm application.

  1. Ensure that you have the following software installed by selecting the tab for your development environment:

  2. Also, ensure that you have completed the tutorial to Set up the backend.
1

We've already put together a task tracker Xamarin application that has most of the code you'll need. You can clone the client application repository directly from GitHub:

git clone --branch start https://github.com/mongodb-university/realm-tutorial-dotnet.git
cd realm-tutorial-dotnet
Tip

The start branch is an incomplete version of the app that we will complete in this tutorial. To view the finished app, check out the final branch and update App.xaml.cs with your Realm app ID.

2

Double-click the realm-tutorial-dotnet.sln file to open the solution in Visual Studio. Once open, take a few minutes to explore how the solution is organized. This is a standard multi-platform solution, based on a template provided by Visual Studio, that has been modified for our specific use. The solution has 3 projects:

Project
Purpose
realm-tutorial-dotnet

Provides shared resources, including the 4 Navigation Elements (the individual "screens" of the app) and the App.xaml file, which provides initialization code.

This project also includes a Models folder, which contains the data models that Realm uses to serialize and deserialize data. To learn more about how Realm object models are used in .NET applications, see Realm Objects in our .NET client guide.

realm-tutorial-dotnet.Android
Contains Android-specific resources, such as the Toolbar formatting.
realm-tutorial-dotnet.iOS
Contains iOS-specific resources.

You will perform all of the steps in this tutorial within the shared realm-tutorial-dotnet project. Specifically, you will be working in the following files:

File
Purpose
AddMemberPage.xaml.cs
Provides the functionality for adding and removing members of a project.
App.xaml.cs
Initializes the app, creates a public static Realm app, and defines the primary startup page.
EditTaskPage.xaml.cs
Provides the functionality for editing an existing Task.
LoginPage.xaml.cs
Provides the functionality to log on with an existing user account, or to register a new user account. When the app starts, if no user is currently logged on, this page is displayed first.
ProjectPage.xaml.cs
Provides the functionality for viewing all Projects that the user is in.
TaskPage.xaml.cs
Provides the functionality for viewing the list of Tasks in a Project.
3

To get the app working with your backend, you'll need to enter your Realm app ID and instantiate the Realm app. The Realm app is the interface to the MongoDB Realm backend.

Navigate to the App.xaml.cs file. At the top of the Application class, replace the appId value with your own Realm app ID. You can find this in the Realm UI.

Next, complete the OnStart() method:

RealmApp = Realms.Sync.App.Create(appId);

At this point, we have a static, public Realms.Sync.App object that we can use elsewhere in the project.

4

Navigate to LoginPage.xaml.cs. In this file, we will implement the login functionality for the app. We are using EmailPasswordAuth to authenticate users. To do this, we need to be able to log on existing users with the LogInAsync() method, and be able to register new users with the RegisterUserAsync() method.

The LoginPage.xaml file provides a UI for the user to enter an email address, password, and then click either the Log In or Create New Account button. You will implement the functionality of each buttons' Clicked event.

In the DoLogin() method, call LogInAsync, passing the credentials that the user entered. If that call succeeds, we have a valid Realms.Sync.User, and we can return to the default screen, which is defined in Projects.xaml.

var user = await App.RealmApp.LogInAsync(Credentials.EmailPassword(email, password));

Next, implement the user registration functionality in the RegisterUser() method by calling the RegisterUserAsync() method. On success, you then call DoLogin() to log on the new user:

await App.RealmApp.EmailPasswordAuth.RegisterUserAsync(email, password);
5

In the realm-tutorial-dotnet project, find the Models folder and expand it. These C# classes define the schemas for the objects we store in our realms. Note the following about the schemas:

  • A User has a string property that defines the User's unique partition.
  • A User also has a collection (IList) of Projects of which they are a member.
  • A Project also has its own unique Partition value.
  • A Task has an Owner property that maps to the Project to which it belongs.
  • A Task also has a Status, which is a string, but we use a TaskStatus enum to ensure consistency in the values we store.
  • The Member class does not map to a collection, but is instead used as a simplified User object for matching a User to a Project.

In summary, a User has an array of projects of which it is a member. Each Project has a name and partition value. Each Task has a name, status, and a list of Projects in which it is contained.

6

Now that we have an authenticated user, the app must access the list of projects in which the user is a member. To do this, we will first connect to the User realm, get the user object, and then display each of the projects listed in the User's MemberOf property.

The ProjectPage.xaml.cs file is the default screen for this app. In the OnAppearing() method, we check to see if we have an authenticated user already. If not, we redirect to the Login page. If we do, or when control is returned from the Login page, we can instantiate a SyncConfiguration object in the LoadProjects() method to get the user's custom realm.

From this realm, we fetch the specific user document that has an _id value matching the Id property. Each User object contains a read-only IList<Project> property called MemberOf, and we iterate through this list to display the Projects in the UI.

To implement this functionality, find the LoadProjects() method in ProjectPage.xaml.cs. This method is only called when we have an authenticated user.

Here, we instantiate the userRealm object by creating a SyncConfiguration object and passing that to the Realm.GetInstanceAsync() method. When building the SyncConfiguration object, we set the partition string to user=<USER_ID>:

userRealm = await Realm.GetInstanceAsync(syncConfig);

We then find the user from the User realm that matches the authenticated user's Id:

user = userRealm.Find<User>(App.RealmApp.CurrentUser.Id);
Note
How Do We Know Which Projects a User Can Access?

The backend you imported makes exactly one custom user data object for each user upon signup. This custom user data object contains a list of partitions a user can read and a list of partitions a user can write to.

The backend is set up so that every user has read-only access to their own custom user data object. The backend also has functions to add and remove access to projects, which we will use later when we add the Manage Team view.

By managing the custom user data object entirely on the backend and only providing read-only access on the client side, we prevent a malicious client from granting themselves arbitrary permissions.

Once you have the user, call SetUpProjectList(). In that method, you populate the MyProjects collection (an ObservableCollection<Project>), which is used to keep the list of projects up-to-date. When the app user touches one of the Projects in the list, we pass control to the TaskPage.xaml.cs class and display the list of Tasks within the selected Project.

7

Open the TaskPage.xaml.cs file. In the OnAppearing() method, we will create another realm, this time for the Task collection. In the user realm we used a partition key value of user=<USER_ID>; the project realm uses a partition key value of project=<USER_ID>. For the sake of simplicity in this tutorial, each user has exactly one project they own, and it is specified by the partition key value containing their own user ID:

taskRealm = await Realm.GetInstanceAsync(syncConfig);

In the SetUpTaskList() method, find all of the tasks. We find all tasks because we configured our taskRealm to use the partition specific to the user, removing the need to filter by "owner":

_tasks = new ObservableCollection<Task>(taskRealm.All<Task>().ToList());

At the bottom of the Task view, we have added a button for creating a new Task. In the Button_Clicked handler, we display a modal dialog to get the name of the new task and then create a new Task, setting the Task's status to TaskStatus.Open. We then add the Task to the taskRealm:

var newTask = new Task()
{
Name = result,
Partition = projectPartition,
Status = Task.TaskStatus.Open.ToString()
};
taskRealm.Write(() =>
{
taskRealm.Add(newTask);
});
Note

Whenever you write or delete from a realm, you must wrap your call within a transaction. The simplest way to do this is to use Write() to create a temporary transaction.

The final Task-related work is providing a way for the user to edit a Task, including changing its state. Within our UI, when a user taps on a task in the list, the EditTaskPage page displays. The logic here is similar to creating a Task, where the updated information is wrapped in a temporary transaction using the taskRealm.Write() method. To view this code, find the Save_Button_Clicked event handler in the EditTaskPage.xaml.cs file.

8

A user can add other users to their team, which allows them to view, edit, and delete tasks on the user's project. The AddMember page implements this functionality by calling a few Realm functions on the backend that we defined in the backend tutorial.

Find the AddMemberPage.xaml.cs file. First, we need to fetch the list of current team members. We do this in the OnAppearing() method:

teamMembers = await App.RealmApp.CurrentUser.Functions.CallAsync<List<User>>("getMyTeamMembers");

The UI provides two buttons for team management: an Add Member button at the bottom of the screen, and, next to each team member in the list, a Delete button to remove that specific member.

Find the Add_Button_Clicked handler. We display a modal dialog prompting the user to provide the email of an existing user. When the user clicks OK, we call the addTeamMember function on the backend to add the specified team member:

var functionResult = await App.RealmApp.CurrentUser.Functions.CallAsync<FunctionResult>("addTeamMember", result);

Finally, in the Delete_Button_Clicked handler, we use the button's CommandParameter to retrieve the team member's email, display a confirmation dialog, and then call the removeTeamMember function on the backend. The final step is to refresh the the list of members:

var result = await App.RealmApp.CurrentUser.Functions.CallAsync("removeTeamMember", email.ToString());
9

Congratulations! Now that you have completed the code, you can run the app and check functionality. Here are some things you can try in the app:

  • Create a user with email first@example.com
  • Explore the app, then log out or launch a second instance of the app on another device or simulator
  • Create another user with email second@example.com
  • Navigate to second@example.com's project
  • Add, update, and remove some tasks
  • Click "Manage Team"
  • Add first@example.com to your team
  • Log out and log in as first@example.com
  • See two projects in the projects list
  • Navigate to second@example.com's project
  • Collaborate by adding, updating, and removing some new tasks
Tip

If something isn't working for you, you can check out the final branch of this repo to compare your code with our finished solution.

Note
Give Feedback

How did it go? Use the Give Feedback tab at the bottom right of the page to let us know if this tutorial was helpful or if you had any issues.

Give Feedback
© 2021 MongoDB, Inc.

About

  • Careers
  • Legal Notices
  • Privacy Notices
  • Security Information
  • Trust Center
© 2021 MongoDB, Inc.