Adventures with Dapr | Saving to Dapr MongoDB State Store Component in .NET 5.0

Kshitij Sharma
Microsoft Azure
Published in
4 min readJul 19, 2021

What is Dapr?

Dapr helps developers build event-driven, resilient distributed applications. Whether on-premises, in the cloud, or on an edge device, Dapr helps you tackle the challenges that come with building microservices and keeps your code platform agnostic.

More on Dapr: https://dapr.io/

This article will discuss how to configure the Mongo State Store component in .NET using Dapr.

With Dapr, we can now change the state store by putting in a different Dapr state store component with zero code change required to publish or consume the events.

Source Code: https://github.com/kshitijcode/dapr-adventures

Other Parts in Adventure with Dapr Series.

Chapter 1 : https://ikshitijsharma.medium.com/adventures-with-dapr-publishing-subscribing-events-to-eventhub-in-net-5-0-5bf44cdb3c75

What are we going to build?

Architecture
  • SaveState Service: A .NET 5.0 service which has a /saveWeatherState endpoint to persist data into MongoDB via Dapr.

Prerequisites :

Provisioning the MongoDB Locally

docker run --name adventurous -p 27017:27017 \ 
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=password -d mongo

This will spin up a Local MongoDB with the specified credentials.

Setting up Dapr

Clone the repository to your local :

git clone git@github.com:kshitijcode/dapr-adventures.git
cd dapr-adventures

To get started, we will set up the state store component definition for Dapr to use our local MongoDB :

The metadata in the component definition for state store is self-explanatory.

We need host,username and password to connect and authenticate against MongoDB.

The mongo.yaml component definition uses an environment secret store Dapr component for reference value for all the metadata. This Dapr secret store component uses a locally defined environment variable for authentication. The secret store component is defined as follows :

Thus we will set the metadata spec as referenced in eventhub.yaml as environment variables :

export MONGO_HOST=localhost:27017                                                             
export MONGO_ROOT_USERNAME="admin"
export MONGO_ROOT_PASSWORD="password"

Let’s start the Dapr sidecar and observe logs :

dapr run --app-id savestate-service --components-path components --app-port 5300 --dapr-grpc-port 5301 --dapr-http-port 5380 --log-level debug
Line 17,18 — Dapr fails to load component

In Line 17,18 we can observe that we are not able to authenticate against MongoDB while loading the MongoDB component and getting the following error :

WARN[0000] error initializing state store mongo (state.mongodb/v1): error in connecting to mongodb, host: localhost:27017 error: connection() : auth error: sasl conversation error: unable to authenticate using mechanism "SCRAM-SHA-1": (AuthenticationFailed) Authentication failed.  app_id=savestate-service instance=Kshitijs-MacBook-Pro.local scope=dapr.runtime type=log ver=1.2.2

How do we fix this?

On debugging further and going through Dapr Mongo Component contrib code, I realized we need to specify the database as well for authentication in the Dapr component definition :

If we don’t specify any value for databaseName it automatically defaults DB to daprStore as defined in component definition for Mongo StateStore.

Let’s rerun Dapr, and its starts successfully :

Dapr Loads all components successfully.

To read more on how to understand Dapr works and how to interpret logs kindly refer to Chapter 1 of the series.

SaveState Service

It’s a .NET 5 based service that runs on port 5300 and publishes an event on a POST request to /saveWeatherState endpoint.

Let us go over the controller for the service :

  • We are using the Dapr Client .NET SDK to save data to Mongo via Dapr.
  • The first argument mongo is the name of the Dapr component that provides the state store implementation.
  • The second argument admin provides the name of the database to send the message.
  • The third argument is the payload of the message.

Open the solution in VSCode and run the Debug PublisherService Launch configuration from the debugger section.

The application starts running on port 5300. This is the same port Dapr listens to as defined by the app-port parameter while starting Dapr.

In Startup.cs, we have defined the Dapr gRPC and http endpoints for publishing events to Dapr:

The values are the same on which the Dapr sidecars runs as defined by dapr-grpc-port and dapr-http-port parameters:

Line 10,11: Values for the PORT Endpoint

The SaveState Service is ready now.

We can send a payload by executing the savestate.rest sample in VSCode using the VSCode Rest Extension. You can try hitting the endpoint with payload through Curl or Postman as well.

View the Data

We can view the saved data by exec into the docker container or through the VSCode Mongo Extension.

Connect to the MongoDB using the extension, and we can validate the data :

Connection to Local MongoDB
Actual Data Stored in Local Mongo

We can see the data getting persisted in the Local MongoDB.

Summary

That’s it! In this post, we saw how to use the Dapr Mongo state store component to save messages.

We also learned how to debug different kinds of Dapr errors. The best part is that we can now change the state store implementation with zero code change required in the application to persist to a data store.

--

--