Guides.NET

Blazor Web App with EF Core, Identity, and SQLite

Create an ASP.NET Core Blazor app with Razor components, EF Core on SQLite, ASP.NET Identity, SignalR, Serilog, and xUnit using Better Fullstack.

Updated October 6, 2026blazoref-coresqlitedotnet

Use this stack when one .NET project should serve both the UI, as Razor components, and a small JSON API, with a file-based SQLite database for local work.

npm create better-fullstack@latest my-blazor-app -- \  --ecosystem dotnet \  --dotnet-web-framework aspnet-blazor \  --dotnet-orm ef-core \  --dotnet-auth aspnet-identity \  --dotnet-api minimal-api \  --dotnet-testing xunit \  --dotnet-job-queue none \  --dotnet-realtime signalr \  --dotnet-observability serilog \  --dotnet-validation none \  --dotnet-caching none \  --dotnet-deploy docker \  --dotnet-libraries none \  --database sqlite

What this creates

  • An ASP.NET Core app that registers Razor components with interactive server rendering.
  • App.razor, Routes.razor, and a Home.razor page at /.
  • EF Core with the SQLite provider and an AppDbContext holding a Todos set.
  • ASP.NET Core Identity registered against that context.
  • GET /api/status, GET /api/todos, and POST /api/todos beside the components.
  • A SignalR hub at /hubs/updates, Serilog console logging, an xUnit project, and a Dockerfile.

Generated shape

txt
my-blazor-app/
├── my_blazor_app.csproj
├── my_blazor_app.http
├── Program.cs
├── appsettings.json
├── appsettings.Development.json
├── Dockerfile
├── Components/
│   ├── App.razor
│   ├── Routes.razor
│   ├── _Imports.razor
│   └── Pages/
│       └── Home.razor
└── my_blazor_app.Tests/
    ├── my_blazor_app.Tests.csproj
    └── ApiTests.cs

The project name becomes my_blazor_app, and _Imports.razor imports my_blazor_app.Components.

Prerequisites

  • .NET SDK 10 or newer.
  • No database server. appsettings.json sets Data Source=my_blazor_app.db, a SQLite file next to the app.

Run and verify

bash
cd my-blazor-app
dotnet restore
dotnet run

Open the URL ASP.NET Core prints. / renders Home.razor, which links to /api/status.

bash
dotnet test my_blazor_app.Tests/my_blazor_app.Tests.csproj

No solution file is generated, so name the test project. The generated test requests / through WebApplicationFactory<Program> and expects a 200 response.

Create the database before using the todo endpoints

Program.cs registers AppDbContext but never calls Migrate() or EnsureCreated(), so the SQLite file has no Todos table until you create it. Microsoft.EntityFrameworkCore.Design is already referenced:

bash
dotnet tool install --global dotnet-ef
dotnet ef migrations add InitialCreate
dotnet ef database update

Interactivity

Program.cs registers the interactive server render mode, and App.razor includes a <script src="_framework/blazor.web.js"> tag. The generated app does not serve that script: a request for /_framework/blazor.web.js returns 404, so the Blazor client never starts in the browser. Pages render as static server-side HTML, and a component marked @rendermode RenderMode.InteractiveServer shows its prerendered markup but does not run @onclick or other event handlers.

Representative snippets

Components and API endpoints share one pipeline:

csharp
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

app.MapGet("/api/todos", async (AppDbContext db) =>
{
    return Results.Ok(await db.Todos.OrderBy(todo => todo.Id).ToListAsync());
});

app.MapHub<UpdatesHub>("/hubs/updates");
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

The hub broadcasts any message it receives to every connected client:

csharp
public sealed class UpdatesHub : Hub
{
    public Task Broadcast(string message) => Clients.All.SendAsync("update", message);
}

When to choose it

Choose Blazor when the team wants C# end to end and a server-rendered UI without a separate JavaScript build. Choose the ASP.NET Core and EF Core guide for an API-only service on PostgreSQL.

Compatibility notes

  • --dotnet-web-framework aspnet-blazor is the server-side Blazor app. The separate --dotnet-frontend option (blazor-webassembly, blazor-web-app) adds a .NET frontend part in composed projects.
  • --dotnet-auth aspnet-identity calls AddIdentityCore<IdentityUser>().AddEntityFrameworkStores<AppDbContext>(), but AppDbContext derives from DbContext, not IdentityDbContext. Change the base class and add a migration before resolving the user store. No login pages are generated.
  • --database postgres switches EF Core to the Npgsql provider.

Deployment notes

The Dockerfile publishes with the .NET 10 SDK and runs on the ASP.NET 10 runtime image on port 8080. The SQLite file lives inside the container's /app directory, so it is lost when the container is replaced. Mount a volume and point ConnectionStrings__DefaultConnection at it, or switch to PostgreSQL for hosted environments.

Troubleshooting

SymptomCheck
SQLite Error 1: 'no such table: Todos'Create and apply an EF Core migration.
Button clicks on a page do nothing/_framework/blazor.web.js returns 404 in the generated app, so the Blazor client does not start.
Identity user store fails to resolveAppDbContext must derive from IdentityDbContext and have a migration.
The .http file's GET / returns HTML/ is the Blazor page here; use /api/status for the JSON status response.
localhost:5000 returns 403 on macOSAirPlay Receiver also listens on port 5000. Start the app with another port, for example PORT=5080 dotnet run.
The generated README mentions TypeScript and npmThe .NET scaffold currently writes the TypeScript README. Use the commands in this guide.

Next steps

GitHub Sponsors