Adventures with Dapr | Saving to Dapr MongoDB State Store Component in .NET 5.0
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.
What are we going to build?
- SaveState Service: A
.NET 5.0
service which has a/saveWeatherState
endpoint to persist data into MongoDB via Dapr.
Prerequisites :
- Dapr 1.2 is installed locally.
- Visual Studio Code
- MongoDB for VSCode Extension
- Docker — To Install Local MongoDB
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
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 :
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:
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 :
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.