.NET (Xamarin) Tutorial
On this page
Overview
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.
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.
Prerequisites
Ensure that you have the following software installed by selecting the tab for your development environment:
- Also, ensure that you have completed the tutorial to Set up the backend.
Set up the Mobile App
Clone the Client App Repository
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
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.
Explore the App Structure
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 This project also includes a |
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. |
Connect to Your MongoDB Realm App
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.
Implement the AuthProvider
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);
View the Schemas
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) ofProjects
of which they are a member. - A
Project
also has its own uniquePartition
value. - A
Task
has anOwner
property that maps to theProject
to which it belongs. - A
Task
also has aStatus
, which is a string, but we use aTaskStatus
enum to ensure consistency in the values we store. - The
Member
class does not map to a collection, but is instead used as a simplifiedUser
object for matching aUser
to aProject
.
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.
Get the Projects
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);
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.
Implement the Task Page
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); });
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.
Implement Team Management
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());
Run and Test
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
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.
What's Next?
- Read our .NET SDK documentation.
- Work through the MongoDB Realm Backend tutorial.
- Find developer-oriented blog posts and integration tutorials on the MongoDB Developer Hub.
- Join the MongoDB Community forum to learn from other MongoDB developers and technical experts.
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.