ASP.NET Core 8 MVC blog with Identity, EF Core, SQL Server, Bootstrap 5, Markdig, and HtmlSanitizer.
- Posts — Create, edit, delete; Markdown content; optional excerpt, cover image; draft/publish
- Comments — Add, edit, delete (owner only); shown on each post
- Auth — Email/password registration + Google OAuth;
DisplayNamefor authors - Slug-based URLs — Unique, SEO-friendly URLs for posts
- Reading time — Estimated from word count (200 wpm)
- Pagination — 10 posts per page on home
- Markdown — Markdig for rendering; HtmlSanitizer for safe HTML output
| Component | Technology |
|---|---|
| Framework | ASP.NET Core 8 MVC |
| Data | Entity Framework Core 8, SQL Server |
| Auth | ASP.NET Core Identity (email/password, Google OAuth) |
| UI | Bootstrap 5.3 (CDN) |
| Markdown | Markdig |
| HTML sanitization | HtmlSanitizer (Ganss.Xss) |
- .NET 8 SDK
- SQL Server or LocalDB
-
Connection string
SetConnectionStrings:DefaultConnectioninBlog2/appsettings.jsonor User Secrets. Example:"ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=Blog2;Trusted_Connection=True;MultipleActiveResultSets=true" }
-
Database
In Development the app applies migrations on startup. Otherwise:cd Blog2 dotnet ef database update -
Google OAuth (optional)
SetAuthentication:Google:ClientIdandAuthentication:Google:ClientSecretinappsettings.jsonor User Secrets. If unset or using placeholderYOUR_GOOGLE_CLIENT_ID, Google sign-in is not registered. -
Run
cd Blog2 dotnet run
Blog2/
├── Blog2/ # Main web project
│ ├── Controllers/ # Home, Account, Post, Comment
│ ├── Data/ # ApplicationDbContext
│ ├── Extensions/ # IdentityExtensions
│ ├── Migrations/ # EF Core migrations
│ ├── Models/ # Post, Comment, ApplicationUser
│ ├── Services/ # PostService, CommentService, SlugService, MarkdownService
│ ├── ViewModels/ # View models for views
│ ├── Views/ # Razor views
│ └── wwwroot/css/ # site.css (custom styles)
├── Blog2.sln
└── README.md
| Method | Route | Description |
|---|---|---|
| GET | / |
Published posts (paginated, ?page=) |
| GET | /blog/{slug} |
Single post and comments |
| GET | /login, POST /login |
Sign in (email/password) |
| POST | /logout |
Sign out |
| GET | /register, POST /register |
Register |
| GET, POST | /external-login |
External auth (provider=Google) |
| GET | /external-login-callback |
OAuth callback |
| GET | /post/create, POST /post/create |
New post (auth) |
| GET | /post/edit/{id}, POST /post/edit/{id} |
Edit post (owner only) |
| POST | /post/delete/{id} |
Delete post (owner only) |
| POST | /comment/add |
Add comment (auth) |
| POST | /comment/edit/{id} |
Edit comment (owner only) |
| POST | /comment/delete/{id} |
Delete comment (owner only) |
| GET | /Home/Error |
Error page (non-dev) |