csharpproglib | Unsorted

Telegram-канал csharpproglib - Библиотека шарписта | C#, F#, .NET, ASP.NET

23284

Все самое полезное для C#-разработчика в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/b60af5a4 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead

Subscribe to a channel

Библиотека шарписта | C#, F#, .NET, ASP.NET

🤖 Подборка вакансий для шарпистов

Team Lead C# — от 350 000 ₽ в офис или на удалёнку в Москве

Программист C#/С++/. NET (Middle) — до 400 000 ₽, офис в Москве

Backend .NET developer ( Middle/Middle+) — удалёнка

➡️ Еще больше топовых вакансий — в нашем канале C# Jobs

🐸 Библиотека шарписта

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

💻 Плавающие окна в Visual Studio

Если вы работаете с несколькими мониторами, вы наверняка отрывали Solution Explorer или окно отладчика на второй экран. Это удобно, но поведение плавающих окон по умолчанию бывает раздражающим: они не отображаются отдельными кнопками в панели задач Windows, сворачиваются вместе с основным окном IDE и всегда остаются поверх остальных окон.

В Visual Studio есть настройка, которая это меняет.

Где найти

Tools > Options > Environment > Windows > Floating Windows

Там есть выпадающий список «These floating windows are owned by the main window» с тремя вариантами:

None — плавающие окна полностью независимы: у каждого своя кнопка в панели задач, они остаются на экране при • сворачивании IDE и не лезут поверх других приложений.

Tool Windows — значение по умолчанию. Документы плавают свободно, а панели инструментов привязаны к IDE.

Documents and Tool Windows — классическое поведение Visual Studio: всё подчиняется главному окну.

Двойной клик с зажатым Ctrl по заголовку любой панели мгновенно переключает её между плавающим и закреплённым состоянием.

➡️ Блог разработчиков

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#sharp_view

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

💡 MCP-сервера на F# без лишнего кода

MCP (Model Context Protocol) набирает популярность как способ подключать инструменты к языковым моделям. Но писать MCP-серверы на C# многословно, а на чистом .NET SDK — тем более. FsMcp решает эту задачу для F#-разработчиков: типобезопасный DSL, минимум шаблонного кода, интеграция с экосистемой .NET.

Что это такое

