Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
When Server-Side Rendering? Choosing Between MVC, Razor Pages, Blazor SSR and an Angular SPA
Server-side rendering wins for SEO, fast first loads, form-heavy internal apps and small teams; an SPA fits heavy interactivity and APIs with many clients. We build the same list with an MVC controller and a Razor Page, trace the request lifecycle in the framework logs, compare a 474-byte Angular shell with 2.5 KB of ready HTML and discuss where Blazor SSR fits.
The ASP.NET Core MVC Pattern in Practice: Controllers, Views, ViewModels and Conventional Routing
In ASP.NET Core MVC a controller derives from Controller, finds its view by name in Views/<Controller> and Shared, and gets page data through a type-safe ViewModel instead of ViewBag. On Bookstore we look at the dotnet new mvc layout, conventional routing, RedirectToAction, an Admin area and a real bug where swapping route order makes links silently point to the wrong address.
Razor Syntax and Layouts: @ Expressions, HTML Encoding, _Layout, Sections, _ViewStart and _ViewImports
Razor HTML-encodes every value written with @ by default; that shuts out XSS but also turns non-ASCII letters such as Turkish ı into entities like ı, fixed with WebEncoderOptions. With real output we cover implicit vs explicit expressions, the danger of Html.Raw and of embedding '@Model' in JavaScript, Json.Serialize, sections, the _ViewStart/_ViewImports hierarchy and the lost-section error in nested layouts.
Partial Views, View Components and Razor Components: Reusing UI Pieces in MVC
Use a partial view for repeated HTML whose data the caller already has, a view component for a fragment on every page that fetches its own data, and a Razor component as a bridge to Blazor or for a piece that will become interactive. We measure queries jumping from 3 to 7 when a partial calls DbContext, build a cart summary view component, return ViewComponent() from a controller and try the <component> tag helper's Static and ServerPrerendered modes.
ASP.NET Core Tag Helpers: Built-in Tag Helpers and Writing Your Own
A tag helper is a C# class, bound at compile time, that processes an HTML tag in Razor on the server; a single asp-for produces id, name, label, input type and data-val attributes. We look at the real output of the built-in anchor, form, input, select, environment and cache tag helpers, the difference from HTML Helpers and the build break from a missing @ on an enum attribute, then write our own <status-badge> and a permission-aware <secure-link>.
Forms in MVC and Razor Pages: Model Binding, Post-Redirect-Get, Antiforgery and Overposting
In MVC controllers the form tag helper produces an antiforgery token but nothing validates it: a tokenless curl request saved a book until AutoValidateAntiforgeryTokenAttribute turned it into a 400. With real requests we cover Post-Redirect-Get and TempData, sending the token in a fetch header, binding collections, nested objects, checkboxes and enums plus the index gap, overposting that set stock to 999 through an entity, and how [Bind] wipes data on updates.
Server-Side and Client-Side Validation: DataAnnotations, ModelState, Unobtrusive Validation and Custom Attributes
Validation in MVC has two layers: DataAnnotations and ModelState are mandatory on the server, while jQuery Unobtrusive Validation driven by data-val-* is only user experience. We try IValidatableObject, AddModelError, [Remote], a custom attribute with IClientModelValidator and Turkish messages in a real browser, and show how under a Turkish culture a price of "1.5" is silently saved as 15 and how type="number" with __Invariant fixes it.
Razor Pages: PageModel, Handler Methods, Page Routing and When to Use It Instead of MVC
With @page a Razor file becomes an endpoint, and PageModel handlers such as OnGetAsync and OnPostDeleteAsync replace actions. We rewrite Bookstore's admin CRUD and examine SupportsGet, TempData, AuthorizeFolder and page filters, why an unmatched handler ends in a 500, and the file layout versus MVC, with real output.
Static Assets and UI Plumbing: MapStaticAssets, Fingerprinting, CSS Isolation and Client Libraries
MapStaticAssets discovers files at build time, compresses them with gzip/Brotli and gives fingerprinted URLs a one-year immutable cache. We measure it with real headers and show why MapControllerRoute(...).WithStaticAssets() in the .NET 10 MVC template does nothing and how to fix it, the tag helper trap in CSS isolation, and using LibMan.
Localization in MVC and Razor Pages: IStringLocalizer, IViewLocalizer, Request Culture and the Turkish "i" Pitfall
UseRequestLocalization picks a culture per request from the query string, cookie, Accept-Language or the URL; .resx files, IViewLocalizer and DataAnnotations messages are translated with it. We make Bookstore's catalog TR/EN and show the tr vs tr-TR gap, 25,5 becoming 255 in the query string, the "C" format and the Turkish i pitfall with real output.
Razor Pages with htmx: Interactive UI Without an SPA, Partial Responses and Antiforgery
With htmx, Razor Pages handlers return the full page or just a partial depending on the HX-Request header; live search, infinite scroll and inline editing work without JSON or an SPA. We carry the antiforgery token with hx-headers and show the Vary and history restore pitfalls, htmx 2's 4xx behavior and htmx 4 differences with real requests.
Migrating from ASP.NET MVC 5 to ASP.NET Core MVC: Equivalents of Global.asax, Web.config, HtmlHelper and Bundling
Moving from MVC 5 to ASP.NET Core turns Global.asax into Program.cs, Web.config into Options, HttpModules into middleware, child actions into view components and bundling into MapStaticAssets; a large app moves piece by piece behind a YARP fallback. We show real build errors for @helper and @Html.Action, the CS0104 trap with System.Web adapters and what replaced Upgrade Assistant.