Skip to main content

14 posts tagged with ".NET"

Runtime behaviour, GC and configuration details of .NET that only surface under real production load.

View All Tags

Test-Driven Development (TDD) in the AI-Driven Development Life Cycle (AI-DLC): A Review of the Evidence and a Proposed Practice

· 28 min read
Nguyễn Huỳnh Minh Tiến
Middle Fullstack Developer @ Utop.vn
Summary

Abstract. Test-Driven Development (TDD) is a technique that repeats three steps: write a failing test (Red), write the minimum code that makes it pass (Green), then restructure the code while keeping all tests passing (Refactor). Empirical studies from before the AI era are mixed: a case study of four industrial teams recorded a 40–90% reduction in defect density at the price of 15–35% more initial development time, while a meta-analysis of 27 studies found only a small quality improvement. In the AI-Driven Development Life Cycle (AI-DLC), where source code is increasingly generated by large language models (LLMs), tests acquire an additional function: they act as executable specifications that clarify intent and verify AI output. Studies of test-driven code generation from 2023 to 2026 report that giving tests to an LLM improves results on benchmarks, and the newest approach lets the model generate and then jointly refine both tests and code. However, the evidence comes mainly from small-scale benchmark problems, the quality of the test suite itself caps any claim of correctness, and no evaluation yet exists at the level of the whole AI-DLC.

Keywords: TDD, AI-DLC, unit testing, large language models, executable specification, refactoring.

MailKit trong .NET: gửi email SMTP và dựng HTML email template chạy đúng trên Outlook

· 16 min read
Nguyễn Huỳnh Minh Tiến
Middle Fullstack Developer @ Utop.vn
Summary

MailKit là thư viện mail mã nguồn mở cho .NET (giấy phép MIT, tác giả Jeffrey Stedfast), nói được cả SMTP, IMAP và POP3. Tài liệu chính thức của Microsoft về System.Net.Mail.SmtpClient khuyến nghị thẳng việc dùng MailKit thay thế. Phần khó của việc gửi email không nằm ở chỗ gọi SendAsync — nó nằm ở cái HTML bên trong: Outlook classic render bằng engine của Word nên không có flex hay grid, Gmail cắt thư dài quá 102KB, và một thư chỉ có HTML mà thiếu bản plain-text thì điểm spam tăng ngay.

Gửi được email và gửi được email hiển thị đúng là hai bài toán khác nhau. Bài này giải quyết cả hai: phần đầu là cơ chế MailKit, phần sau là những ràng buộc rất cũ kỹ của HTML email mà không đọc trước thì sẽ mất buổi chiều ngồi hỏi vì sao cái template đẹp trên Chrome lại vỡ tan trên Outlook.

One Vietnamese Diacritic Killed an API Call: cf-ipcity, HttpClient and the ASCII Limit

· 11 min read
Nguyễn Huỳnh Minh Tiến
Middle Fullstack Developer @ Utop.vn
Summary

Cloudflare injects cf-ipcity into incoming requests, and for visitors in Vietnam the value is Hồ Chí Minh — with diacritics, which means non-ASCII. Our .NET service forwarded every incoming header verbatim onto its outgoing calls, so that value landed in HttpClient. The surprise is that Headers.Add does not throw, and TryAddWithoutValidation returns true; everything only blows up at SendAsync with HttpRequestException: Request headers must contain only ASCII characters, and not a single byte leaves the process. The bug is neither Cloudflare's nor .NET's — it is in an application that forwards every header unconditionally.

The setting is an e-commerce loyalty platform serving roughly three million customers. I have removed the client's name and every identifying detail; what remains is the technical part.

Everything looked normal. The API was running. The Kubernetes pods were healthy. The database was fine. Requests were reaching the application. But one HTTP call to an internal service kept failing in production — and only in production.

What broke it, it turned out, was the name of the user's own city.

Forwarding Headers in ASP.NET Core: Why 'Forward Everything' Is an Architectural Bug

· 12 min read
Nguyễn Huỳnh Minh Tiến
Middle Fullstack Developer @ Utop.vn
Summary

Copying every incoming header onto an outgoing request is an anti-pattern, and it fails in three different directions: correctness (one non-ASCII value makes HttpClient throw), security (you trust and relay data the client set itself), and architecture (headers injected by infrastructure become part of your application's contract). The fix is an allowlist — an explicit list of headers permitted to pass — placed in a shared DelegatingHandler. When you write that handler, mind one trap: it does not live in the request's scope.

This post closes a three-part series that began with a production incident on an e-commerce loyalty platform of roughly three million customers, where Cloudflare's cf-ipcity: Hồ Chí Minh header broke an internal call. The first part told the story, the second explained why headers cannot carry Vietnamese. This one answers what is left: how do you rewrite that code correctly?

Can an HTTP Header Carry Vietnamese? ASCII, obs-text, and Where .NET Draws the Line

· 11 min read
Nguyễn Huỳnh Minh Tiến
Middle Fullstack Developer @ Utop.vn
Summary

Short answer: no, not if you want it to survive every layer. The HTTP specification defines header values in terms of printable ASCII, plus an obsolete branch called obs-text that allows bytes 0x80–0xFF but defines no charset for interpreting them. The consequence is that a Vietnamese string can get through partially: í lives inside Latin-1 and is representable, while ồ is not, because it is U+1ED3 — beyond 0xFF. .NET takes a decisive stance: HttpClient refuses to send any non-ASCII header value. To carry text with diacritics you must encode it, using percent-encoding, RFC 8187 or Base64.

This post branches off a production incident where the header cf-ipcity: Hồ Chí Minh, injected by Cloudflare, made HttpClient throw. There I stopped at the symptom. Here I answer the question that symptom raises: what exactly is an HTTP header allowed to contain?