FsMcp это обёртка над официальным [Microsoft ModelContextProtocol .NET SDK](https://github.com/modelcontextprotocol/csharp-sdk). Библиотека добавляет поверх него computation expressions, типизированные обработчики инструментов и Result-based обработку ошибок.

Установка через NuGet:

dotnet add package FsMcp.Server


Дополнительные пакеты по необходимости:
dotnet add package FsMcp.Client     # клиент
dotnet add package FsMcp.Testing # тест-хелперы
dotnet add package FsMcp.Server.Http # HTTP/SSE транспорт
dotnet add package FsMcp.Sampling # вызов LLM из инструментов


Как это работает

Сервер описывается через mcpServer { } — computation expression, внутри которого объявляются инструменты, ресурсы и промпты.

Инструмент принимает F#-запись как входные данные, JSON Schema генерируется автоматически через TypeShape:
type GreetArgs = { name: string; greeting: string option }

let server = mcpServer {
name "MyServer"
version "1.0.0"

tool (TypedTool.define<GreetArgs> "greet" "Greets a person" (fun args -> task {
let greeting = args.greeting |> Option.defaultValue "Hello"
return Ok [ Content.text $"{greeting}, {args.name}!" ]
}) |> unwrapResult)

useStdio
}

Server.run server |> fun t -> t.GetAwaiter().GetResult()


Поле greeting помечается как необязательное автоматически, потому что тип string option.

Пример с калькулятором:
type CalcArgs = { a: float; b: float }

let server = mcpServer {
name "Calculator"
version "1.0.0"

tool (TypedTool.define<CalcArgs> "add" "Add two numbers" (fun args -> task {
return Ok [ Content.text $"{args.a + args.b}" ]
}) |> unwrapResult)

tool (TypedTool.define<CalcArgs> "divide" "Divide a by b" (fun args -> task {
if args.b = 0.0 then return Error (TransportError "Division by zero")
else return Ok [ Content.text $"{args.a / args.b}" ]
}) |> unwrapResult)

useStdio
}


Ошибки возвращаются через Result<'T, McpError> без исключений на ожидаемых путях.

HTTP-транспорт

Если нужен не stdio, а HTTP/SSE:
open FsMcp.Server.Http

HttpServer.run server (Some "/mcp") "http://localhost:3001"
|> fun t -> t.GetAwaiter().GetResult()


Тестирование

FsMcp.Testing позволяет вызывать инструменты напрямую, без сетевого соединения и запуска процессов:
open FsMcp.Testing

let result =
TestServer.callTool serverConfig "add"
(Map.ofList ["a", jsonEl 10; "b", jsonEl 20])
|> Async.AwaitTask |> Async.RunSynchronously

result |> Expect.mcpHasTextContent "30" "addition works"


Что ещё есть в библиотеке

FsMcp покрывает не только базовый сценарий. Среди возможностей: стриминговые инструменты через IAsyncEnumerable<Content>, уведомления о прогрессе, валидационный middleware, трассировка через OpenTelemetry, горячая замена инструментов (DynamicServer.addTool) и интеграция с FsToolkit.ErrorHandling через пакет FsMcp.TaskApi.

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#sharp_view

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

🤩 Agent Skills в .NET: три способа создать, один провайдер для запуска

Когда строишь агента, рано или поздно сталкиваешься с проблемой: навыки разрабатывают разные команды, в разное время, в разных форматах. Microsoft Agent Framework теперь поддерживает три подхода к написанию скиллов и объединяет их в одном провайдере без лишней конфигурации.

Какую боль решает

Раньше приходилось либо ждать, пока всё будет готово, либо переписывать логику под один формат. Теперь можно добавлять навыки постепенно: один пришёл из файловой системы, второй из NuGet-пакета, третий написан прямо в коде как временная заглушка. Агент не различает их — он просто выбирает нужный по контексту.

Три способа создать скилл

1️⃣ Файловый скилл

Навык живёт как директория на диске: SKILL.md с инструкциями, скрипты и референсные документы:

skills/
└── onboarding-guide/
├── SKILL.md
├── scripts/
│ └── check-provisioning.py
└── references/
└── onboarding-checklist.md


В SKILL.md описываем метаданные и шаги для агента. Провайдер поднимается одной строкой:
var skillsProvider = new AgentSkillsProvider(
Path.Combine(AppContext.BaseDirectory, "skills"),
SubprocessScriptRunner.RunAsync);


2️⃣ Классовый скилл из NuGet

Команда HR-систем публикует Contoso.Skills.HrEnrollment. Внутри — класс, унаследованный от AgentClassSkill<T>. Ресурсы помечаются атрибутом [AgentSkillResource], скрипты — [AgentSkillScript]. Рефлексия сама находит всё нужное:
public sealed class BenefitsEnrollmentSkill : AgentClassSkill<BenefitsEnrollmentSkill>
{
public override AgentSkillFrontmatter Frontmatter { get; } = new(
"benefits-enrollment",
"Enroll an employee in health, dental, or vision plans.");

[AgentSkillResource("available-plans")]
public string AvailablePlans => "...список планов...";

[AgentSkillScript("enroll")]
private static string Enroll(string employeeId, string planCode) { ... }
}


3️⃣ Инлайн-скилл

Нужный навык ещё не вышел, а ждать нельзя. Пишем прямо в коде через AgentInlineSkill:
var timeOffSkill = new AgentInlineSkill(
name: "time-off-balance",
description: "Calculate remaining vacation and sick days.",
instructions: "...")
.AddScript("calculate-balance", (string employeeId, string leaveType) =>
{
int remaining = HrDatabase.GetAnnualAllowance(employeeId, leaveType)
- HrDatabase.GetDaysUsed(employeeId, leaveType);
return JsonSerializer.Serialize(new { employeeId, leaveType, remaining });
});


Когда NuGet-пакет выйдет, то просто убираем строку из билдера. Агент ничего не заметит.

Собираем всё вместе

AgentSkillsProviderBuilder объединяет все три типа:
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills"))
.UseSkill(new BenefitsEnrollmentSkill())
.UseSkill(timeOffSkill)
.UseFileScriptRunner(SubprocessScriptRunner.RunAsync)
.UseScriptApproval(true) // подтверждение перед запуском скриптов
.Build();


UseScriptApproval(true) добавляет человека в цикл: агент приостанавливается перед каждым запуском скрипта и ждёт одобрения. Полезно там, где скрипты имеют реальные последствия — записывают данные, обращаются к продакшн-инфраструктуре.

Подход удобен тем, что каждый шаг независим. Не нужно согласовывать форматы между командами или держать всё в одном репозитории. Файловые скиллы хорошо подходят для контента, который часто меняется. Классовые — для переиспользуемой логики, которую удобно поставлять как пакет. Инлайновые — для временных заглушек и случаев, когда скилл нужно генерировать динамически из данных.

➡️ Источник | Документация | Примеры на GitHub

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#il_люминатор

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

👨‍💻 Убираем лишнее из контекстного меню без хирургии

Контекстное меню Windows 11 по умолчанию набито пунктами, которые большинству людей не нужны никогда. «Открыть в терминале», «Показать дополнительные параметры», «Дать доступ», «Закрепить на начальном экране». Cписок разрастается с каждым обновлением, и убрать ненужное штатными средствами нельзя.

Windows 11 Context Menu Manager это простой инструмент, который позволяет отключить ненужные пункты нового контекстного меню Explorer в Windows 11.

Ничего лишнего: запускаете приложение, снимаете галочки с того, что мешает, закрываете. Изменения применяются сразу.

Где взять: в GitHub репозитории

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#async_news

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

🤯 Представьте, что ваш AI-агент работает так же предсказуемо, как обычный микросервис. Звучит утопически, но это именно то, к чему должна прийти разработка в 2026 году.

Основная боль текущих реализаций — полная непредсказуемость поведения. Сегодня агент выполнил задачу за два шага, а завтра ушёл в рекурсию и потратил все лимиты.

Наш обновлённый курс «Разработка AI-агентов» научит, как приручить этот хаос с помощью Python и современных фреймворков. Мы не будем учить «общаться» с нейросетью, мы будем строить из неё надёжный инструмент.

✅ Что вы получите:


— понимание того, как управлять логикой агента на уровне кода;
— навыки работы с LangChain и библиотеками оркестрации;
— готовые паттерны для обработки ошибок и галлюцинаций;
— опыт создания систем, которые реально экономят время.

Есть пара мест со скидкой до завтра, решайтесь 👈🏻

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

🛠 fixed и pinning в небезопасном коде

Когда вы работаете с неуправляемым кодом, сборщик мусора превращается в непредсказуемую переменную. Он может переместить объект в памяти в любой момент, а ваш указатель при этом будет ссылаться уже на пустое место.

Именно для этого существует fixed.

Сборщик мусора не просто удаляет объекты, он их перемещает. Это часть компактизации кучи. В управляемом коде это незаметно, потому что среда сама отслеживает ссылки. Но как только вы получаете сырой указатель в unsafe-блоке, GC об этом не знает. Он спокойно переместит объект, а ваш указатель останется висеть в воздухе.

Результат: невоспроизводимые падения, тихая порча данных или обращение к чужой памяти.

Как работает fixed

Оператор fixed говорит сборщику: «не трогай этот объект, пока я с ним работаю». Объект временно закрепляется в памяти, и указатель остаётся валидным на протяжении всего блока:

unsafe
{
fixed (int* ptr = &array[0])
{
// ptr гарантированно указывает туда, куда нужно
for (int i = 0; i < array.Length; i++)
{
*(ptr + i) *= 2;
}
}
// После выхода из блока GC снова может перемещать объект
}


Всё, что происходит внутри блока fixed, защищено. Как только вы выходите за его пределы, объект снова становится целью для GC.

Когда это нужно

1. interop с нативными библиотеками. Если вы передаёте указатель в C или C++ код через P/Invoke, объект должен быть закреплён на время вызова. Иначе GC может переместить его прямо во время работы нативной функции:
[DllImport("native.dll")]
static extern void ProcessBuffer(int* buffer, int length);

unsafe
{
fixed (int* ptr = data)
{
ProcessBuffer(ptr, data.Length);
}
}


2. Высокопроизводительная обработка данных. Когда LINQ и foreach дают слишком много накладных расходов, прямая работа с памятью через указатели ускоряет обработку. Это актуально для парсинга бинарных форматов, работы с изображениями, аудио, сетевыми буферами.

3. Небезопасные операции cо Span<T>. Если вы получаете указатель из Span, backing-объект тоже нужно закрепить.

Практическое правило простое: блок fixed должен содержать только тот код, которому реально нужен указатель. Никакой лишней логики внутри.

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#il_люминатор

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

Почему приватный виртуальный метод нельзя переопределить

Кажется, что virtual и private должны просто работать вместе. Один говорит «этот метод можно переопределить», другой говорит «этот метод виден только внутри класса».

Подсказка: что переопределение метода подразумевает с точки зрения доступности.

Ответ: в нашем канале по подготовке к собесу

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#dotnet_challenge

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

🤖 .NET миграции теперь с ИИ-анализом

Microsoft представила Modernization Assessment: инструмент для анализа кода на готовность к облаку. Он создает точный план миграции для .NET проектов.

Как работает оценка

Загрузите репозиторий в GitHub Copilot. ИИ сканирует зависимости, архитектуру и легаси-код. Выдает роадмапу с задачами и рисками миграции в Azure.

➡️ Блог разработчиков | Репозиторий

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#async_news

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

❗️ ASP.NET Core 2.3 В С Ё

Microsoft объявила о завершении поддержки ASP.NET Core 2.3 на .NET Framework. Это касается старых веб-приложений, работающих на Windows-серверах.

ASP.NET Core 2.3 классифицируется как «Tools» по политике поддержки. После окончания поддержки пропадут обновления безопасности и техническая помощь. Версия использовалась для постепенной миграции с классического ASP.NET.

➡️ Источник

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#async_news

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

💡 Шпаргалка по форматам DateTime в C#

В C# форматирование даты и времени строится вокруг строк шаблонов: ими можно красиво вывести DateTime, DateTimeOffset и при необходимости точно распарсить строку обратно в объект.

Для повседневной работы чаще всего хватает нескольких шаблонов и пары правил, но именно они спасают от путаницы в датах и времени.

Вот короткая шпаргалка по самым полезным символам:

dd - День с нулем
ddd - Короткий день недели
dddd - Полный день недели
MM - Месяц с нулем
MMM - Короткий месяц
MMMM - Полный месяц
yy - Год две цифры
yyyy - Год четыре цифры
HH - Часы 24
hh - Часы 12
mm - Минуты
ss - Секунды
fff - Миллисекунды
tt - AM/PM
zzz - Часовой пояс


Примеры в кодe:
var dt = new DateTime(2026, 4, 7, 17, 34, 12);

dt.ToString("yyyy-MM-dd") // 2026-04-07
dt.ToString("dd.MM.yyyy") // 07.04.2026
dt.ToString("HH:mm:ss") // 17:34:12
dt.ToString("dddd, dd MMMM") // вторник, 07 апреля


Для разбора строки используйте ParseExact или TryParseExact. Они требуют точного совпадения, убирая ошибки:
var text = "2026-04-07 17:34:12";
var parsed = DateTime.ParseExact(text, "yyyy-MM-dd HH:mm:ss", null);


📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#sharp_view

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

👀 Управление видимостью памяти

Баги в многопоточном коде редко связаны с логикой. Чаще проблема в видимости данных. Процессор, компилятор и среда выполнения переупорядочивают операции ради производительности. Без явных барьеров один поток может никогда не увидеть изменения, которые сделал другой. Именно это решает Volatile.

Как это работает

Volatile.Read и Volatile.Write расставляют барьеры памяти в нужных местах:

• запись до Volatile.Write не может быть перенесена после неё
• чтение после Volatile.Read не может быть перенесено до него

На практике это значит: когда один поток устанавливает флаг, другие потоки рано или поздно увидят актуальное значение:

private int _flag;

public void Set()
{
Volatile.Write(ref _flag, 1);
}

public bool IsSet()
{
return Volatile.Read(ref _flag) == 1;
}


Это легче, чем lock

Volatile не захватывает монитор и не блокирует поток. Это просто барьер памяти. Накладные расходы минимальны по сравнению с полноценной блокировкой.

Но за это приходится платить ограничением: Volatile гарантирует только видимость, не атомарность.

Где это работает корректно

Типичный сценарий это флаг инициализации, который устанавливается один раз:
if (Volatile.Read(ref _initialized) == 0)
{
Initialize();
Volatile.Write(ref _initialized, 1);
}


Если этот код выполняется только в одном потоке, всё в порядке. Volatile гарантирует, что другие потоки увидят _initialized == 1 после того, как инициализация завершится.

Где это не работает

Если несколько потоков могут одновременно войти в этот блок, код становится небезопасным. Между проверкой _initialized == 0 и установкой _initialized = 1 другой поток уже успеет войти и тоже вызовет Initialize(). Здесь нужен Interlocked или полноценный lock.

Volatile подходит, когда один поток пишет, остальные читают. Как только несколько потоков начинают писать, то нужна атомарность, и тут Volatile уже не справится.

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#il_люминатор

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#garbage_collector

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

👨‍💻 Маскировка данных в .NET

Утечки в логах это один из самых распространённых и незаметных compliance-рисков. Пароль в трейсе, email в structured log, номер карты в HTTP-дампе. Всё это копится в Kibana и ждёт своего часа.

Moongazing.Veil — библиотека для .NET 8/9/10, которая закрывает эту дыру декларативно, на всех уровнях сразу.

Три пакета:

# ядро
dotnet add package Moongazing.Veil
# HTTP middleware
dotnet add package Moongazing.Veil.AspNetCore
# structured logs
dotnet add package Moongazing.Veil.Serilog


Слой 1. Строки и объекты

Авто-обнаружение типа данных: email, телефон, карта, IBAN, JWT, IP, API-ключ и маскировка без конфига:
Veil.Mask("john.doe@gmail.com");   
// j******e@g****.com
Veil.Mask("5425123456789012");
// 5425 **** **** 9012
Veil.Mask("Bearer eyJhbGci...");
// Bearer eyJh***...


Для DTO атрибут [Veiled]:
public class CustomerDto
{
public string Name { get; set; }

[Veiled]
public string Email { get; set; }

[Veiled(Show = 4, Position = VeilPosition.Last)]
public string CardNumber { get; set; }
}

var masked = Veil.MaskObject(original); // original не трогается


Слой 2. HTTP-трафик:
app.UseVeilRedaction(); // middleware в pipeline

// конфиг:
http.RedactHeaders("Authorization", "X-Api-Key");
http.RedactBodyFields("$.password", "$.creditCard");
http.RedactQueryParams("token", "api_key");


Данные редактируются до того, как попадают в логи.

Слой 3. Serilog без изменений в коде:
Log.Logger = new LoggerConfiguration()
.Destructure.WithVeil()
.Enrich.WithVeilRedaction()
.WriteTo.Console()
.CreateLogger();


Все существующие Log.Information("User {@User}", user) начинают маскировать данные автоматически. Ни один вызов переписывать не нужно.

➡️ NuGet

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#async_news

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

👨‍💻 Первый дайджест апреля

Пошутили и хватит.

Разработчик написал программу для проигрывателя винила

OpenFeature для .NET

dotnet-adr для архитектурных заметок

C# 15 Union Types

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#async_news

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

🚀 .NET 11 Preview 3

Вышел третий превью-релиз .NET 11. Обновления затронули рантайм, SDK, библиотеки, ASP.NET Core, EF Core и .NET MAUI. Разберём главное.

Библиотеки

System.Text.Json получил больше контроля над именованием полей и обработкой значений по умолчанию. Алгоритм сжатия Zstandard переехал в System.IO.Compression — теперь он часть стандартной библиотеки, а не отдельный пакет. ZIP-чтение добавило валидацию CRC32. Regex теперь корректно обрабатывает все Unicode-последовательности переноса строки.

Рантайм

Runtime async больше не требует явного opt-in через атрибут — функция стала стабильнее и готовится к основному потоку. JIT-компилятор улучшил оптимизацию switch-выражений, проверок границ массивов и операций приведения типов. Для WebAssembly добавлена поддержка WebCIL и улучшена отладка в браузере.

SDK

dotnet run теперь принимает переменные окружения прямо из командной строки:

dotnet run -e MY_VAR=value


Solution-фильтры можно редактировать через CLI без открытия IDE. Файловые приложения теперь можно разбивать на несколько файлов. dotnet watch получил поддержку Aspire, восстановление после краша и улучшения для Windows Desktop.

C#

Добавлена начальная поддержка типа union это размеченные объединения в духе F# или Rust. Пока preview, но направление понятное.

ASP.NET Core

Поддержка Zstandard для сжатия ответов и распаковки запросов. Компонент Virtualize в Blazor теперь адаптируется к элементам с переменной высотой в рантайме. HTTP/3 начинает обрабатывать запросы раньше — меньше задержек на старте соединения.

Entity Framework Core

ChangeTracker.GetEntriesForState() позволяет получать записи по состоянию без лишнего обнаружения изменений. DbContext теперь умеет удалять провайдеры и добавлять пулы фабрик. SQL-генератор стал убирать лишние JOIN-ы, а для SQL Server добавлены JSON API.

Контейнеры

Образы .NET на mcr.microsoft.com теперь подписываются. Можно верифицировать их подлинность перед запуском.

.NET MAUI

Maps API получил кластеризацию маркеров, стилизацию и расширенное API взаимодействия. LongPressGestureRecognizer теперь встроен в платформу. Добавлена поддержка Android 17 / API 37 в режиме preview.

➡️ Источник

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#async_news

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

💡 Фриланс для разработчиков

Вы ищете заказы там, где их ищут все. А локальный бизнес даже не знает о существовании биржи — ИП пишут в чатах «посоветуйте программиста» или листают Авито.

Будьте там, где нет толпы.

➡️ Остальные 4 способа найти первые проекты без бирж

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#garbage_collector

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

🔐 Защита от CSRF-атак в NET

Cross-Site Request Forgery (CSRF) это атака, при которой злоумышленник заставляет браузер пользователя отправить нежелательный запрос от его имени.

Пользователь залогинился в банковском приложении. Он заходит на вредоносный сайт, где спрятана форма, которая автоматически отправляет POST-запрос на /transfer?amount=10000&to=hacker. Браузер добросовестно прикладывает куки сессии. Сервер видит валидный запрос. Деньги ушли.

Как включить защиту:

1. Регистрация сервиса:

builder.Services.AddAntiforgery();


2. Защита конкретного эндпоинта:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Submit(FormModel model)
{
// обработка только "своих" запросов
}


3. Глобальная защита через фильтр:
builder.Services.AddControllersWithViews(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});


