A ready-to-use, layered ASP.NET Core 10 MVC solution template with Identity, EF Core, the repository pattern, Mapster mappings, dependency injection, tests and StyleCop warnings fixed.
- .NET 10 solution in the new
.slnxformat, split into Common, Data, Services, Web and Tests layers - ASP.NET Core MVC with an
Administrationarea restricted to theAdministratorrole - ASP.NET Core Identity (default UI) with custom
ApplicationUserandApplicationRole - Entity Framework Core with SQL Server, migrations applied on startup and data seeding
- Generic repositories with audit info (
CreatedOn,ModifiedOn) and soft delete (IsDeleted,DeletedOn) handled automatically - Mapster mappings declared on the view models via
IMapFrom<T>,IMapTo<T>andIHaveCustomMappings - SendGrid e-mail sender (and a
NullMessageSenderfor development) - Bootstrap 5.3, jQuery 4 and jQuery Validation, restored with LibMan at build time and bundled/minified with WebOptimizer
- xUnit.net v3 unit tests (Moq and the EF Core in-memory provider) and integration tests with
WebApplicationFactory, running on Microsoft Testing Platform - StyleCop analyzers and selected .NET code analysis rules configured in
.globalconfigandstylecop.json, and central package management (Directory.Packages.props) - GitHub Actions workflow that builds the solution and runs the tests
| Registration with client-side validation | Settings (entities mapped with Mapster) |
|---|---|
![]() |
![]() |
| Account management (ASP.NET Core Identity) | Administration area |
![]() |
![]() |
- .NET 10 SDK
- SQL Server (LocalDB, Express, Developer or a Docker container)
- Visual Studio 2026, Visual Studio Code or JetBrains Rider (optional)
Install the template from NuGet:
dotnet new install AspNetCoreTemplateCreate a project from it. Every AspNetCoreTemplate occurrence in file names, namespaces and the database name is replaced with your project name:
dotnet new aspnet-core -n YourProjectName -o YourProjectNameAfter creating the files, dotnet new asks whether to run dotnet format, which re-sorts the using directives for your project name so the StyleCop analyzers report no warnings. Answer yes, or pass --allow-scripts yes to skip the question.
Alternatively, clone this repository and run the TemplateRenamer tool from the src folder to rename the solution in place, then run dotnet format --diagnostics SA1210 --severity warn there.
-
Set the
DefaultConnectionconnection string inWeb/YourProjectName.Web/appsettings.json(it defaults toServer=.;Database=YourProjectName;Trusted_Connection=True;...). For LocalDB useServer=(localdb)\\mssqllocaldb. -
Run the web project from the solution folder:
cd YourProjectName dotnet run --project Web/YourProjectName.Web
The database is created and migrated on startup and the seeders add the
Administratorrole and a sample setting. -
Register a user and add it to the
Administratorrole to access the administration area, for example:INSERT INTO AspNetUserRoles (UserId, RoleId) SELECT u.Id, r.Id FROM AspNetUsers u, AspNetRoles r WHERE u.Email = 'you@example.com' AND r.Name = 'Administrator'
The Data project contains a design-time DbContext factory that reads its own appsettings.json, so migrations are created from that folder with the EF Core tools:
cd Data/YourProjectName.Data
dotnet ef migrations add YourMigrationNameThe test projects use xUnit.net v3 on Microsoft Testing Platform, which global.json turns on for dotnet test, so run it from the solution folder:
dotnet test YourProjectName.slnxEach test project is also a standalone executable, so dotnet run --project Tests/YourProjectName.Services.Data.Tests works as well.
The Web.Tests project starts the whole application with WebApplicationFactory, so it needs a reachable SQL Server. You can point it at a separate database with an environment variable:
$env:ConnectionStrings__DefaultConnection = "Server=.;Database=YourProjectName_Tests;Trusted_Connection=True;TrustServerCertificate=True"
dotnet test YourProjectName.slnxgraph TD
Web[Web] --> ViewModels[Web.ViewModels]
Web --> Infrastructure[Web.Infrastructure]
Web --> Services[Services]
Web --> ServicesData[Services.Data]
Web --> Messaging[Services.Messaging]
Web --> Data[Data]
ViewModels --> Mapping[Services.Mapping]
ViewModels --> Models[Data.Models]
ServicesData --> Mapping
ServicesData --> Models
ServicesData --> DataCommon[Data.Common]
Data --> Models
Data --> DataCommon
Data --> Common[Common]
Models --> DataCommon
AspNetCoreTemplate.Common contains things shared by the whole solution, for example GlobalConstants.cs with the system name and the administrator role name.
- AspNetCoreTemplate.Data.Common contains the base entity classes (
BaseModel<TKey>,BaseDeletableModel<TKey>), theIAuditInfoandIDeletableEntityinterfaces and theIRepository<T>andIDeletableEntityRepository<T>abstractions of the repository pattern. - AspNetCoreTemplate.Data.Models contains the entities, including
ApplicationUserandApplicationRole, which extend the Identity user and role. - AspNetCoreTemplate.Data contains the
ApplicationDbContext, the entity configurations, the migrations, the seeders and the EF Core repository implementations. TheDbContextfills in the audit info on save and applies a global query filter that hides soft-deleted entities, whileDeletein the deletable entity repository only marks entities as deleted (HardDeleteandUndeleteare also available).
- AspNetCoreTemplate.Services.Data contains the business logic that works with the repositories.
- AspNetCoreTemplate.Services.Mapping registers the Mapster mappings declared on your classes and provides the
To<T>()projection forIQueryable. - AspNetCoreTemplate.Services.Messaging contains the
IEmailSenderabstraction with a ready-to-use SendGrid implementation. - AspNetCoreTemplate.Services is the place for services that do not depend on the database.
Implement IMapFrom<TSource> (or IMapTo<TDestination>) and the mapping is registered on startup:
using AspNetCoreTemplate.Data.Models;
using AspNetCoreTemplate.Services.Mapping;
public class TagViewModel : IMapFrom<Tag>
{
public int Id { get; set; }
public string Name { get; set; }
}Implement IHaveCustomMappings when some members need custom configuration:
using AspNetCoreTemplate.Data.Models;
using AspNetCoreTemplate.Services.Mapping;
public class PostViewModel : IMapFrom<Post>, IHaveCustomMappings
{
public int Id { get; set; }
public string Title { get; set; }
public string AuthorName { get; set; }
public void CreateMappings(Mapster.TypeAdapterConfig configuration)
{
configuration.NewConfig<Post, PostViewModel>()
.Map(destination => destination.AuthorName, source => source.Author.UserName);
}
}Then project queries straight to view models, so only the needed columns are selected:
var posts = this.postsRepository.AllAsNoTracking().To<PostViewModel>().ToList();Note
Mapster has its own Mapster.IMapFrom<T> interface, so avoid using Mapster; next to using AspNetCoreTemplate.Services.Mapping; and write Mapster.TypeAdapterConfig instead.
- AspNetCoreTemplate.Web is the ASP.NET Core MVC application (controllers, views, the
Administrationarea, Identity and static files). - AspNetCoreTemplate.Web.ViewModels contains the view and input models, mapped from and to the entities.
- AspNetCoreTemplate.Web.Infrastructure is the place for middlewares, filters, tag helpers and other web infrastructure.
- AspNetCoreTemplate.Services.Data.Tests contains xUnit.net v3 unit tests for the service layer and the mappings, using Moq and the EF Core in-memory provider.
- AspNetCoreTemplate.Web.Tests contains integration tests that host the application with
WebApplicationFactory. - Sandbox is a console application with the full dependency injection setup, handy for trying out services and running one-off tasks.
dotnet pack .\nuget.csprojPublishing a GitHub release whose tag matches the Version in nuget.csproj packs the template and publishes it to NuGet automatically (publish.yml, using nuget.org Trusted Publishing).
If you are having problems, please let us know by raising a new issue.
This project is licensed under the MIT license.





