C# Portal | Программирование
13.9K subscribers
1.15K photos
126 videos
29 files
928 links
Присоединяйтесь к нашему каналу и погрузитесь в мир для C#-разработчика

Сотрудничество, реклама: @devmangx

Менеджер: @Spiral_Yuri

РКН: https://clck.ru/3FocB6
Download Telegram
Чувак сделал намеренно уязвимое dotnet приложение 👀

Многие советы по безопасности в .NET остаются слишком абстрактными, пока ты не увидишь баг прямо в коде.

Поэтому этот проект, где всё намеренно сделано неправильно. Это намеренно уязвимое .NET-приложение, в котором собрано более 50 распространённых реальных ошибок, которые могут проскочить в обычный бизнес-код.

Ссылка - https://github.com/AlexGoOn/the-most-vulnerable-dotnet-app

Некоторые из включённых вещей:

Инъекционные атаки (SQL, command, template, LDAP, XML, logs)
Cross-Site Scripting (stored, reflected, в атрибутах, в SVG)
Небезопасная загрузка файлов (path traversal, Zip Slip, произвольная запись файлов)
Проблемы с криптографией (hashing, ECB, предсказуемый random)
Сериализация (XXE, XML bomb, binary, YAML)


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍3🤔1
8 лет опыта научили меня, что кидать исключения дорого.

Поэтому я начал делать так:

Раньше я бросал исключения, когда:

- пользователь не найден
- переданы невалидные параметры
- результат метода null

И всю логику обработки я выносил на вызывающую сторону, которая теперь должна знать, какое именно исключение прилетело и как на него реагировать.

Но реальность такая: исключения отлично подходят для ошибок, с которыми ты не знаешь, что делать.

К счастью, большинство ошибок можно обработать, и вот как:

Паттерн Result.

Вместо того чтобы кидать исключения, методы возвращают объект Result, который явно показывает успех/провал и содержит либо успешное значение, либо информацию об ошибке.

Ещё стоит подумать о своей кастомной Error-модели, где ты будешь нормально, описательно расписывать все типы ошибок и использовать её внутри Result.

В своих проектах я люблю иметь две версии: не-дженерик (для void-методов) и дженерик (обёртка для конкретного результата). Так намерение кода читается сразу и без гаданий.

Я предпочитаю свою реализацию, но если тебе это не заходит, можно взять готовые библиотеки, например FluentResults.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🥴129👍7🤔3
Оператор LINQ FullJoin() появится в dotnet 11?

https://github.com/dotnet/runtime/issues/124787

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Когда стоит использовать паттерн Outbox?

Паттерн Outbox хранит исходящие сообщения в таблице базы данных, а потом фоновый процесс публикует их в брокер сообщений.

Зачем вообще заморачиваться?

Потому что в распределённых системах всё ломается: падают downstream-сервисы, отваливается сеть и т.д.

Если публиковать сообщения прямо внутри обработки запроса, есть риск их потерять, когда что-то пойдёт не так.

Outbox опирается на атомарные транзакции БД:

Сохранить состояние приложения
Сохранить сообщение в Outbox (либо оба шага, либо ни один)

А дальше фоновый процесс уже безопасно доставляет сообщение.

Важно помнить: Outbox решает надёжность публикации.

А на стороне консюмера всё равно нужна идемпотентность, чтобы нормально переживать ретраи.

Хочешь глубже?

Полная статья тут: https://milanjovanovic.tech/blog/implementing-the-outbox-pattern

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍43
C# records как value objects?

Records по задумке иммутабельные, и у них структурное сравнение (равенство по значениям).

А именно это обычно и нужно от value object.

Плюс сверху получаем pattern matching, короткий синтаксис и deconstruction.

public class Booking
{
public Address Address { get; init; }

public DateRange Period { get; init; }
}

public record Address(
string Street,
string City,
string State,
string Country,
string ZipCode);


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9😁1
Каждый раз, когда ты пишешь очередной новенький List<>,
ты на самом деле принимаешь решение по производительности.

Большинство разработчиков воспринимают структуры данных как контейнеры. А это не так. Это контракты по перформансу.

Вот как полезно думать о самых популярных структурах в .NET, по-практически:

Array
Бери, когда размер фиксирован и нужен честный O(1) доступ по индексу.
Самый быстрый вариант. Нет ресайза. Нет сюрпризов.

List<T>
Отличный дефолтный выбор, пока не упираешься в ресайз.
Под капотом при росте capacity копируется весь массив.

Dictionary<TKey, TValue>
В среднем O(1) на поиск.
Но плохое распределение хеша -> коллизии -> деградация скорости.

Stack<T>
Идеален для рекурсии, парсинга, undo/redo.
Но глубокая рекурсия? Привет, StackOverflow (сайт) или stack overflow (ошибка).

Queue<T>
FIFO. Отлично для фоновой обработки и пайплайнов.
Типа планирования задач, обработки сообщений.

Tree / Graph
Используются чаще, чем кажется:
роутинг, индексация, разрешение зависимостей, поиск.

Смысл не в том, чтобы заучивать Big-O.

Смысл понимать:

- как выделяется память
- как работает ресайз
- что происходит под нагрузкой
- на какой компромисс ты соглашаешься

Хорошие инженеры пишут код, который работает.

Классные инженеры знают, почему он работает и в какой момент перестанет.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍76
GitHub Copilot SDK для .NET: полное руководство разработчика

Разберись с GitHub Copilot SDK для .NET в этом полном гайде для разработчиков. Собирай кастомных AI-агентов на базе CopilotClient и CopilotSession, со стримингом, tools и поддержкой нескольких моделей в C#.

Статья здесь

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
5
Пример Vertical Slice Architecture в ASP.NET

Я один такой, кто складывает вообще всё в один файл?

С этим работать просто мечта 😍

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🤯7🥴43🔥1
Паттерн Builder в реальном мире на C#: полная реализация

Посмотрите, как паттерн Builder работает на практике, на полноценном реальном примере на C#. Пошаговая реализация конфигурационной системы, которая показывает поэтапную сборку объекта.

Статья здесь

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
5
Как применять EF-миграции в продакшене?

Самый распространенный подход: накатывать их через CLI командой Update-Database.

Но я предпочитаю генерировать для миграций SQL-скрипты. Так можно проверить SQL-выражения и убедиться, что все ок.

Еще лучше, если у вас есть DBA.

CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
"MigrationId" character varying(150) NOT NULL,
"ProductVersion" character varying(32) NOT NULL,
CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId")
);

START TRANSACTION;

CREATE TABLE "Products" (
"Id" integer GENERATED BY DEFAULT AS IDENTITY,
"Name" character varying(100) NOT NULL,
"Description" character varying(1000),
"Price" numeric(18,2) NOT NULL,
CONSTRAINT "PK_Products" PRIMARY KEY ("Id"),
CONSTRAINT "CK_Price_NotNegative" CHECK (Price > 0)
);

CREATE UNIQUE INDEX "IX_Products_Name" ON "Products" ("Name");

INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20240516095344_Create_Database', '8.0.5');

COMMIT;


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🥴9🤔1
Отсутствие нейминг-конвенций в коде меня дико бесит.

Можешь с этим что-нибудь сделать?

Только без истерик в PR (так не надо).

Если вдруг не знал: довольно легко написать архитектурные тесты, которые проверяют нейминг-конвенции в твоём коде.

Вот пример для именования command handler-ов.

[Fact]
public void CommandHandler_ShouldHave_NameEndingWith_CommandHandler()
{
Types.InAssembly(ApplicationAssembly)
.That()
.ImplementInterface(typeof(ICommandHandler<>))
.Or()
.ImplementInterface(typeof(ICommandHandler<,>))
.Should()
.HaveNameEndingWith("CommandHandler")
.GetResult()
.ShouldBeSuccessful();
}


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🥴76👍4🤔1
Кто-то собрал вообще все туториалы в стиле сделай это с нуля со всего интернета в одном месте.

Называется build-your-own-x, и это самый популярный репозиторий в истории GitHub по числу звёзд.

466 000 звёзд. Больше, чем у React. Больше, чем у TensorFlow. Больше, чем у любого инструмента, который когда-либо делали.