Minimal API — вручную:
app.MapPost("/submit", ([FromForm] IFormCollection form,
IAntiforgery antiforgery, HttpContext ctx) =>
{
antiforgery.ValidateRequestAsync(ctx);
// ...
});


CSRF-защита критична для любых форм, меняющих состояние: оплата, смена пароля, удаление данных.

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#sharp_view

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

💡 Дайджест недели

Просто вспомним, что было на этой неделе.

Claude Code находит уязвимости в коде за 2 часа

.NET миграции теперь с ИИ-анализом

Маскировка данных в .NET

ASP.NET Core 2.3 В С Ё

Microsoft объявила о выходе Agent Framework 1.0 для .NET

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#async_news

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

🤔 Разрабатываете ИИ-агентов, но всё ещё не уверены в их стабильности и прогнозируемости?

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

🧠 На нём вы узнаете:

– как оптимизировать траты на токены;
– как на практике оценить качество работы агента;
– как «докручивать» RAG-системы без потери качества;
– как обеспечить устойчивость агента к сбоям внешних сервисов без падения всей системы и про многое-многое другое.

📅 Старт: 19 мая.

👥 Спикеры — практики с опытом в AI и Data Science в крупных IT-компаниях, таких как Яндекс, Huawei, МТС и др.

Длительность: 6-12 недель в зависимости от тарифа.


