Nano ASP.NET SaaS Boilerplate
Please allow a few seconds if the app is booting from a cold start.
Admin credentials (all tenants): / Password123!
Sample data resets every hour
Nano ASP.NET SaaS Boilerplate
.NET Solution
Vue UI
React UI
Razor Pages
.NET Solution

Persistence & Infrastructure

This guide will cover persistence and any infrastructure not already covered in the Authorization & Authentication or Multi-Tenancy guides.

The Repository

The RepositoryAsync class in Infrastructure/Persistence/Repository, is a generic repository responsible for all low level data operations. It’s implemented via IRepositoryAsync in Application/Common and can be used by application services via dependency injection. RepositoryAsync uses the ApplicationDbContext.

All methods have multiple overrides and can return data as entities or mapped DTOs. DTO mapping is handled by Automapper using projection to efficiently map domain entities and related data onto DTOs. Mapping configuration is defined in MappingProfiles in Infrastructure/Mapper.

To query data, any service can pass a specification object to the repository methods which will then be evaluated by Ardalis specification. Specification objects can contain filters, sorting, or any kind of criteria. Using the specification pattern is a great way to encapsulate query logic, making it reusable and easy to maintain.

Pagination is another low level data operation that is handled by the repository. There are two methods for returning paginated data GetTanstackPaginatedResultsAsync and GetJQDTPaginatedResultsAsync which differ slightly in the request and response format as needed by the table plugins.

Migrations & DB Contexts

There are two DB contexts which are used for actual data persistence, BaseDbContext and ApplicationDbContext, and one auxiliary context, TenantDbContext. These contexts are explained in detail in the Multi-Tenancy guide.

Migrations are handled per context found in Infrastructure/Persistence/Migrations. Initial migrations are already created. Any pending migrations will apply automatically on app start.

When creating migrations:

  • Select Infrastructure as the default project in Package Manager Console
  • Use the add-migration command with -Context to specify DB context and -o to specify output.
  • Running the application will apply any pending migrations. To explicitly run migrations, use the update-database with the -Context switch
add-migration -Context BaseDbContext -o Persistence/Migrations/BaseDb Base-NewMigration
add-migration -Context ApplicationDbContext -o Persistence/Migrations/AppDb App-NewMigration

If using Rider, specify –project AspNano.Infrastructure and -s AspNano.WebApi

Db Initializer

This database seeder class contains the SeedTenantAdminAndRoles method which is run on app start if no root tenant is found in the default database. This method will create a root tenant, roles, and root admin user.


Automapper is a third party NuGet package that provides DTO to domain entity mapping. It requires rules to be defined for each DTO / entity relationship. Add mapping rules in in Infrastructure/Mapper/MappingRules when you create new entities and DTOs.


MailKit is third party NuGet package that facilitates sending emails in .NET applications. Mail settings are defined in appsettings.json. Sign up for free email testing at Ethereal and replace the provided keys with your own.

Images & Files

The CloudinaryService uses the Cloudinary .NET SDK which is a third party NuGet package. Cloudinary is a digital asset management platform, which provides programmatic control of images and files on external storage. For the majority of cases, storing images and files on an external service is better than managing locally. There are many options for managing digital assets; Cloudinary is merely one example, albeit a good one.

Cloudinary settings are found in appsettings.json. If you use Cloudinary, sign up for the free tier and replace the provided keys with your own.

Next Steps

If you’ve purchased the full version with UI projects, continue on to the Vue project or React project documentation to start learning about them. Or, check out the Razor project documentation to see what changes it brings to the .NET solution.