In this guide, I will show you how to use the current version (8.2.1) of the EF Core Provider for mongoDB with its limitations.
The limitations that prevent this provider from directly being used for ASP.NET Core Identity include lack of support for the Select projection and some other Linq operations, which are used in Identity. Therefore some extra steps are needed to achieve an operational program.
Prerequisites
You need the following to complete follow along.
- Mongo Atlas account and a database URL for your cluster
- Configured development Environment that can develop Blazor Server App (I will be using Visual Studio 2022)
- An active internet connection (I guess it's obvious but anyway)
Creating the project
In Visual studio, Create a Blazor Server application (I have named min WeatherApp) and choose .NET version to 8.0 LTS and Athentication type to Individual Account. For Interactive render mode, select Server and choose your Global Interactivity location
After creating the application, you will notice that it has been configured to use SQL server by Default as the storage for EF Core in the Program.cs file. We shall change this shortly
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
Adding MongoDB related configurations
We shall start by installing the required nugget packages.
Use any preferred method to install the package MongoDB.EntityFrameworkCore version 8.2.
In the appsettings.json file define an object to store the MongoDB settings as shown below
"MongoDBSettings": {
"AtlasURI": "mongodb+srv://<username>:<password>@cluster0.abc.mongodb.net/?retryWrites=true&w=majority",
"DatabaseName": "weatherapp"
}
For the AtlasURI key, use the URI from the cluster that you created in your MongoDB Atlas account.
Also create a MongoDBSettings class in the Data folder in the root of the project to be used in mapping the settings.
public class MongoDBSettings
{
public string AtlasURI { get; set; } = string.Empty;
public string DatabaseName { get; set; } = string.Empty;
}
In the Program.cs file, there is a section of code used to configure the database context to use SQL server as shown below.

Replace that code with the code below, that uses MongoDB provider.
builder.Services.Configure<MongoDBSettings>(
builder.Configuration.GetSection("MongoDBSettings"));
var mongoDBSettings = builder.Configuration.GetSection("MongoDBSettings").Get<MongoDBSettings>();
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseMongoDB(mongoDBSettings!.AtlasURI ?? "", mongoDBSettings.DatabaseName ?? "")
.EnableSensitiveDataLogging());
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
Using the MongoDB ObjectId as the primary key type for ASP.NET Core Identity
By default, ASP.NET Core Identity uses a GUID string as the primary key while storing users in the SQL databases. However, it allows you to customize this and use another type like long, ulong, int, etc. In this case, since our databases uses its on unique identifier as the ObjectId, we shall use this for identity. Let do the necessary modifications to ensure this.
Note: Remember to add the necessary using statements in each file where we have modified the code.
Firstly, modify the ApplicationUser class in the Data folder to use the ObjectId as the primary key type for the identity user.
public class ApplicationUser : IdentityUser<ObjectId>
{
}
In the same Data folder, modify the ApplicationDbContext class to also inherit from a version of IdentityDbContext that allows specifying a different type for the primary key of the user and roles. We shall use ObjectId for both.
public class ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: IdentityDbContext<ApplicationUser, IdentityRole<ObjectId>, ObjectId>(options)
{
}
At this moment, we are able to run the application and a user can be registered. But when we try some other operations like the default account confirmation, we get exceptions notifying us that the conversion from the string type to the ObjectId type is not supported.
This prevents us from using other identity features. In order to handle this, and the other limitations of the EF Core Provider for MongoDB, we shall need to use a custom store for both users and roles.
Creating the custom stores for identity
In the project, create a new folder and name it CustomIdentityStores and create 2 files, namely UserStore.cs and RoleStore.cs
Get the starter code from the identity repository for each of these files using the links below (from the official identity repository)
Apart from the namespace declaration, paste the rest of the code into the corresponding file and we deal with the modifications (use local namespace).
In the UserStore.cs we shall have one error corresponding to some resource that we don't have access to.
For simplicity, just replace it to a constant string(e.g. "Role Not Found")
Modify the custom stores to handle Id conversion and other limitations of the provider
UserStore.cs
In this file, replace the FindByIdAsync method by the code below, which uses the ObjectId.Parse method instead of the identity one.
public override Task<TUser?> FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
var id = ObjectId.Parse(userId);// ConvertIdFromString(userId);
return UsersSet.FindAsync(new object?[] { id }, cancellationToken).AsTask();
}
Also modify the default User Store type and the corresponding other implementations to use ObjectId as the type of the unique identifier for both User and Role entities.
Make sure that you replace the DBContext injected in the default implementation to use the one ApplicationDbContext of our application.
In addition, methods such as GetRolesAsync where unsupported features such as the select projection are used, we can use client-side evaluation if we don't have a lot of roles or use any techniques of your choice to convert the Linq to SQL logic to something that is supported by the provider.
For example the code shown below:
can be converted to.
Do this for all such cases (e.g. in the GetClaimsAsync method) and end up with the changes as shown in the complete file here.
RoleStore.cs
In this file, follow the same steps as in the UserStore.cs. The example result is shown the completed file here.
Register the new Stores
In the Program.cs file, register these classes to be used by identity instead of the default stores by using the code below.
builder.Services.AddTransient<IUserStore<User>, UserStore>();
builder.Services.AddTransient<IRoleStore<IdentityRole<ObjectId>>, RoleStore<IdentityRole<ObjectId>>>();
Once Everything is wired correctly, You should be able to run the application, register, login and view the authorized resources.
Find the completed code in a git hub repository here.
Enjoy coding without any limits.







Top comments (0)