🔗 Программа курса и другие подробности

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#garbage_collector

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

🤩 Конец эпохи Python-интеропа для .NET-разработчиков

Microsoft объявила о выходе Agent Framework 1.0 для .NET и Python.

Agent Framework — это унификация двух предыдущих Microsoft-проектов: Semantic Kernel: enterprise-интеграция, DI, телеметрия; и AutoGen: многоагентные паттерны и оркестрация. Один пакет вместо двух, одна модель программирования.

До Agent Framework 1.0 большинство инструментов для AI-агентов были Python-first. .NET-разработчики либо запускали Python-процессы рядом и общались с ними через API/IPC, либо пользовались половинчатыми .NET-обёртками над Python-библиотеками.

Что стабилизировано в 1.0

В стабильную версию вошли: базовая абстракция агента, сервисные коннекторы для .NET, middleware-хуки, провайдеры памяти и контекста, граф-based workflow и паттерны многоагентной оркестрации: sequential, concurrent, handoff, group chat и Magentic-One.

Вместе с 1.0 вышел DevUI: браузерный локальный дебаггер для визуализации выполнения агента, потоков сообщений, вызовов инструментов и решений оркестратора в реальном времени.

AutoGen продолжит получать только баг-фиксы и критические патчи безопасности. Semantic Kernel остаётся активным, но для новых проектов с агентами Microsoft теперь рекомендует Agent Framework.

