Ответы об ошибках в API обычно выглядят как мусор. ProblemDetails это исправляет.
Вот типичный ответ при ошибке:
"Object reference not set to an instance of an object."
Пользы ноль.
А вот что даёт ProblemDetails:
Структурировано. Читаемо. Соответствует стандарту (RFC 9457).
В .NET 10 настройка стала удобнее.
Нужно три вещи:
→ AddProblemDetails() — регистрирует встроенные сервисы ProblemDetails
→ IExceptionHandler — современный способ обработки исключений (вместо кастомного посредника)
→ StatusCodeSelector — автоматически мапит типы исключений на HTTP-статусы
Изменение в .NET 10:
Если
Теперь обработчик сам отвечает за логирование.
Если нужно старое поведение — используй
Базовая настройка в Program.cs занимает несколько строк:
- AddProblemDetails()
- AddExceptionHandler<YourHandler>()
- UseExceptionHandler()
- UseStatusCodePages()
Без сторонних пакетов. Без самописных посредников. Всё встроено в .NET.
👉 @KodBlog
Вот типичный ответ при ошибке:
"Object reference not set to an instance of an object."
Пользы ноль.
А вот что даёт ProblemDetails:
{
"title": "Product not found",
"status": 404,
"detail": "No product with ID 42.",
"instance": "/products/42"
}Структурировано. Читаемо. Соответствует стандарту (RFC 9457).
В .NET 10 настройка стала удобнее.
Нужно три вещи:
→ AddProblemDetails() — регистрирует встроенные сервисы ProblemDetails
→ IExceptionHandler — современный способ обработки исключений (вместо кастомного посредника)
→ StatusCodeSelector — автоматически мапит типы исключений на HTTP-статусы
Изменение в .NET 10:
Если
IExceptionHandler возвращает true, посредник больше не пишет диагностику (логи, метрики) по умолчанию.Теперь обработчик сам отвечает за логирование.
Если нужно старое поведение — используй
SuppressDiagnosticsCallback.Базовая настройка в Program.cs занимает несколько строк:
- AddProblemDetails()
- AddExceptionHandler<YourHandler>()
- UseExceptionHandler()
- UseStatusCodePages()
Без сторонних пакетов. Без самописных посредников. Всё встроено в .NET.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6🤣2🍾1
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - h4ckf0r0day/obscura: The headless browser for AI agents and web scraping
The headless browser for AI agents and web scraping - h4ckf0r0day/obscura
🌚5🤩2🤣2🍾1
Как правильно структурировать фичу в формате вертикального среза?
Вот простая структура вертикального среза, которую можно смело брать на вооружение:
🔸 Объект запроса/ответа
🔸 Определение эндпоинта
🔸 Бизнес-логика
Всё, что относится к одной фиче, находится в одном месте.
Почему это круто — объяснено здесь
Если ты до сих пор не используешь подход с вертикальными срезами, скорее всего, твое приложение концептуально сложнее, чем нужно.
👉 @KodBlog
Вот простая структура вертикального среза, которую можно смело брать на вооружение:
Всё, что относится к одной фиче, находится в одном месте.
Почему это круто — объяснено здесь
Если ты до сих пор не используешь подход с вертикальными срезами, скорее всего, твое приложение концептуально сложнее, чем нужно.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤3🍾2
Это изменит работу с вашими API:
(начиная с .NET 9)
Начиная с .NET 9, Swagger больше не входит в стартовый шаблон Web API.
Microsoft убрали Swashbuckle.AspNetCore, так как он больше не поддерживается активно.
Вместо этого из коробки доступен Microsoft.AspNetCore.OpenApi для генерации OpenAPI-документов.
Но это означает, что встроенного UI для отображения эндпоинтов API больше нет.
Поэтому можно вручную вернуть Swashbuckle.
Либо использовать альтернативы, например Scalar.
Некоторые возможности Scalar:
- Встроенный API-клиент / playground
- Интерактивная документация API
- Тёмная тема из коробки
- Лёгкий деплой
- Интеграции с фреймворками
.NET мог отказаться от Swagger.
Но это может привести к более качественной документации API.
👉 @KodBlog
(начиная с .NET 9)
Начиная с .NET 9, Swagger больше не входит в стартовый шаблон Web API.
Microsoft убрали Swashbuckle.AspNetCore, так как он больше не поддерживается активно.
Вместо этого из коробки доступен Microsoft.AspNetCore.OpenApi для генерации OpenAPI-документов.
Но это означает, что встроенного UI для отображения эндпоинтов API больше нет.
Поэтому можно вручную вернуть Swashbuckle.
Либо использовать альтернативы, например Scalar.
Некоторые возможности Scalar:
- Встроенный API-клиент / playground
- Интерактивная документация API
- Тёмная тема из коробки
- Лёгкий деплой
- Интеграции с фреймворками
.NET мог отказаться от Swagger.
Но это может привести к более качественной документации API.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍4🍾2
Что не нужно на старте:
- Kubernetes
- Микросервисы
- Раздельные базы для чтения/записи
Что нужно:
- Юнит-тесты
- Конвейер CI/CD
- Здоровые кодовые привычки
- Монолитная архитектура на старте
«А что, если монолит перерастёт сам себя?»
В этом и идея. Монолит — не навсегда.
Начинаешь с простого.
Дальше эволюционируешь осознанно по мере изменения требований.
Это называется Эволюционная архитектура, и лучше всего это понимается на практике.
4 репозитория на GitHub:
1. Evolutionary Architecture by Example:
https://github.com/evolutionary-architecture/evolutionary-architecture-by-example
2. Booking to Cloud Architecture — монолит:
https://github.com/meysamhadeli/booking-monolith
3. Booking to Cloud Architecture — модульный монолит:
https://github.com/meysamhadeli/booking-modular-monolith
4. Booking to Cloud Architecture — микросервисы:
https://github.com/meysamhadeli/booking-microservices
Отсутствие простоты, а не времени — основной враг в любом проекте.
👉 @KodBlog
- Kubernetes
- Микросервисы
- Раздельные базы для чтения/записи
Что нужно:
- Юнит-тесты
- Конвейер CI/CD
- Здоровые кодовые привычки
- Монолитная архитектура на старте
«А что, если монолит перерастёт сам себя?»
В этом и идея. Монолит — не навсегда.
Начинаешь с простого.
Дальше эволюционируешь осознанно по мере изменения требований.
Это называется Эволюционная архитектура, и лучше всего это понимается на практике.
4 репозитория на GitHub:
1. Evolutionary Architecture by Example:
https://github.com/evolutionary-architecture/evolutionary-architecture-by-example
2. Booking to Cloud Architecture — монолит:
https://github.com/meysamhadeli/booking-monolith
3. Booking to Cloud Architecture — модульный монолит:
https://github.com/meysamhadeli/booking-modular-monolith
4. Booking to Cloud Architecture — микросервисы:
https://github.com/meysamhadeli/booking-microservices
Отсутствие простоты, а не времени — основной враг в любом проекте.
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - evolutionary-architecture/evolutionary-architecture-by-example: Navigate the complex landscape of .NET software architecture…
Navigate the complex landscape of .NET software architecture with our step-by-step, story-like guide. Unpack the interplay between modular monoliths, microservices, domain-driven design, and variou...
❤5🍾1
State и Strategy в C#: ключевые отличия
Сравнение паттернов State и Strategy в C# с примерами кода бок о бок, ключевыми различиями в поведении и рекомендациями, когда какой использовать.
Читать статью здесь: https://bgh.st/3cce96
👉 @KodBlog
Сравнение паттернов State и Strategy в C# с примерами кода бок о бок, ключевыми различиями в поведении и рекомендациями, когда какой использовать.
Читать статью здесь: https://bgh.st/3cce96
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🍾1
Как использовать enum в C#: объявление, значения и лучшие практики
Разбор использования перечислений в C# с нуля: объявление, задание значений, приведение типов, сравнение, перебор и практики, которые стоит применять в продакшене.
Читать статью здесь: https://bgh.st/djmghy
👉 @KodBlog
Разбор использования перечислений в C# с нуля: объявление, задание значений, приведение типов, сравнение, перебор и практики, которые стоит применять в продакшене.
Читать статью здесь: https://bgh.st/djmghy
Please open Telegram to view this post
VIEW IN TELEGRAM
Dev Leader
How to Use Enum in C#: Declaration, Values, and Best Practices
Learn how to use enum in C# from scratch. Covers declaring enums, assigning values, casting, comparing, iterating, and the best practices every C# developer sho
👍6🍾1
required string и string? в EF Core — это не просто разница в синтаксисе, это семантика модели и контракт с базой.
- required string → обязательная инициализация в модели + колонка NOT NULL в БД
- string? → допускает null + колонка с NULL в БД
EF Core использует nullable-аннотации и контекст компилятора, чтобы выводить ограничение целостности схемы. Это напрямую влияет на миграции и поведение трекинга изменений.
Важно: доменную модель нужно задавать явно, а бизнес-ограничения дублировать через Fluent API, чтобы исключить расхождения между кодом и схемой базы.
👉 @KodBlog
- required string → обязательная инициализация в модели + колонка NOT NULL в БД
- string? → допускает null + колонка с NULL в БД
EF Core использует nullable-аннотации и контекст компилятора, чтобы выводить ограничение целостности схемы. Это напрямую влияет на миграции и поведение трекинга изменений.
Важно: доменную модель нужно задавать явно, а бизнес-ограничения дублировать через Fluent API, чтобы исключить расхождения между кодом и схемой базы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🍾3
Node.js аддоны… на C#? Да.
Native AOT позволяет собирать нативные shared-библиотеки, которые подключаются напрямую через N-API — без node-gyp, без установки Python, без C++-обвязок.
Получается чистая межъязыковая связка через:
* UnmanagedCallersOnly
* LibraryImport
* Span<T>
* zero-alloc UTF-8 маршалинг
Идея — минимальный оверхед между Node.js и нативным кодом при сохранении управляемого кода на C#.
Блог: https://ift.tt/2mz8B1E
👉 @KodBlog
Native AOT позволяет собирать нативные shared-библиотеки, которые подключаются напрямую через N-API — без node-gyp, без установки Python, без C++-обвязок.
Получается чистая межъязыковая связка через:
* UnmanagedCallersOnly
* LibraryImport
* Span<T>
* zero-alloc UTF-8 маршалинг
Идея — минимальный оверхед между Node.js и нативным кодом при сохранении управляемого кода на C#.
Блог: https://ift.tt/2mz8B1E
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3🍾2
Идемпотентность — одна из тех вещей, о которых не думаешь, пока один и тот же запрос не выполняется дважды.
Запрос может упасть, превысить таймаут или быть повторён клиентом. С точки зрения клиента это выглядит нормально. На стороне сервера в этот момент одно и то же действие может выполниться повторно. Если речь про создание заказа или проведение платежа, повторное выполнение приводит к неконсистентному состоянию.
Для этого используется идемпотентность.
Операция считается идемпотентной, если многократное выполнение даёт тот же результат, что и однократное. При одном или нескольких одинаковых запросах итоговое состояние системы не должно меняться.
Один из стандартных способов реализации — идемпотентный ключ. Клиент отправляет уникальный ключ вместе с запросом. Сервер сохраняет этот ключ и результат выполнения. При первом запросе он обрабатывает логику. При повторном запросе с тем же ключом обработка не запускается заново, возвращается сохранённый результат.
Это важно из-за повторов запросов, которые возникают регулярно. Сеть нестабильна, сервисы отвечают с задержками, клиенты автоматически делают ретраи.
Повторы останавливать не нужно. Нужно исключить повторное выполнение одной и той же операции.
👉 @KodBlog
Запрос может упасть, превысить таймаут или быть повторён клиентом. С точки зрения клиента это выглядит нормально. На стороне сервера в этот момент одно и то же действие может выполниться повторно. Если речь про создание заказа или проведение платежа, повторное выполнение приводит к неконсистентному состоянию.
Для этого используется идемпотентность.
Операция считается идемпотентной, если многократное выполнение даёт тот же результат, что и однократное. При одном или нескольких одинаковых запросах итоговое состояние системы не должно меняться.
Один из стандартных способов реализации — идемпотентный ключ. Клиент отправляет уникальный ключ вместе с запросом. Сервер сохраняет этот ключ и результат выполнения. При первом запросе он обрабатывает логику. При повторном запросе с тем же ключом обработка не запускается заново, возвращается сохранённый результат.
Это важно из-за повторов запросов, которые возникают регулярно. Сеть нестабильна, сервисы отвечают с задержками, клиенты автоматически делают ретраи.
Повторы останавливать не нужно. Нужно исключить повторное выполнение одной и той же операции.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤2🍾2
Глоббинг в C#
Несколько дней назад я сделал резервную копию документов в OneDrive и не заметил, что после завершения все файлы фактически были перенесены туда.
Далее я откатил резервную копию (20 ГБ), и во многих случаях процесс создал дубликаты.
Знание глоббинга позволило написать код для удаления дубликатов (5000+ файлов) и обхода отдельных папок.
Рекомендую уделить время изучению глоббинга.
Код: https://github.com/karenpayneoregon/learning-topics/tree/master/GlobbingApp1
👉 @KodBlog
Несколько дней назад я сделал резервную копию документов в OneDrive и не заметил, что после завершения все файлы фактически были перенесены туда.
Далее я откатил резервную копию (20 ГБ), и во многих случаях процесс создал дубликаты.
Знание глоббинга позволило написать код для удаления дубликатов (5000+ файлов) и обхода отдельных папок.
Рекомендую уделить время изучению глоббинга.
Код: https://github.com/karenpayneoregon/learning-topics/tree/master/GlobbingApp1
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔3❤1👍1🍾1
CQS и CQRS — это одно и то же?
Не совсем.
CQS (разделение команд и запросов) — это принцип:
команды изменяют состояние, ничего не возвращают
запросы возвращают данные, не изменяют состояние
он применяется на уровне методов и относится к намерению, а не к жёстким правилам.
CQRS строится на этой идее уже на архитектурном уровне. Он разделяет модели чтения и записи ради масштабируемости, ясности и гибкости.
Хочешь посмотреть, как реализовать CQRS на практике?
Вот как: читать
Большинство приложений уже делают это, даже без прямого упоминания CQRS.
👉 @KodBlog
Не совсем.
CQS (разделение команд и запросов) — это принцип:
команды изменяют состояние, ничего не возвращают
запросы возвращают данные, не изменяют состояние
он применяется на уровне методов и относится к намерению, а не к жёстким правилам.
CQRS строится на этой идее уже на архитектурном уровне. Он разделяет модели чтения и записи ради масштабируемости, ясности и гибкости.
Хочешь посмотреть, как реализовать CQRS на практике?
Вот как: читать
Большинство приложений уже делают это, даже без прямого упоминания CQRS.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🍾2
azure-alphabet.pdf
2.5 MB
Хочешь уверенно работать с Azure как бэкенд-разработчик на .NET?
Кристи потратил 20+ часов, чтобы собрать «Алфавит Azure для тебя:
• Разобраться в 26 ключевых сервисах и концепциях Azure (без воды)
• Понимать, что делает каждый сервис, когда его использовать и зачем он нужен
• Стартовать путь разработки в Azure
Я его скачал и делюсь с вами!❤️ ❤️
👉 @KodBlog
Кристи потратил 20+ часов, чтобы собрать «Алфавит Azure для тебя:
• Разобраться в 26 ключевых сервисах и концепциях Azure (без воды)
• Понимать, что делает каждый сервис, когда его использовать и зачем он нужен
• Стартовать путь разработки в Azure
Я его скачал и делюсь с вами!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🍾1
Самый простой способ генерировать PDF-отчёты
Первый выбор — конвертация HTML → PDF.
В большинстве коммерческих проектов используется IronPDF.
Нужен бесплатный вариант:
- Puppeteer Sharp
- headless-версия Chrome
Но ключевая идея важнее конкретного инструмента.
Если есть HTML-шаблон, появляется полный контроль над форматированием.
Можно использовать современный CSS для стилизации HTML-разметки.
Общая схема реализации:
1. MVC-представления и Razor-синтаксис
2. Рендер динамического HTML-контента
3. Передача HTML в PDF-рендерер
Такой подход использовался в нескольких проектах с хорошими результатами.
Нужен пример реализации гибкой PDF-генерации?
Гайд: тут
👉 @KodBlog
Первый выбор — конвертация HTML → PDF.
В большинстве коммерческих проектов используется IronPDF.
Нужен бесплатный вариант:
- Puppeteer Sharp
- headless-версия Chrome
Но ключевая идея важнее конкретного инструмента.
Если есть HTML-шаблон, появляется полный контроль над форматированием.
Можно использовать современный CSS для стилизации HTML-разметки.
Общая схема реализации:
1. MVC-представления и Razor-синтаксис
2. Рендер динамического HTML-контента
3. Передача HTML в PDF-рендерер
Такой подход использовался в нескольких проектах с хорошими результатами.
Нужен пример реализации гибкой PDF-генерации?
Гайд: тут
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🍾1
Совет по LINQ:
Вызывай
Почему?
> В первом случае всё загружается в память до фильтрации
> Во втором — фильтрация происходит на источнике, что лучше для БД или больших коллекций
> Особенно важно при работе с EF Core или API, использующих
🎉 🎉
👉 @KodBlog
Вызывай
ToList() после фильтрации, а не до.Почему?
> В первом случае всё загружается в память до фильтрации
> Во втором — фильтрация происходит на источнике, что лучше для БД или больших коллекций
> Особенно важно при работе с EF Core или API, использующих
IQueryablePlease open Telegram to view this post
VIEW IN TELEGRAM
🥴12😁6🤯3🍾1
Что такое Queue<T>?
Queue<T> — это коллекция в C# с принципом FIFO (первым пришёл — первым ушёл).
То есть первый добавленный элемент будет извлечён первым.
Когда использовать?
> Планирование задач
> Очереди на печать
> Обработка сообщений
> Поиск в ширину (BFS) в графах
Пример прикрепил, с вас лайк❤️
👉 @KodBlog
Queue<T> — это коллекция в C# с принципом FIFO (первым пришёл — первым ушёл).
То есть первый добавленный элемент будет извлечён первым.
Когда использовать?
> Планирование задач
> Очереди на печать
> Обработка сообщений
> Поиск в ширину (BFS) в графах
Пример прикрепил, с вас лайк
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤1🍾1💋1
Ubuntu 26.04 поставляется с .NET 10 из коробки: новые контейнерные образы -resolute, готовность к Linux 7.0, постквантовая криптография и чистая поддержка cgroup v2.
Native AOT работает быстро: компактные бинарники + ~3 мс запуска. .NET 8/9 доступны через PPA с бэкпортами.
👉 @KodBlog
Native AOT работает быстро: компактные бинарники + ~3 мс запуска. .NET 8/9 доступны через PPA с бэкпортами.
Please open Telegram to view this post
VIEW IN TELEGRAM
Microsoft News
What’s new for .NET in Ubuntu 26.04
Ubuntu 26.04 (Resolute Raccoon) ships today with .NET 10. Here's how to install .NET 10 from the archive, use the new -resolute container tags, build Native AOT apps, and install .NET 8 and 9 from the dotnet-backports PPA.
👍10🔥5🍾4
EF Core имеет заметную просадку производительности при использовании колонок-идентификаторов.
Как это обычно решают ?
В большинстве проектов для первичных ключей используют либо автоинкремент из базы данных, либо GUID.
При вызове метода SaveChanges EF Core возвращает сгенерированное значение идентификатора, которое сформировала база.
В SQL Server EF Core применяет оператор MERGE с предложением OUTPUT, чтобы объединять множественные вставки в один запрос и возвращать новые значения идентификаторов.
Подход рабочий, но у него есть жёсткие ограничения:
- лимит в 2100 параметров: SQL Server допускает максимум 2100 параметров на один запрос. При 14 колонках это примерно 100–200 строк за одну партию. Для 10 000 строк Product это приводит к множеству обходных вызовов к базе.
- стоимость привязки параметров: каждый параметр создаётся, привязывается и отправляется по сети. Для больших объёмов это десятки тысяч параметров.
- нагрузка на отслеживание изменений: после каждой партии EF Core обновляет трекер изменений и присваивает возвращённые идентификаторы объектам.
Это заметно ухудшает производительность при массовых вставках.
При этом часто нет необходимости возвращать идентификаторы сразу после вставки.
Заявленный результат:
10 000 записей Product.
EF Core SaveChanges с возвратом идентификаторов: ~7000 мс.
Оптимизированная вставка: ~200 мс.
👉 @KodBlog
Как это обычно решают ?
В большинстве проектов для первичных ключей используют либо автоинкремент из базы данных, либо GUID.
При вызове метода SaveChanges EF Core возвращает сгенерированное значение идентификатора, которое сформировала база.
В SQL Server EF Core применяет оператор MERGE с предложением OUTPUT, чтобы объединять множественные вставки в один запрос и возвращать новые значения идентификаторов.
Подход рабочий, но у него есть жёсткие ограничения:
- лимит в 2100 параметров: SQL Server допускает максимум 2100 параметров на один запрос. При 14 колонках это примерно 100–200 строк за одну партию. Для 10 000 строк Product это приводит к множеству обходных вызовов к базе.
- стоимость привязки параметров: каждый параметр создаётся, привязывается и отправляется по сети. Для больших объёмов это десятки тысяч параметров.
- нагрузка на отслеживание изменений: после каждой партии EF Core обновляет трекер изменений и присваивает возвращённые идентификаторы объектам.
Это заметно ухудшает производительность при массовых вставках.
При этом часто нет необходимости возвращать идентификаторы сразу после вставки.
Заявленный результат:
10 000 записей Product.
EF Core SaveChanges с возвратом идентификаторов: ~7000 мс.
Оптимизированная вставка: ~200 мс.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤3🍾1
Использование нативной компиляции AOT в .NET для сборки DLL под Windows WinAPI: читать
Я пропустил один момент с AOT: через него можно собирать нативные библиотеки динамической компоновки. Проверил на практике — получаются небольшие стандартные DLL в стиле WinAPI, которые можно вызывать из легаси-приложений.
👉 @KodBlog
Я пропустил один момент с AOT: через него можно собирать нативные библиотеки динамической компоновки. Проверил на практике — получаются небольшие стандартные DLL в стиле WinAPI, которые можно вызывать из легаси-приложений.
Please open Telegram to view this post
VIEW IN TELEGRAM
West-Wind
Using .NET Native AOT to build Windows WinAPI Dlls
Did you know that you can use .NET AOT compilation to create native Windows DLLs to potentially replace traditional C/C++ compiled DLLs? It's now possible to build completely native DLLs that can be called from external applications and legacy applications…
👍5🍾2