И это не код. Это кураторская подборка пошаговых туториалов, которые учат пересобирать с нуля технологии, которыми ты пользуешься каждый день. С нуля.

Ричард Фейнман сказал: "Чего я не могу создать, того я не понимаю."

https://github.com/codecrafters-io/build-your-own-x

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍113🤔1
Как сделать ваши API-эндпоинты быстрее в 426 раз:
(подсказка: это не кэш)

Когда разработчики видят медленные API, первая реакция часто такая: лечить тормоза неправильным лекарством, кэшем.

Но это решение держится на ключевом заблуждении:

будто кэширование может исправить тормоза, вызванные плохими запросами к базе данных.

Поэтому первый шаг к более масштабируемым системам это починить именно запросы.

Чтобы это показать, проведем небольшой эксперимент.

Я сделал небольшой веб-API с одним эндпоинтом /products.

До оптимизации:

- Количество обработанных запросов: 378
- Среднее запросов/сек: 11.01
- Средняя длительность запроса: примерно 4 секунды

После оптимизации:
- Количество обработанных запросов: 140,331
- Среднее запросов/сек: 4,689.36
- Средняя длительность запроса: 10.69 мс

Сначала исправляй доступ к данным.
А кэш используй потом, чтобы масштабироваться, а не выживать.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍72👎1🤔1
Поддержка MinBy / MaxBy скоро появится в Entity Framework 😍

Судя по всему, это должно приехать в EF 11 Preview 2.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
8🔥1🤔1
Жирный лайфхак: как бесплатно и за пару минут сделать сайт с документацией для любого репозитория на GitHub:

👉 @KodBlog
This media is not supported in your browser
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👎3🥴21🤔1🤨1
У нас новости: нативная трассировка OpenTelemetry появится в ASP.NET 11 Preview 2! ✌️

ASP.NET Core теперь нативно добавляет атрибуты семантических конвенций OpenTelemetry в Activity HTTP-сервера, приводя это в соответствие со спецификацией OpenTelemetry HTTP server span. Все обязательные атрибуты теперь включены по умолчанию, то есть метаданные совпадают с теми, что раньше были доступны только через библиотеку OpenTelemetry.Instrumentation.AspNetCore.

Чтобы собирать встроенные данные трассировки, подпишитесь на source Microsoft.AspNetCore в вашей конфигурации OpenTelemetry:

builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
.AddSource("Microsoft.AspNetCore")
.AddConsoleExporter());


Никакая дополнительная библиотека инструментирования (например OpenTelemetry.Instrumentation.AspNetCore) больше не нужна. Фреймворк теперь напрямую проставляет атрибуты семантических конвенций, такие как http.request.method, url.path, http.response.status_code и server.address, в Activity запроса.


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
5🤔1
Самый простой способ добавить валидацию в Options Pattern

Можно использовать data annotations, например атрибут Required.

Также нужно обновить настройку DI и вызвать метод ValidateDataAnnotations.

Это включит валидацию при разрешении options из DI-контейнера.

public class GitHubSettings
{
[Required]
public string AccessToken { get; init; }

[Required]
public string RepositoryName { get; init; }
}

builder.Services
.AddOptions<GitHubSettings>()
.BindConfiguration("GitHubSettings")
.ValidateDataAnnotations();


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🤔2
thoseThreeOnlyBringRegret

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥101🤔1
Самое мощное правило для написания читаемого C# кода:

(Я вынес его из одного ТВ-шоу 90-х про бои на мечах)

Никогда не делайте цепочку больше чем из одного тернарного оператора.

Сейчас объясню.

В детстве я смотрел сериал Highlander.

Если не знакомы с этим шоу:

Там куча людей дерется на мечах.

Главное правило? Должен остаться только один.

То есть в конце выживает только один.

Золотое правило при работе с тернарным оператором в C#:

Должен быть только один.

То есть избегайте цепочек из более чем одного тернарного оператора.

Решение:

1. Перепишите в if-else.
2. Посмотрите, можно ли еще сильнее отрефакторить и упростить код.

Запомните:

Если видите цепочку тернарных операторов, доставайте меч, ну то есть рефакторьте, и рубите эту цепочку.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
13🥴10💯2🤔1