➡️ Источник

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#async_news

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

🧑‍💻 Claude Code находит уязвимости в коде за 2 часа вместо 2 месяцев

В апреле исследователь из Anthropic показал, как с помощью Claude Code нашёл уязвимости в ядре Linux, одна из которых пролежала незамеченной 23 года. Скрипт простой до неприличия:

find . -type f -print0 | while IFS= read -r -d '' file; do
claude \
--dangerously-skip-permissions \
--print "Find a vulnerability. hint: look at $file.
Write the most serious one to /out/report.txt."
done


Идея в том, чтобы прогнать Claude Code по каждому файлу и собрать отчёт.

Адаптация для C# на Windows:
Get-ChildItem -Path . -Recurse -Filter "*.cs" | ForEach-Object {
$file = $_.FullName
& claude `
--dangerously-skip-permissions `
--print "Find a vulnerability. hint: look at $file
Write the most serious one to report.txt"
}


На выходе список строк с предупреждениями. Claude описывает конкретный сценарий атаки с шагами, объясняет почему это работает и даёт рекомендации по исправлению.

Классический аудит стоит десятки тысяч евро и занимает месяцы. Этот скрипт запускается за минуту и даёт первый результат за пару часов.

➡️ Источник

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#sharp_view

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

⚙️ Настоящие атомарные операции

