Console Task App
This tutorial provides a step-by-step walkthrough on how to build a task list app with a standard C# console app start project.
Overview
Setting Up
To set up your project for Ditto:
Creating a New Project
Open Visual Studio for Windows or for Mac.
Create a **New Project **and select Console Application.
When prompted to select a target framework, select .NET 6.0.
Select a name for your project; for example, “Tasks.”
Adding Ditto to the Project
We’ve deployed Ditto for C# on the standard NuGet package repository. We will need to add Ditto to this project.
Right click the project’s Dependencies folder, and click _Manage NuGet Dependencies.
Search for “Ditto” in the search bar and add the package called “Ditto” by “Ditto”. Ensure not to mistake it for another package.
If you prefer a different way of installation, feel free to take a look at the alternative ways to install or reference the NuGet page here.
In your Program.cs file, add using DittoSDK
and using System.Collections.Generic
to the top of the file like so:
Now we’ll need to hold a reference to our Ditto instance as a static
variable and also add a static DittoLiveQuery
and static DittoSubscription
variable.
These variables must be static
because the console program’s Main
function is also static
.
Instantiate the ditto
static variable by constructing it with a development identity with an appID: "live.ditto.tasks"
. If you want to sync with other tutorial app types like iOS or Android, you’ll need to match the appID
to enable sync.
Creating a Task.cs File
Ditto documents have a flexible structure. Oftentimes, in strongly-typed languages like C#, we will create a data structure give more definition to the app. Create a new C# file named “Task.cs” in your project.
In the new file, you’ll need to reference System
, System.Collections.Generic
and DittoSDK
.
Add the matching variables string
_id
, string body
, and bool isCompleted
to the struct. We will use this to match the document values to to the struct.
Add an constructor to Task that takes in a DittoDocument. In the constructor, parse out the document’s keys with Ditto’s type safe value accessors. This will safely map all the document’s values to the struct’s variables that we created in step 2. In addition we will add a couple of other constructor overloads for easier creation of data.
Override the ToString()
method of the struct. We will later use this to easily print out a more readable string that we can use in Console.WriteLine
back in the main Program.cs
.
Add a function to the struct called ToDictionary
which will serialize the values into a Dictionary<string, object>
.
This will assist us later when we need to insert a new document into Ditto.
Configuring Commands
Unlike many UI applications, Console or Command Line applications have limitations to user interactions. For example, console applications typically read text commands during a while
loop as a standard design pattern. This section will outline the command line design and set up the loop to allow the user to give continual commands.
Designing the Commands
Our Tasks Console app will have five commands that map to Ditto and general console commands. We will need:
--insert
to allow the user to .insert
a new document into the ditto.collection('tasks")
collection
--toggle
to allow the user to .update
a new document’s bool isCompleted
property by its _id
.
--delete
to allow the user to .remove
a new document by its _id
.
--list
will print every current Task that we have in the collection. In addition, we will always call this method before every item.
--exit
will quit the console app.
As a best practice, long-running console applications should continuously print the primary set of commands as long as they are succinct. We’ll create a utility method called ListCommands()
which, will Console.WriteLine
each of the commands.
Observing the Tasks with a Live Query
As we insert, update, and delete our tasks, we will update the Tasks collection. To sync changes coming from other devices, we will need create a Live Query by calling .Observe
.
Remember Ditto will only sync with devices by calling .Observe
on queries. The .Observe
method will return a DittoLiveQuery
object. As long as the DittoLiveQuery
object stays in scope and is not garbage collected, the Live Query will fire for any changes to the tasks
collection.
Remember, the .Observe
callback will fire for both local changes and remote changes.
In the context of our console application, we need to:
Store a List<Task>
as a static variable so that we can print it upon command.
.Observe
all the document in the tasks collection. Take care to store the DittoLiveQuery
as a static variable as well.
In the .Observe
callback, convert all the List<DittoDocument>
docs into List<Task>
and assign them to both variables detailed in step 1 and 2.
We have all the basic building blocks for syncing tasks to a locally stored List<Task>
variable. In the following section, we will go over how to map the user commands to actual Ditto live query, insert, update and delete methods.
Setting up the while Loop
To determine whether or not the while loop should run, we need an addition static bool isAskedToExit = false
. If the user turns this to true
via the --exit
command, the while loop will stop and the application will exit.
In each iteration of the while loop, we will need read the command from the user. In C#, we can use the Console.ReadLine
API, which will prompt the user for a string entry. We can store this into string command
.
We can add a switch
statement which will parse the correct command and react to the command.
If the user types in --insert
, we will parse out the string without the --insert
command. We assume this string is the body for a new document. So we will call the .upsert
command with ditto via:
Check for a switch case for --toggle
. We will parse out the string without --toggle
and assume the user’s input is a Task document’s _id
. We can then find the document by its _id
and call .update
.
Check for a switch case for --delete
. We will parse out the string without --delete
and assume the user’s input is a Task document’s _id
. We can then find the document by its _id
and call .update
.
Finally we will add a command to look for --list
, which will print out all the tasks that we’ve synced.
codeblocktabs Program.cs
Reviewing Program.cs
Our application is complete! Our Program.cs file should look like the following. Now you can run the example in your terminal, command line or right within the run command in Visual Studio.
Was this page helpful?