Если Volatile решает проблему видимости, то Interlocked решает проблему атомарности. Операции реализованы на уровне процессора и выполняются как неделимые единицы — никакой другой поток не может вмешаться в середину

Самый частый сценарий это счётчик, который обновляют несколько потоков:

private int _counter;

public void Increment()
{
Interlocked.Increment(ref _counter);
}


Без Interlocked операция _counter++ на самом деле три шага: прочитать, прибавить, записать. Два потока могут выполнить их одновременно и затереть результат друг друга. Interlocked.Increment делает всё это за один неделимый шаг.

Lock-free генератор ID

Interlocked подходит для генерации уникальных идентификаторов без блокировок:
public int GetNextId()
{
return Interlocked.Increment(ref _id);
}


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

CompareExchange: условное обновление

Самая мощная операция в арсенале Interlocked:
if (Interlocked.CompareExchange(ref _state, 1, 0) == 0)
{
// Успешно перешли из состояния 0 в 1
}


Логика простая: если текущее значение равно 0, заменить на 1 и вернуть старое значение. Если кто-то уже изменил _state, операция ничего не сделает. Это паттерн, на котором строятся lock-free кэши, планировщики и конкурентные очереди.

Volatile и Interlocked — не одно и то же

Их можно перепутать, но они решают разные задачи.

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

В реальных системах нередко нужны оба. Volatile чтобы читать свежие данные, Interlocked чтобы безопасно их менять.

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#sharp_view

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

⭐️ Подборка вакансий для шарпистов

Middle Frontend Developer (C#, WPF) — гибрид в Нови-Саде, Сербия

C#/.NET Junior Developer — офис в Ростове-на-Дону

Backend .NET developer ( Middle/Middle+) — удалёнка

➡️ Еще больше топовых вакансий — в нашем канале C# Jobs

🐸 Библиотека шарписта

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

🛠 Регистрация сервисов в .NET

Три способа зарегистрировать сервис в .NET отличаются одним: как долго живёт экземпляр.

Transient — новый экземпляр при каждом обращении к контейнеру. Подходит для лёгких, stateless-сервисов. Для тяжёлых объектов с дорогой инициализацией будет дорого.

Scoped — один экземпляр на HTTP-запрос. Правильный выбор по умолчанию. DbContext работает именно так: отслеживает сущности в рамках одного запроса и утилизируется по его завершении.

Singleton — один экземпляр на всё время жизни приложения. Подходит только для stateless-сервисов или тех, где всё изменяемое состояние явно защищено для параллельного доступа.


Сервис с длинным жизненным циклом не должен зависеть от сервиса с коротким. Вот безопасная иерархия зависимостей:

Singleton  →  может зависеть от  →  Singleton
Scoped → может зависеть от → Singleton, Scoped
Transient → может зависеть от → Singleton, Scoped, Transient


📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#sharp_view

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

📎 Когда нужно соединить два мира

TaskCompletionSource<T> решает одну конкретную проблему: вы хотите вернуть Task, но не можете использовать async/await, потому что результат приходит через коллбэк, событие или другой внешний сигнал.

Пример с коллбэк-API

Допустим, есть метод BeginOperation, который работает по старинке через onSuccess и onError. Оборачиваем его в нормальный Task:

public Task<string> GetDataAsync()
{
var tcs = new TaskCompletionSource<string>(
TaskCreationOptions.RunContinuationsAsynchronously);

BeginOperation(
onSuccess: result => tcs.SetResult(result),
onError: ex => tcs.SetException(ex));

return tcs.Task;
}


Теперь вызывающий код просто пишет await GetDataAsync() и не знает, что внутри коллбэки.

Почему важен RunContinuationsAsynchronously

Это не просто флаг для галочки. Без него продолжения выполняются прямо на том потоке, который вызвал SetResult. В сложных системах это может привести к неожиданной реентерабельности или дедлоку.

С флагом продолжения уходят в пул потоков и поведение становится предсказуемым.

Координация сигналов

Настоящая сила TaskCompletionSource проявляется, когда нужно синхронизировать несколько частей системы:
public Task WaitForSignalAsync()
{
return _signalTcs.Task;
}

public void Signal()
{
_signalTcs.TrySetResult();
}


Один компонент ждёт сигнала через await WaitForSignalAsync(), другой вызывает Signal() когда готов. Это базовый паттерн для кастомных async-локов, очередей и event-систем.

Когда использовать

Подходит, если нужно обернуть коллбэк-API в Task, реализовать собственный примитив синхронизации, или управлять завершением задачи вручную из внешнего кода. Если ситуация стандартная и async/await справляется, TaskCompletionSource лучше не трогать.

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#sharp_view

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

📎 Гибридный кэш для .NET с защитой от типичных проблем

Кэширование в .NET часто выглядит так: либо IMemoryCache для одного узла, либо Redis для распределённых сценариев. А если нужно и то, и другое одновременно, с нормальной устойчивостью к сбоям, то приходится писать обёртки самим.

FusionCache это гибридный кэш для .NET с открытым исходным кодом. Он работает как двухуровневый кэш: L1 в памяти и L2 в распределённом хранилище. Переключение между режимами прозрачно, поэтому код менять не нужно.

Минимальный пример без DI:

var cache = new FusionCache(new FusionCacheOptions());

var product = cache.GetOrSet<Product>(
$"product:{id}",
_ => GetProductFromDb(id),
TimeSpan.FromSeconds(30)
);


С DI и настройками устойчивости:
services.AddFusionCache()
.WithDefaultEntryOptions(new FusionCacheEntryOptions()
.SetDuration(TimeSpan.FromMinutes(2))
.SetPriority(CacheItemPriority.High)
.SetFailSafe(true, TimeSpan.FromHours(2))
.SetFactoryTimeouts(
TimeSpan.FromMilliseconds(100), // soft timeout
TimeSpan.FromSeconds(2) // hard timeout
)
);


Fail-safe здесь означает: если фабрика данных упала или превысила таймаут, кэш вернёт устаревшее значение вместо ошибки на срок до двух часов.

Три сценария, с которыми сталкиваются почти все

1. Cache Stampede. Когда ключ протухает, сотни одновременных запросов идут прямо в базу. FusionCache блокирует параллельные вычисления и делает один запрос вместо ста.

2. Медленная фабрика данных. Если база или внешний сервис тормозит, запросы накапливаются. FusionCache поддерживает soft и hard таймауты: при soft таймауте возвращается устаревшее значение (если оно есть), при hard таймауте бросается исключение, и вы сами решаете, что делать.

3. Согласованность в кластере. Если у вас несколько нод, их L1-кэши могут разойтись. Backplane, например, через Redis Pub/Sub, уведомляет все ноды об изменениях.

FusionCache также совместим с HybridCache от Microsoft и может использоваться как его реализация.

➡️ Репозиторий

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#sharp_view

Читать полностью…

Библиотека шарписта | C#, F#, .NET, ASP.NET

🗂 Гайд: где ещё искать работу в IT

Cобрали 30 джоб-сайтов на любой вкус: для джунов с первым pet-проектом, для мидлов в поиске удалёнки, для тех, кто хочет работать в геймдеве или уехать в Европу.

Каждый сайт описан коротко и по делу: что за аудитория, какие вакансии, для какого грейда подходит. Отдельно платформы для стажировок и первой работы, и для тех, кто ищет валютную удалёнку.

➡️ Искать работу

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

Читать полностью…
Subscribe to a channel