[{"data":1,"prerenderedAt":18791},["ShallowReactive",2],{"navigation_docs":3,"-csharp-aspnet-web-api-controller-base-actionresult":2949,"-csharp-aspnet-web-api-controller-base-actionresult-surround":18786},[4,1640,1765,2219,2352,2559,2641,2691,2748,2782,2908,2945],{"title":5,"icon":6,"path":7,"stem":8,"children":9},"C#","i-devicon-csharp","/csharp","01.csharp",[10,13,60,90,120,202,219,253,379,404,457,650,1346,1636],{"title":11,"path":7,"stem":12},"C# Roadmap","01.csharp/index",{"title":14,"icon":15,"path":16,"stem":17,"children":18,"page":59},"Fundamentals","i-lucide-book-open","/csharp/fundamentals","01.csharp/01.fundamentals",[19,23,27,31,35,39,43,47,51,55],{"title":20,"path":21,"stem":22},"Вступ до екосистеми .NET","/csharp/fundamentals/introduction-to-ecosystem","01.csharp/01.fundamentals/01.introduction-to-ecosystem",{"title":24,"path":25,"stem":26},"Структура програми на C#","/csharp/fundamentals/program-structure","01.csharp/01.fundamentals/02.program-structure",{"title":28,"path":29,"stem":30},"Змінні та Типи Даних","/csharp/fundamentals/variables-data-types","01.csharp/01.fundamentals/03.variables-data-types",{"title":32,"path":33,"stem":34},"Масиви","/csharp/fundamentals/arrays","01.csharp/01.fundamentals/04.arrays",{"title":36,"path":37,"stem":38},"Strings & Text Handling","/csharp/fundamentals/strings-text-handling","01.csharp/01.fundamentals/05.strings-text-handling",{"title":40,"path":41,"stem":42},"Дати і Час","/csharp/fundamentals/dates-time-handling","01.csharp/01.fundamentals/06.dates-time-handling",{"title":44,"path":45,"stem":46},"Потік Керування","/csharp/fundamentals/control-flow","01.csharp/01.fundamentals/07.control-flow",{"title":48,"path":49,"stem":50},"Методи","/csharp/fundamentals/methods","01.csharp/01.fundamentals/08.methods",{"title":52,"path":53,"stem":54},"Основи Відлагодження","/csharp/fundamentals/debugging-basics","01.csharp/01.fundamentals/09.debugging-basics",{"title":56,"path":57,"stem":58},"Інтерактивна Консоль (Classic)","/csharp/fundamentals/interactive-console","01.csharp/01.fundamentals/10.interactive-console",false,{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":59},"OOP","i-lucide-box","/csharp/oop","01.csharp/02.oop",[66,70,74,78,82,86],{"title":67,"path":68,"stem":69},"Package Management (Управління Пакетами)","/csharp/oop/package-management","01.csharp/02.oop/01.package-management",{"title":71,"path":72,"stem":73},"Класи та Об'єкти","/csharp/oop/classes-objects","01.csharp/02.oop/02.classes-objects",{"title":75,"path":76,"stem":77},"Властивості та Поля","/csharp/oop/properties-fields","01.csharp/02.oop/03.properties-fields",{"title":79,"path":80,"stem":81},"Стовпи ООП","/csharp/oop/oop-pillars","01.csharp/02.oop/04.oop-pillars",{"title":83,"path":84,"stem":85},"Advanced Types","/csharp/oop/advanced-types","01.csharp/02.oop/05.advanced-types",{"title":87,"path":88,"stem":89},"Namespaces (Простори Імен)","/csharp/oop/namespaces","01.csharp/02.oop/06.namespaces",{"title":91,"icon":92,"path":93,"stem":94,"children":95,"page":59},"Advanced Core","i-lucide-zap","/csharp/advanced-core","01.csharp/03.advanced-core",[96,100,104,108,112,116],{"title":97,"path":98,"stem":99},"Generics (Узагальнення)","/csharp/advanced-core/generics","01.csharp/03.advanced-core/01.generics",{"title":101,"path":102,"stem":103},"Делегати, Події та Лямбда-вирази","/csharp/advanced-core/delegates-events-lambdas","01.csharp/03.advanced-core/02.delegates-events-lambdas",{"title":105,"path":106,"stem":107},"Interfaces Deep Dive (Інтерфейси: Поглиблений Розгляд)","/csharp/advanced-core/interfaces-deep-dive","01.csharp/03.advanced-core/03.interfaces-deep-dive",{"title":109,"path":110,"stem":111},"Обробка Винятків","/csharp/advanced-core/exception-handling","01.csharp/03.advanced-core/04.exception-handling",{"title":113,"path":114,"stem":115},"Pattern Matching","/csharp/advanced-core/pattern-matching","01.csharp/03.advanced-core/05.pattern-matching",{"title":117,"path":118,"stem":119},"Додаткові Можливості C#","/csharp/advanced-core/additional-features","01.csharp/03.advanced-core/06.additional-features",{"title":121,"icon":122,"path":123,"stem":124,"children":125,"page":59},"Architecture Best Practices","i-lucide-building-2","/csharp/architecture-best-practices","01.csharp/04.architecture-best-practices",[126,130,149,153,157,161,165,169],{"title":127,"path":128,"stem":129},"Software Design Principles (Частина 1)","/csharp/architecture-best-practices/software-design-principles","01.csharp/04.architecture-best-practices/01.software-design-principles",{"title":131,"icon":132,"path":133,"stem":134,"children":135,"page":59},"Design Patterns","i-lucide-folder","/csharp/architecture-best-practices/design-patterns","01.csharp/04.architecture-best-practices/02.design-patterns",[136],{"title":137,"icon":132,"path":138,"stem":139,"children":140,"page":59},"Creational","/csharp/architecture-best-practices/design-patterns/creational","01.csharp/04.architecture-best-practices/02.design-patterns/creational",[141,145],{"title":142,"path":143,"stem":144},"Singleton (Одинак)","/csharp/architecture-best-practices/design-patterns/creational/singleton","01.csharp/04.architecture-best-practices/02.design-patterns/creational/01.singleton",{"title":146,"path":147,"stem":148},"Builder (Будівельник)","/csharp/architecture-best-practices/design-patterns/creational/builder","01.csharp/04.architecture-best-practices/02.design-patterns/creational/02.builder",{"title":150,"path":151,"stem":152},"Building Professional CLIs","/csharp/architecture-best-practices/building-professional-clis","01.csharp/04.architecture-best-practices/03.building-professional-clis",{"title":154,"path":155,"stem":156},"Validation & Flow Control","/csharp/architecture-best-practices/validation-flow-control","01.csharp/04.architecture-best-practices/04.validation-flow-control",{"title":158,"path":159,"stem":160},"The Modern .NET Host (Microsoft.Extensions)","/csharp/architecture-best-practices/modern-dotnet-host","01.csharp/04.architecture-best-practices/05.modern-dotnet-host",{"title":162,"path":163,"stem":164},"Data Mapper: Repository та DAO патерни (Частина 1)","/csharp/architecture-best-practices/data-mapper-part1","01.csharp/04.architecture-best-practices/06.data-mapper-part1",{"title":166,"path":167,"stem":168},"Data Mapper: Repository та DAO патерни (Частина 2)","/csharp/architecture-best-practices/data-mapper-part2","01.csharp/04.architecture-best-practices/07.data-mapper-part2",{"title":170,"icon":132,"path":171,"stem":172,"children":173,"page":59},"Di Ioc","/csharp/architecture-best-practices/di-ioc","01.csharp/04.architecture-best-practices/08.di-ioc",[174,178,182,186,190,194,198],{"title":175,"path":176,"stem":177},"Проблема залежностей та Інверсія Контролю","/csharp/architecture-best-practices/di-ioc/the-dependency-problem","01.csharp/04.architecture-best-practices/08.di-ioc/01.the-dependency-problem",{"title":179,"path":180,"stem":181},"Будуємо власний Service Container","/csharp/architecture-best-practices/di-ioc/build-your-own-container","01.csharp/04.architecture-best-practices/08.di-ioc/02.build-your-own-container",{"title":183,"path":184,"stem":185},"Service Locator: Паттерн та Анти-паттерн","/csharp/architecture-best-practices/di-ioc/service-locator-pattern","01.csharp/04.architecture-best-practices/08.di-ioc/03.service-locator-pattern",{"title":187,"path":188,"stem":189},"Паттерни Dependency Injection","/csharp/architecture-best-practices/di-ioc/dependency-injection-patterns","01.csharp/04.architecture-best-practices/08.di-ioc/04.dependency-injection-patterns",{"title":191,"path":192,"stem":193},"Microsoft DI: IServiceCollection та IServiceProvider","/csharp/architecture-best-practices/di-ioc/microsoft-di-deep-dive","01.csharp/04.architecture-best-practices/08.di-ioc/05.microsoft-di-deep-dive",{"title":195,"path":196,"stem":197},"Service Lifetimes та Scopes","/csharp/architecture-best-practices/di-ioc/service-lifetimes-and-scopes","01.csharp/04.architecture-best-practices/08.di-ioc/06.service-lifetimes-and-scopes",{"title":199,"path":200,"stem":201},"DI Анти-паттерни та Найкращі Практики","/csharp/architecture-best-practices/di-ioc/di-anti-patterns-and-best-practices","01.csharp/04.architecture-best-practices/08.di-ioc/07.di-anti-patterns-and-best-practices",{"title":203,"icon":132,"path":204,"stem":205,"children":206,"page":59},"Standard Library","/csharp/standard-library","01.csharp/05.standard-library",[207,211,215],{"title":208,"path":209,"stem":210},"Collections (Колекції)","/csharp/standard-library/collections","01.csharp/05.standard-library/01.collections",{"title":212,"path":213,"stem":214},"High Performance Types (Високопродуктивні Типи)","/csharp/standard-library/high-performance-types","01.csharp/05.standard-library/02.high-performance-types",{"title":216,"path":217,"stem":218},"LINQ (Language Integrated Query)","/csharp/standard-library/linq","01.csharp/05.standard-library/03.linq",{"title":220,"icon":221,"path":222,"stem":223,"children":224,"page":59},"System Internals Concurrency","i-lucide-server","/csharp/system-internals-concurrency","01.csharp/06.system-internals-concurrency",[225,229,233,237,241,245,249],{"title":226,"path":227,"stem":228},"Memory Management","/csharp/system-internals-concurrency/memory-management","01.csharp/06.system-internals-concurrency/01.memory-management",{"title":230,"path":231,"stem":232},"Reflection API: System.Type та Метадані","/csharp/system-internals-concurrency/reflection-fundamentals","01.csharp/06.system-internals-concurrency/02.reflection-fundamentals",{"title":234,"path":235,"stem":236},"Attributes та Dynamic Language Runtime","/csharp/system-internals-concurrency/attributes-dynamic","01.csharp/06.system-internals-concurrency/03.attributes-dynamic",{"title":238,"path":239,"stem":240},"Expression Trees: Швидка Альтернатива Рефлексії","/csharp/system-internals-concurrency/expression-trees-compiled","01.csharp/06.system-internals-concurrency/04.expression-trees-compiled",{"title":242,"path":243,"stem":244},"Source Generators: Compile-Time Code Generation","/csharp/system-internals-concurrency/source-generators","01.csharp/06.system-internals-concurrency/05.source-generators",{"title":246,"path":247,"stem":248},"Multithreading Fundamentals","/csharp/system-internals-concurrency/multithreading-fundamentals","01.csharp/06.system-internals-concurrency/06.multithreading-fundamentals",{"title":250,"path":251,"stem":252},"Synchronization Primitives","/csharp/system-internals-concurrency/synchronization-primitives","01.csharp/06.system-internals-concurrency/07.synchronization-primitives",{"title":254,"icon":255,"path":256,"stem":257,"children":258,"page":59},"System Programming Windows","i-lucide-cpu","/csharp/system-programming-windows","01.csharp/07.system-programming-windows",[259,263,267,271,275,279,283,287,291,295,299,303,307,311,315,319,323,327,331,335,339,343,347,351,355,359,363,367,371,375],{"title":260,"path":261,"stem":262},"Як Працює Операційна Система","/csharp/system-programming-windows/how-os-works","01.csharp/07.system-programming-windows/01.how-os-works",{"title":264,"path":265,"stem":266},"Процеси в .NET — API та Запуск","/csharp/system-programming-windows/processes-in-dotnet","01.csharp/07.system-programming-windows/02.processes-in-dotnet",{"title":268,"path":269,"stem":270},"Процеси в .NET — IPC та Міжпроцесна Комунікація","/csharp/system-programming-windows/02a.processes-ipc","01.csharp/07.system-programming-windows/02a.processes-ipc",{"title":272,"path":273,"stem":274},"Application Domains та Збірки — AppDomain і AssemblyLoadContext","/csharp/system-programming-windows/appdomains-assemblies","01.csharp/07.system-programming-windows/03.appdomains-assemblies",{"title":276,"path":277,"stem":278},"Application Domains та Збірки — Plug-in Система з Hot-Reload","/csharp/system-programming-windows/03a.appdomains-plugin-system","01.csharp/07.system-programming-windows/03a.appdomains-plugin-system",{"title":280,"path":281,"stem":282},"Потоки — Основи та API Thread","/csharp/system-programming-windows/thread-fundamentals","01.csharp/07.system-programming-windows/04.thread-fundamentals",{"title":284,"path":285,"stem":286},"Потоки — Lifecycle, Пріоритети та Безпечне Завершення","/csharp/system-programming-windows/04a.thread-lifecycle-priorities","01.csharp/07.system-programming-windows/04a.thread-lifecycle-priorities",{"title":288,"path":289,"stem":290},"Проблеми Спільного Стану — Race Condition та Data Race","/csharp/system-programming-windows/shared-state-problems","01.csharp/07.system-programming-windows/05.shared-state-problems",{"title":292,"path":293,"stem":294},"Проблеми Спільного Стану — Memory Model та volatile","/csharp/system-programming-windows/05a.shared-state-memory-model","01.csharp/07.system-programming-windows/05a.shared-state-memory-model",{"title":296,"path":297,"stem":298},"Синхронізація — Monitor, lock та еволюція примітивів","/csharp/system-programming-windows/synchronization-fundamentals","01.csharp/07.system-programming-windows/06.synchronization-fundamentals",{"title":300,"path":301,"stem":302},"Синхронізація — Наскрізний Приклад та Deadlock Detection","/csharp/system-programming-windows/06a.synchronization-walkthrough","01.csharp/07.system-programming-windows/06a.synchronization-walkthrough",{"title":304,"path":305,"stem":306},"Синхронізація — Mutex, Semaphore та Event-Based Primitives","/csharp/system-programming-windows/synchronization-advanced","01.csharp/07.system-programming-windows/07.synchronization-advanced",{"title":308,"path":309,"stem":310},"Синхронізація — Interlocked, Volatile та Lock-Free Структури","/csharp/system-programming-windows/07a.synchronization-advanced-walkthrough","01.csharp/07.system-programming-windows/07a.synchronization-advanced-walkthrough",{"title":312,"path":313,"stem":314},"Interlocked, CAS та Lock-Free Структури","/csharp/system-programming-windows/interlocked-cas-lockfree","01.csharp/07.system-programming-windows/08.interlocked-cas-lockfree",{"title":316,"path":317,"stem":318},"Volatile, Memory Model та Spinning","/csharp/system-programming-windows/08a.volatile-memory-model","01.csharp/07.system-programming-windows/08a.volatile-memory-model",{"title":320,"path":321,"stem":322},"ThreadPool — Пул Потоків для Ефективного Виконання","/csharp/system-programming-windows/thread-pool","01.csharp/07.system-programming-windows/09.thread-pool",{"title":324,"path":325,"stem":326},"ThreadPool — Просунуті Сценарії та Внутрішня Будова","/csharp/system-programming-windows/09a.thread-pool-advanced","01.csharp/07.system-programming-windows/09a.thread-pool-advanced",{"title":328,"path":329,"stem":330},"Concurrent та Immutable Collections","/csharp/system-programming-windows/concurrent-collections","01.csharp/07.system-programming-windows/10.concurrent-collections",{"title":332,"path":333,"stem":334},"TPL, Task та Композиція — Від Thread до Task","/csharp/system-programming-windows/tpl-parallel-plinq","01.csharp/07.system-programming-windows/11.tpl-parallel-plinq",{"title":336,"path":337,"stem":338},"Parallel Class та PLINQ — Data Parallelism","/csharp/system-programming-windows/11a.tpl-parallel-plinq-advanced","01.csharp/07.system-programming-windows/11a.tpl-parallel-plinq-advanced",{"title":340,"path":341,"stem":342},"Async/Await — Фундамент Асинхронного Програмування","/csharp/system-programming-windows/async-fundamentals","01.csharp/07.system-programming-windows/12.async-fundamentals",{"title":344,"path":345,"stem":346},"SynchronizationContext та ConfigureAwait — Контекст Виконання","/csharp/system-programming-windows/async-context-configureawait","01.csharp/07.system-programming-windows/13.async-context-configureawait",{"title":348,"path":349,"stem":350},"Async — Просунуті Паттерни","/csharp/system-programming-windows/async-advanced","01.csharp/07.system-programming-windows/14.async-advanced",{"title":352,"path":353,"stem":354},"System.Threading.Channels — Async Producer-Consumer","/csharp/system-programming-windows/channels","01.csharp/07.system-programming-windows/15.channels",{"title":356,"path":357,"stem":358},"Асинхронна Синхронізація","/csharp/system-programming-windows/async-synchronization","01.csharp/07.system-programming-windows/16.async-synchronization",{"title":360,"path":361,"stem":362},"Unsafe Code та Вказівники","/csharp/system-programming-windows/unsafe-code","01.csharp/07.system-programming-windows/17.unsafe-code",{"title":364,"path":365,"stem":366},"P/Invoke та Windows API — Міст між .NET та Native Code","/csharp/system-programming-windows/pinvoke-winapi","01.csharp/07.system-programming-windows/18.pinvoke-winapi",{"title":368,"path":369,"stem":370},"Реєстр Windows — Центральна База Конфігурації Системи","/csharp/system-programming-windows/windows-registry","01.csharp/07.system-programming-windows/19.windows-registry",{"title":372,"path":373,"stem":374},"Windows Hooks, Hotkeys та Services — Глибока Інтеграція з ОС","/csharp/system-programming-windows/windows-hooks-services","01.csharp/07.system-programming-windows/20.windows-hooks-services",{"title":376,"path":377,"stem":378},"Системне Програмування C# (Windows) — 07.system-programming-windows","/csharp/system-programming-windows/implementation_plan","01.csharp/07.system-programming-windows/implementation_plan",{"title":380,"icon":132,"path":381,"stem":382,"children":383,"page":59},"Io","/csharp/io","01.csharp/08.io",[384,388,392,396,400],{"title":385,"path":386,"stem":387},"8.1.1. Основи роботи з файловою системою","/csharp/io/file-system-basics","01.csharp/08.io/01.file-system-basics",{"title":389,"path":390,"stem":391},"8.1.2. Потоки (Streams) та Серіалізація Даних","/csharp/io/streams-serialization","01.csharp/08.io/02.streams-serialization",{"title":393,"path":394,"stem":395},"8.2.1. JSON Serialization з System.Text.Json","/csharp/io/json-serialization","01.csharp/08.io/03.json-serialization",{"title":397,"path":398,"stem":399},"8.2.2. XML Serialization та LINQ to XML","/csharp/io/xml-serialization","01.csharp/08.io/04.xml-serialization",{"title":401,"path":402,"stem":403},"8.2.3. Binary Serialization: MessagePack та Protocol Buffers","/csharp/io/binary-serialization","01.csharp/08.io/05.binary-serialization",{"title":405,"icon":132,"path":406,"stem":407,"children":408,"page":59},"Ado Net","/csharp/ado-net","01.csharp/09.ado-net",[409,413,417,421,425,429,433,437,441,445,449,453],{"title":410,"path":411,"stem":412},"9.1. Введення в ADO.NET","/csharp/ado-net/introduction-to-adonet","01.csharp/09.ado-net/01.introduction-to-adonet",{"title":414,"path":415,"stem":416},"9.2. Клас DbConnection — з'єднання з базою даних","/csharp/ado-net/connection","01.csharp/09.ado-net/02.connection",{"title":418,"path":419,"stem":420},"9.3. Клас DbCommand — виконання SQL-запитів","/csharp/ado-net/command-and-queries","01.csharp/09.ado-net/03.command-and-queries",{"title":422,"path":423,"stem":424},"9.4. Клас DbDataReader — ефективне читання даних","/csharp/ado-net/datareader","01.csharp/09.ado-net/04.datareader",{"title":426,"path":427,"stem":428},"9.5. Параметризовані запити та захист від SQL Injection","/csharp/ado-net/parameters-and-sql-injection","01.csharp/09.ado-net/05.parameters-and-sql-injection",{"title":430,"path":431,"stem":432},"9.6. Транзакції в ADO.NET","/csharp/ado-net/transactions","01.csharp/09.ado-net/06.transactions",{"title":434,"path":435,"stem":436},"9.7. DbProviderFactory — провайдер-незалежний код","/csharp/ado-net/provider-factory","01.csharp/09.ado-net/07.provider-factory",{"title":438,"path":439,"stem":440},"9.8. Асинхронний доступ до даних","/csharp/ado-net/async-data-access","01.csharp/09.ado-net/08.async-data-access",{"title":442,"path":443,"stem":444},"9.9. Від'єднаний режим: DataSet, DataTable, DataRow","/csharp/ado-net/disconnected-mode-dataset","01.csharp/09.ado-net/09.disconnected-mode-dataset",{"title":446,"path":447,"stem":448},"9.10. DataAdapter — міст між DataSet та базою даних","/csharp/ado-net/data-adapter","01.csharp/09.ado-net/10.data-adapter",{"title":450,"path":451,"stem":452},"9.11. Data Mapper та Repository: Архітектура доступу до даних","/csharp/ado-net/data-mapper-repository","01.csharp/09.ado-net/11.data-mapper-repository",{"title":454,"path":455,"stem":456},"9.12. Identity Map, Unit of Work та Specification Pattern","/csharp/ado-net/advanced-patterns","01.csharp/09.ado-net/12.advanced-patterns",{"title":458,"icon":255,"path":459,"stem":460,"children":461,"page":59},"Ef Core","/csharp/ef-core","01.csharp/10.ef-core",[462,466,470,474,478,482,486,490,494,498,502,506,510,514,518,522,526,532,538,542,546,550,554,558,562,566,570,574,578,582,586,590,594,598,602,606,610,614,618,622,626,630,634,638,642,646],{"title":463,"path":464,"stem":465},"Що таке ORM? Від SQL до об'єктів","/csharp/ef-core/what-is-orm","01.csharp/10.ef-core/01.what-is-orm",{"title":467,"path":468,"stem":469},"Перший проєкт — від нуля до CRUD","/csharp/ef-core/first-project","01.csharp/10.ef-core/02.first-project",{"title":471,"path":472,"stem":473},"DbContext — Серце EF Core","/csharp/ef-core/dbcontext-deep-dive","01.csharp/10.ef-core/03.dbcontext-deep-dive",{"title":475,"path":476,"stem":477},"Провайдери баз даних — Архітектура та Вибір СУБД","/csharp/ef-core/database-providers","01.csharp/10.ef-core/04.database-providers",{"title":479,"path":480,"stem":481},"Конвенції EF Core — Магія без конфігурації","/csharp/ef-core/conventions","01.csharp/10.ef-core/05.conventions",{"title":483,"path":484,"stem":485},"Fluent API та Data Annotations — Явна конфігурація моделі","/csharp/ef-core/fluent-api-vs-annotations","01.csharp/10.ef-core/06.fluent-api-vs-annotations",{"title":487,"path":488,"stem":489},"Зв'язки — One-to-One та One-to-Many","/csharp/ef-core/relationships-basics","01.csharp/10.ef-core/07.relationships-basics",{"title":491,"path":492,"stem":493},"Зв'язки Advanced — Many-to-Many та Складні Сценарії","/csharp/ef-core/relationships-advanced","01.csharp/10.ef-core/08.relationships-advanced",{"title":495,"path":496,"stem":497},"Властивості — Типи, Конвертери, Компаратори (Частина 1)","/csharp/ef-core/property-configuration-part1","01.csharp/10.ef-core/09.property-configuration-part1",{"title":499,"path":500,"stem":501},"Властивості — Value Comparers, Generators, Shadow Properties (Частина 2)","/csharp/ef-core/property-configuration-part2","01.csharp/10.ef-core/09.property-configuration-part2",{"title":503,"path":504,"stem":505},"Складні типи — Owned Types та Complex Types (Частина 1)","/csharp/ef-core/complex-types-owned-part1","01.csharp/10.ef-core/10.complex-types-owned-part1",{"title":507,"path":508,"stem":509},"Складні типи — Complex Types, Keyless Entities, Порівняння (Частина 2)","/csharp/ef-core/complex-types-owned-part2","01.csharp/10.ef-core/10.complex-types-owned-part2",{"title":511,"path":512,"stem":513},"JSON Columns — Складні дані у JSON (Частина 1)","/csharp/ef-core/json-columns-part1","01.csharp/10.ef-core/11.json-columns-part1",{"title":515,"path":516,"stem":517},"JSON Columns — Value Comparers, Індекси, Провайдери (Частина 2)","/csharp/ef-core/json-columns-part2","01.csharp/10.ef-core/11.json-columns-part2",{"title":519,"path":520,"stem":521},"Успадкування — Абстрактні класи та TPH (Частина 1)","/csharp/ef-core/inheritance-part1","01.csharp/10.ef-core/12.inheritance-part1",{"title":523,"path":524,"stem":525},"Успадкування — TPT, TPC та Порівняння Стратегій (Частина 2)","/csharp/ef-core/inheritance-part2","01.csharp/10.ef-core/12.inheritance-part2",{"title":527,"path":528,"stem":529,"children":530},"Індекси, Обмеження та Схема (Частина 1)","/csharp/ef-core/indexes-constraints-part1","01.csharp/10.ef-core/13.indexes-constraints-part1",[531],{"title":527,"path":528,"stem":529},{"title":533,"path":534,"stem":535,"children":536},"Індекси, Обмеження та Схема (Частина 2)","/csharp/ef-core/indexes-constraints-part2","01.csharp/10.ef-core/13.indexes-constraints-part2",[537],{"title":533,"path":534,"stem":535},{"title":539,"path":540,"stem":541},"Seed Data — Початкові Дані (Частина 1)","/csharp/ef-core/seeding-part1","01.csharp/10.ef-core/14.seeding-part1",{"title":543,"path":544,"stem":545},"Seed Data — SQL-скрипти, Bogus та Стратегії (Частина 2)","/csharp/ef-core/seeding-part2","01.csharp/10.ef-core/14.seeding-part2",{"title":547,"path":548,"stem":549},"Global Query Filters — Глобальні Фільтри (Частина 1)","/csharp/ef-core/global-query-filters-part1","01.csharp/10.ef-core/15.global-query-filters-part1",{"title":551,"path":552,"stem":553},"Global Query Filters — Підводні камені та Інтеграція (Частина 2)","/csharp/ef-core/global-query-filters-part2","01.csharp/10.ef-core/15.global-query-filters-part2",{"title":555,"path":556,"stem":557},"LINQ-запити в EF Core (Частина 1)","/csharp/ef-core/linq-queries-part1","01.csharp/10.ef-core/16.linq-queries-part1",{"title":559,"path":560,"stem":561},"LINQ-запити в EF Core (Частина 2)","/csharp/ef-core/linq-queries-part2","01.csharp/10.ef-core/16.linq-queries-part2",{"title":563,"path":564,"stem":565},"Завантаження Пов'язаних Даних (Частина 1)","/csharp/ef-core/loading-related-data-part1","01.csharp/10.ef-core/17.loading-related-data-part1",{"title":567,"path":568,"stem":569},"Завантаження Пов'язаних Даних (Частина 2)","/csharp/ef-core/loading-related-data-part2","01.csharp/10.ef-core/17.loading-related-data-part2",{"title":571,"path":572,"stem":573},"Raw SQL, Views та Stored Procedures (Частина 1)","/csharp/ef-core/raw-sql-part1","01.csharp/10.ef-core/18.raw-sql-part1",{"title":575,"path":576,"stem":577},"Raw SQL — Stored Procedures, DbFunction та Bulk Operations (Частина 2)","/csharp/ef-core/raw-sql-part2","01.csharp/10.ef-core/18.raw-sql-part2",{"title":579,"path":580,"stem":581},"Продвинуті Запити — Compiled Queries, Bulk та Оптимізація (Частина 1)","/csharp/ef-core/advanced-queries-part1","01.csharp/10.ef-core/19.advanced-queries-part1",{"title":583,"path":584,"stem":585},"Продвинуті Запити — Query Tags, Bulk та Interceptors (Частина 2)","/csharp/ef-core/advanced-queries-part2","01.csharp/10.ef-core/19.advanced-queries-part2",{"title":587,"path":588,"stem":589},"Change Tracker — Відстеження Змін (Частина 1)","/csharp/ef-core/change-tracking-part1","01.csharp/10.ef-core/20.change-tracking-part1",{"title":591,"path":592,"stem":593},"Change Tracker — Графи Об'єктів та Disconnected (Частина 2)","/csharp/ef-core/change-tracking-part2","01.csharp/10.ef-core/20.change-tracking-part2",{"title":595,"path":596,"stem":597},"Збереження Даних та Транзакції (Частина 1)","/csharp/ef-core/saving-data-part1","01.csharp/10.ef-core/21.saving-data-part1",{"title":599,"path":600,"stem":601},"Збереження Даних — Concurrency та Outbox (Частина 2)","/csharp/ef-core/saving-data-part2","01.csharp/10.ef-core/21.saving-data-part2",{"title":603,"path":604,"stem":605},"Конкурентність та Блокування (Частина 1)","/csharp/ef-core/concurrency-part1","01.csharp/10.ef-core/22.concurrency-part1",{"title":607,"path":608,"stem":609},"Конкурентність — Дедлоки та Queue Processing (Частина 2)","/csharp/ef-core/concurrency-part2","01.csharp/10.ef-core/22.concurrency-part2",{"title":611,"path":612,"stem":613},"Міграції в EF Core — Основи (Частина 1)","/csharp/ef-core/migrations-basics-part1","01.csharp/10.ef-core/23.migrations-basics-part1",{"title":615,"path":616,"stem":617},"Міграції в EF Core — Основи (Частина 2)","/csharp/ef-core/migrations-basics-part2","01.csharp/10.ef-core/23.migrations-basics-part2",{"title":619,"path":620,"stem":621},"Міграції — Просунуті Сценарії (Частина 1)","/csharp/ef-core/migrations-advanced-part1","01.csharp/10.ef-core/24.migrations-advanced-part1",{"title":623,"path":624,"stem":625},"Міграції — Просунуті Сценарії (Частина 2)","/csharp/ef-core/migrations-advanced-part2","01.csharp/10.ef-core/24.migrations-advanced-part2",{"title":627,"path":628,"stem":629},"Управління Схемою та Database-First (Частина 1)","/csharp/ef-core/schema-management-part1","01.csharp/10.ef-core/25.schema-management-part1",{"title":631,"path":632,"stem":633},"Управління Схемою та Database-First (Частина 2)","/csharp/ef-core/schema-management-part2","01.csharp/10.ef-core/25.schema-management-part2",{"title":635,"path":636,"stem":637},"Продуктивність EF Core — Основи (Частина 1)","/csharp/ef-core/performance-fundamentals-part1","01.csharp/10.ef-core/26.performance-fundamentals-part1",{"title":639,"path":640,"stem":641},"Interceptors в EF Core (Частина 1)","/csharp/ef-core/interceptors-part1","01.csharp/10.ef-core/29.interceptors-part1",{"title":643,"path":644,"stem":645},"Interceptors в EF Core — Connection, Transaction та Materialization (Частина 2)","/csharp/ef-core/interceptors-part2","01.csharp/10.ef-core/29.interceptors-part2",{"title":647,"path":648,"stem":649},"План вивчення Entity Framework Core — Повний курс","/csharp/ef-core/implementation_plan","01.csharp/10.ef-core/implementation_plan",{"title":651,"icon":652,"path":653,"stem":654,"children":655,"page":59},"ASP.NET","i-devicon-dotnetcore","/csharp/aspnet","01.csharp/11.aspnet",[656,730,791,869,927,941,967,1057,1111,1182,1212,1289],{"title":657,"icon":658,"path":659,"stem":660,"children":661,"page":59},"Minimal API","i-lucide-network","/csharp/aspnet/minimal-api","01.csharp/11.aspnet/01.minimal-api",[662,666,670,674,678,682,686,690,694,698,702,706,710,714,718,722,726],{"title":663,"path":664,"stem":665},"Вступ до ASP.NET та еволюція фреймворку","/csharp/aspnet/minimal-api/introduction","01.csharp/11.aspnet/01.minimal-api/01.introduction",{"title":667,"path":668,"stem":669},"Перший додаток на ASP.NET Core","/csharp/aspnet/minimal-api/first-application","01.csharp/11.aspnet/01.minimal-api/02.first-application",{"title":671,"path":672,"stem":673},"WebApplication, Builder та Dependency Injection","/csharp/aspnet/minimal-api/webapplication-builder","01.csharp/11.aspnet/01.minimal-api/03.webapplication-builder",{"title":675,"path":676,"stem":677},"Конвеєр запитів та Middleware","/csharp/aspnet/minimal-api/request-pipeline-middleware","01.csharp/11.aspnet/01.minimal-api/04.request-pipeline-middleware",{"title":679,"path":680,"stem":681},"Маршрутизація в ASP.NET Core: Основи","/csharp/aspnet/minimal-api/routing-basics","01.csharp/11.aspnet/01.minimal-api/05.routing-basics",{"title":683,"path":684,"stem":685},"Маршрутизація в ASP.NET Core: Розширені можливості","/csharp/aspnet/minimal-api/routing-advanced","01.csharp/11.aspnet/01.minimal-api/06.routing-advanced",{"title":687,"path":688,"stem":689},"Статичні файли в ASP.NET Core","/csharp/aspnet/minimal-api/static-files","01.csharp/11.aspnet/01.minimal-api/07.static-files",{"title":691,"path":692,"stem":693},"Статичні Активи: MapStaticAssets (ASP.NET Core 9.0)","/csharp/aspnet/minimal-api/static-assets","01.csharp/11.aspnet/01.minimal-api/08.static-assets",{"title":695,"path":696,"stem":697},"Конфігурація в ASP.NET Core: Основи","/csharp/aspnet/minimal-api/configuration-fundamentals","01.csharp/11.aspnet/01.minimal-api/09.configuration-fundamentals",{"title":699,"path":700,"stem":701},"Конфігурація: Паттерн Options","/csharp/aspnet/minimal-api/configuration-options","01.csharp/11.aspnet/01.minimal-api/10.configuration-options",{"title":703,"path":704,"stem":705},"Логування в ASP.NET Core: Основи","/csharp/aspnet/minimal-api/logging-basics","01.csharp/11.aspnet/01.minimal-api/11.logging-basics",{"title":707,"path":708,"stem":709},"Логування: Serilog та Middleware","/csharp/aspnet/minimal-api/logging-advanced","01.csharp/11.aspnet/01.minimal-api/12.logging-advanced",{"title":711,"path":712,"stem":713},"Управління станом: HttpContext.Items та Cookies","/csharp/aspnet/minimal-api/state-management","01.csharp/11.aspnet/01.minimal-api/13.state-management",{"title":715,"path":716,"stem":717},"Стан сесії: Sessions","/csharp/aspnet/minimal-api/session-state","01.csharp/11.aspnet/01.minimal-api/14.session-state",{"title":719,"path":720,"stem":721},"Структура проєкту: від хаосу до архітектури","/csharp/aspnet/minimal-api/project-structure","01.csharp/11.aspnet/01.minimal-api/15.project-structure",{"title":723,"path":724,"stem":725},"Scalar у Minimal API: повний проєкт і Fluent OpenAPI","/csharp/aspnet/minimal-api/scalar-openapi-fluent","01.csharp/11.aspnet/01.minimal-api/16.scalar-openapi-fluent",{"title":727,"path":728,"stem":729},"Swagger / Swashbuckle у Minimal API: окремий класичний шлях","/csharp/aspnet/minimal-api/swagger-swashbuckle","01.csharp/11.aspnet/01.minimal-api/17.swagger-swashbuckle",{"title":731,"icon":658,"path":732,"stem":733,"children":734,"page":59},"API","/csharp/aspnet/api","01.csharp/11.aspnet/02.api",[735,739,743,747,751,755,759,763,767,771,775,779,783,787],{"title":736,"path":737,"stem":738},"Що таке API. Клієнт-серверна архітектура","/csharp/aspnet/api/what-is-api","01.csharp/11.aspnet/02.api/01.what-is-api",{"title":740,"path":741,"stem":742},"Формати даних: JSON, XML, TOML та бінарні формати","/csharp/aspnet/api/data-formats","01.csharp/11.aspnet/02.api/02.data-formats",{"title":744,"path":745,"stem":746},"Парадигми API та концепція REST","/csharp/aspnet/api/api-paradigms-rest","01.csharp/11.aspnet/02.api/03.api-paradigms-rest",{"title":748,"path":749,"stem":750},"HTTP-методи, статус-коди та заголовки","/csharp/aspnet/api/http-methods-status-codes","01.csharp/11.aspnet/02.api/04.http-methods-status-codes",{"title":752,"path":753,"stem":754},"Організація HTTP API за принципами REST","/csharp/aspnet/api/rest-organizing","01.csharp/11.aspnet/02.api/05.rest-organizing",{"title":756,"path":757,"stem":758},"Номенклатура URL та CRUD-операції","/csharp/aspnet/api/url-nomenclature-crud","01.csharp/11.aspnet/02.api/06.url-nomenclature-crud",{"title":760,"path":761,"stem":762},"Правила дизайну: іменування та стандарти","/csharp/aspnet/api/api-design-naming","01.csharp/11.aspnet/02.api/07.api-design-naming",{"title":764,"path":765,"stem":766},"Валідація, ліміти та обробка помилок","/csharp/aspnet/api/api-design-validation","01.csharp/11.aspnet/02.api/08.api-design-validation",{"title":768,"path":769,"stem":770},"Обробка помилок у Minimal API","/csharp/aspnet/api/error-handling-http","01.csharp/11.aspnet/02.api/09.error-handling-http",{"title":772,"path":773,"stem":774},"Ідемпотентність та синхронізація стану","/csharp/aspnet/api/idempotency-sync","01.csharp/11.aspnet/02.api/10.idempotency-sync",{"title":776,"path":777,"stem":778},"Пагінація та організація списків","/csharp/aspnet/api/pagination-lists","01.csharp/11.aspnet/02.api/11.pagination-lists",{"title":780,"path":781,"stem":782},"Безпека API, кешування та інтернаціоналізація","/csharp/aspnet/api/security-auth","01.csharp/11.aspnet/02.api/12.security-auth",{"title":784,"path":785,"stem":786},"Процес проєктування API та документування","/csharp/aspnet/api/api-design-process","01.csharp/11.aspnet/02.api/13.api-design-process",{"title":788,"path":789,"stem":790},"OpenAPI: контракт, специфікація та документація API","/csharp/aspnet/api/openapi","01.csharp/11.aspnet/02.api/14.openapi",{"title":792,"icon":793,"path":794,"stem":795,"children":796,"page":59},"Auth","i-lucide-shield-check","/csharp/aspnet/auth","01.csharp/11.aspnet/03.auth",[797,801,805,809,813,817,821,825,829,833,837,841,845,849,853,857,861,865],{"title":798,"path":799,"stem":800},"Основи аутентифікації та авторизації","/csharp/aspnet/auth/auth-fundamentals","01.csharp/11.aspnet/03.auth/01.auth-fundamentals",{"title":802,"path":803,"stem":804},"JWT-аутентифікація","/csharp/aspnet/auth/jwt-authentication","01.csharp/11.aspnet/03.auth/02.jwt-authentication",{"title":806,"path":807,"stem":808},"Авторизація: ролі, політики та resource-based доступ","/csharp/aspnet/auth/authorization-policies","01.csharp/11.aspnet/03.auth/03.authorization-policies",{"title":810,"path":811,"stem":812},"Cookie-аутентифікація та ASP.NET Core Identity","/csharp/aspnet/auth/cookie-auth-identity","01.csharp/11.aspnet/03.auth/04.cookie-auth-identity",{"title":814,"path":815,"stem":816},"JWT + Refresh Tokens (HttpOnly Cookie)","/csharp/aspnet/auth/04b.identity-auth-jwt","01.csharp/11.aspnet/03.auth/04b.identity-auth-jwt",{"title":818,"path":819,"stem":820},"Identity: Підтвердження Email та Скидання Пароля","/csharp/aspnet/auth/identity-email-confirmation","01.csharp/11.aspnet/03.auth/05.identity-email-confirmation",{"title":822,"path":823,"stem":824},"Identity: Двофакторна Аутентифікація (2FA)","/csharp/aspnet/auth/identity-two-factor","01.csharp/11.aspnet/03.auth/06.identity-two-factor",{"title":826,"path":827,"stem":828},"Identity: Внутрішня Архітектура та Кастомізація","/csharp/aspnet/auth/identity-internals","01.csharp/11.aspnet/03.auth/07.identity-internals",{"title":830,"path":831,"stem":832},"OAuth 2.0 та зовнішні провайдери","/csharp/aspnet/auth/oauth-external-providers","01.csharp/11.aspnet/03.auth/08.oauth-external-providers",{"title":834,"path":835,"stem":836},"Безпека на практиці: CORS, HTTPS та захист від атак","/csharp/aspnet/auth/security-hardening","01.csharp/11.aspnet/03.auth/09.security-hardening",{"title":838,"path":839,"stem":840},"Теорія OAuth 2.0: Поняття, Аналогії та Флоу","/csharp/aspnet/auth/oauth-theory","01.csharp/11.aspnet/03.auth/10.oauth-theory",{"title":842,"path":843,"stem":844},"OIDC, OAuth 2.0 та Keycloak в ASP.NET Core","/csharp/aspnet/auth/oidc-keycloak","01.csharp/11.aspnet/03.auth/10.oidc-keycloak",{"title":846,"path":847,"stem":848},"API Keys аутентифікація в ASP.NET Core","/csharp/aspnet/auth/api-keys","01.csharp/11.aspnet/03.auth/11.api-keys",{"title":850,"path":851,"stem":852},"Rate Limiting та Throttling в ASP.NET Core","/csharp/aspnet/auth/rate-limiting","01.csharp/11.aspnet/03.auth/12.rate-limiting",{"title":854,"path":855,"stem":856},"Refresh Token Rotation в ASP.NET Core","/csharp/aspnet/auth/refresh-token-rotation","01.csharp/11.aspnet/03.auth/13.refresh-token-rotation",{"title":858,"path":859,"stem":860},"Certificate Authentication та mTLS в ASP.NET Core","/csharp/aspnet/auth/certificate-auth","01.csharp/11.aspnet/03.auth/14.certificate-auth",{"title":862,"path":863,"stem":864},"RBAC, ABAC та ReBAC в ASP.NET Core","/csharp/aspnet/auth/rbac-abac-rebac","01.csharp/11.aspnet/03.auth/15.rbac-abac-rebac",{"title":866,"path":867,"stem":868},"Multi-tenancy та ізоляція даних в ASP.NET Core","/csharp/aspnet/auth/multi-tenancy","01.csharp/11.aspnet/03.auth/16.multi-tenancy",{"title":870,"icon":871,"path":872,"stem":873,"children":874,"page":59},"Нотифікації","i-lucide-bell","/csharp/aspnet/notifications","01.csharp/11.aspnet/04.notifications",[875,879,883,887,891,895,899,903,907,911,915,919,923],{"title":876,"path":877,"stem":878},"In-App нотифікації через базу даних","/csharp/aspnet/notifications/in-app-database-notifications","01.csharp/11.aspnet/04.notifications/01.in-app-database-notifications",{"title":880,"path":881,"stem":882},"Polling: Регулярний запит оновлень","/csharp/aspnet/notifications/polling","01.csharp/11.aspnet/04.notifications/02.polling",{"title":884,"path":885,"stem":886},"Server-Sent Events: Однострімовий push від сервера","/csharp/aspnet/notifications/server-sent-events","01.csharp/11.aspnet/04.notifications/03.server-sent-events",{"title":888,"path":889,"stem":890},"WebSockets: Двостороннє з'єднання в реальному часі","/csharp/aspnet/notifications/websockets","01.csharp/11.aspnet/04.notifications/04.websockets",{"title":892,"path":893,"stem":894},"SignalR: Абстракція над транспортами реального часу","/csharp/aspnet/notifications/signalr","01.csharp/11.aspnet/04.notifications/05.signalr",{"title":896,"path":897,"stem":898},"Background Services: Фонові задачі в ASP.NET Core","/csharp/aspnet/notifications/background-services","01.csharp/11.aspnet/04.notifications/06.background-services",{"title":900,"path":901,"stem":902},"Web Push нотифікації","/csharp/aspnet/notifications/web-push","01.csharp/11.aspnet/04.notifications/07.web-push",{"title":904,"path":905,"stem":906},"Email нотифікації","/csharp/aspnet/notifications/email-notifications","01.csharp/11.aspnet/04.notifications/08.email-notifications",{"title":908,"path":909,"stem":910},"Порівняння підходів: Як вибрати правильну технологію нотифікацій","/csharp/aspnet/notifications/choosing-the-right-approach","01.csharp/11.aspnet/04.notifications/09.choosing-the-right-approach",{"title":912,"path":913,"stem":914},"Hangfire: Надійне планування фонових задач","/csharp/aspnet/notifications/hangfire","01.csharp/11.aspnet/04.notifications/10.hangfire",{"title":916,"path":917,"stem":918},"Практика: Конвертація зображень у WebP через Hangfire","/csharp/aspnet/notifications/hangfire-image-webp","01.csharp/11.aspnet/04.notifications/11.hangfire-image-webp",{"title":920,"path":921,"stem":922},"Практика: Підготовка відео до HLS-стрімінгу через Hangfire","/csharp/aspnet/notifications/hangfire-video-hls","01.csharp/11.aspnet/04.notifications/12.hangfire-video-hls",{"title":924,"path":925,"stem":926},"Telegram-нотифікації: від одного повідомлення до масових розсилок і мульти-канального підходу","/csharp/aspnet/notifications/telegram-notifications","01.csharp/11.aspnet/04.notifications/13.telegram-notifications",{"title":928,"icon":929,"path":930,"stem":931,"children":932,"page":59},"Інтернаціоналізація","i-lucide-languages","/csharp/aspnet/i18n","01.csharp/11.aspnet/05.i18n",[933,937],{"title":934,"path":935,"stem":936},"Інтернаціоналізація (i18n) у Minimal API: від A до Я","/csharp/aspnet/i18n/internationalization","01.csharp/11.aspnet/05.i18n/01.internationalization",{"title":938,"path":939,"stem":940},"Humanizer: людиномовні рядки у .NET","/csharp/aspnet/i18n/humanizer","01.csharp/11.aspnet/05.i18n/02.humanizer",{"title":942,"icon":943,"path":944,"stem":945,"children":946,"page":59},"Кешування","i-lucide-layers","/csharp/aspnet/caching","01.csharp/11.aspnet/06.caching",[947,951,955,959,963],{"title":948,"path":949,"stem":950},"Огляд кешування: чотири рівні і коли що обирати","/csharp/aspnet/caching/caching","01.csharp/11.aspnet/06.caching/01.caching",{"title":952,"path":953,"stem":954},"IMemoryCache: кеш в оперативній пам'яті","/csharp/aspnet/caching/memory-cache","01.csharp/11.aspnet/06.caching/02.memory-cache",{"title":956,"path":957,"stem":958},"IDistributedCache і Redis: розподілений кеш","/csharp/aspnet/caching/distributed-cache","01.csharp/11.aspnet/06.caching/03.distributed-cache",{"title":960,"path":961,"stem":962},"Response Cache: HTTP-кешування через Cache-Control","/csharp/aspnet/caching/response-cache","01.csharp/11.aspnet/06.caching/04.response-cache",{"title":964,"path":965,"stem":966},"Output Cache: серверний кеш HTTP-відповідей (.NET 7+)","/csharp/aspnet/caching/output-cache","01.csharp/11.aspnet/06.caching/05.output-cache",{"title":968,"icon":969,"path":970,"stem":971,"children":972,"page":59},"Тестування","i-lucide-test-tube","/csharp/aspnet/testing","01.csharp/11.aspnet/07.testing",[973,977,981,985,989,993,997,1001,1005,1009,1013,1017,1021,1025,1029,1033,1037,1041,1045,1049,1053],{"title":974,"path":975,"stem":976},"Що таке тестування? Від інтуїції до науки","/csharp/aspnet/testing/what-is-testing","01.csharp/11.aspnet/07.testing/01.what-is-testing",{"title":978,"path":979,"stem":980},"Піраміда тестування — Стратегія, а не Догма","/csharp/aspnet/testing/testing-pyramid","01.csharp/11.aspnet/07.testing/02.testing-pyramid",{"title":982,"path":983,"stem":984},"Дві Школи Тестування — Лондон проти Детройту","/csharp/aspnet/testing/testing-schools","01.csharp/11.aspnet/07.testing/03.testing-schools",{"title":986,"path":987,"stem":988},"TDD та BDD — Тести як Дизайн-інструмент","/csharp/aspnet/testing/tdd-and-bdd","01.csharp/11.aspnet/07.testing/04.tdd-and-bdd",{"title":990,"path":991,"stem":992},"Що саме тестувати — Техніки аналізу та Циклomatична складність","/csharp/aspnet/testing/what-to-test","01.csharp/11.aspnet/07.testing/05.what-to-test",{"title":994,"path":995,"stem":996},"Тестові Фреймворки — Навіщо вони і що всередині","/csharp/aspnet/testing/test-frameworks","01.csharp/11.aspnet/07.testing/06.test-frameworks",{"title":998,"path":999,"stem":1000},"xUnit — Факти, Теорії та Lifecycle тестів","/csharp/aspnet/testing/xunit-basics","01.csharp/11.aspnet/07.testing/07.xunit-basics",{"title":1002,"path":1003,"stem":1004},"xUnit Advanced — Fixtures, Кастомізація та Розширення","/csharp/aspnet/testing/xunit-advanced","01.csharp/11.aspnet/07.testing/08.xunit-advanced",{"title":1006,"path":1007,"stem":1008},"Moq — Глибоке занурення в мокування","/csharp/aspnet/testing/mocking-with-moq","01.csharp/11.aspnet/07.testing/09.mocking-with-moq",{"title":1010,"path":1011,"stem":1012},"Тестування Баз Даних — EF Core, SQLite та Testcontainers","/csharp/aspnet/testing/database-testing","01.csharp/11.aspnet/07.testing/10.database-testing",{"title":1014,"path":1015,"stem":1016},"Integration Testing — Частина 1 [Теорія та WebApplicationFactory]","/csharp/aspnet/testing/integration-testing","01.csharp/11.aspnet/07.testing/11.integration-testing",{"title":1018,"path":1019,"stem":1020},"Інтеграційне тестування — Практика","/csharp/aspnet/testing/11a.integration-testing-practice","01.csharp/11.aspnet/07.testing/11a.integration-testing-practice",{"title":1022,"path":1023,"stem":1024},"Integration Testing — Частина 2 [Просунуті Сценарії та Testcontainers]","/csharp/aspnet/testing/integration-testing-advanced","01.csharp/11.aspnet/07.testing/12.integration-testing-advanced",{"title":1026,"path":1027,"stem":1028},"Професійний Postman: Колекції, Змінні та GitHub Інтеграція","/csharp/aspnet/testing/postman-professional","01.csharp/11.aspnet/07.testing/13.postman-professional",{"title":1030,"path":1031,"stem":1032},"HttpClient у Тестах Частина 1: Архітектура та MockHttpMessageHandler","/csharp/aspnet/testing/httpclient-testing","01.csharp/11.aspnet/07.testing/14.httpclient-testing",{"title":1034,"path":1035,"stem":1036},"HttpClient у Тестах Частина 2: WireMock.Net та Resilience","/csharp/aspnet/testing/wiremock-net","01.csharp/11.aspnet/07.testing/15.wiremock-net",{"title":1038,"path":1039,"stem":1040},"Патерни та Анти-патерни Тестування: Test Smells","/csharp/aspnet/testing/testing-patterns","01.csharp/11.aspnet/07.testing/16.testing-patterns",{"title":1042,"path":1043,"stem":1044},"Просунуті інструменти: Time, Snapshots та Властивості","/csharp/aspnet/testing/advanced-testing-tools","01.csharp/11.aspnet/07.testing/17.advanced-testing-tools",{"title":1046,"path":1047,"stem":1048},"Тестування Архітектури з NetArchTest","/csharp/aspnet/testing/architecture-testing","01.csharp/11.aspnet/07.testing/18.architecture-testing",{"title":1050,"path":1051,"stem":1052},"Тестування Продуктивності: BenchmarkDotNet, NBomber та k6","/csharp/aspnet/testing/performance-testing","01.csharp/11.aspnet/07.testing/19.performance-testing",{"title":1054,"path":1055,"stem":1056},"Залишок плану для курсу \"Тестування ASP.NET Minimal API\"","/csharp/aspnet/testing/remaining_plan","01.csharp/11.aspnet/07.testing/remaining_plan",{"title":1058,"icon":1059,"path":1060,"stem":1061,"children":1062,"page":59},"Платежі","i-lucide-credit-card","/csharp/aspnet/payments","01.csharp/11.aspnet/08.payments",[1063,1067,1071,1075,1079,1083,1087,1091,1095,1099,1103,1107],{"title":1064,"path":1065,"stem":1066},"Основи платіжної інфраструктури","/csharp/aspnet/payments/payment-fundamentals","01.csharp/11.aspnet/08.payments/01.payment-fundamentals",{"title":1068,"path":1069,"stem":1070},"Методи оплати в Україні","/csharp/aspnet/payments/payment-methods-ukraine","01.csharp/11.aspnet/08.payments/02.payment-methods-ukraine",{"title":1072,"path":1073,"stem":1074},"PCI DSS та безпека платежів","/csharp/aspnet/payments/pci-dss-security","01.csharp/11.aspnet/08.payments/03.pci-dss-security",{"title":1076,"path":1077,"stem":1078},"Архітектура платіжної підсистеми","/csharp/aspnet/payments/payment-architecture","01.csharp/11.aspnet/08.payments/04.payment-architecture",{"title":1080,"path":1081,"stem":1082},"Інтеграція LiqPay (ПриватБанк)","/csharp/aspnet/payments/liqpay-integration","01.csharp/11.aspnet/08.payments/05.liqpay-integration",{"title":1084,"path":1085,"stem":1086},"Інтеграція Monobank Acquiring API","/csharp/aspnet/payments/monobank-acquiring","01.csharp/11.aspnet/08.payments/06.monobank-acquiring",{"title":1088,"path":1089,"stem":1090},"Інтеграція Stripe","/csharp/aspnet/payments/stripe-integration","01.csharp/11.aspnet/08.payments/07.stripe-integration",{"title":1092,"path":1093,"stem":1094},"Webhooks — глибоке занурення","/csharp/aspnet/payments/webhooks-deep-dive","01.csharp/11.aspnet/08.payments/08.webhooks-deep-dive",{"title":1096,"path":1097,"stem":1098},"Підписки та рекурентні платежі","/csharp/aspnet/payments/subscriptions-recurring","01.csharp/11.aspnet/08.payments/09.subscriptions-recurring",{"title":1100,"path":1101,"stem":1102},"Повернення коштів та диспути","/csharp/aspnet/payments/refunds-disputes","01.csharp/11.aspnet/08.payments/10.refunds-disputes",{"title":1104,"path":1105,"stem":1106},"Тестування платіжних інтеграцій","/csharp/aspnet/payments/testing-payments","01.csharp/11.aspnet/08.payments/11.testing-payments",{"title":1108,"path":1109,"stem":1110},"Чекліст виходу в Production","/csharp/aspnet/payments/production-checklist","01.csharp/11.aspnet/08.payments/12.production-checklist",{"title":1112,"icon":1113,"items":1114,"path":1127,"stem":1128,"children":1129,"page":59},"Популярні бібліотеки","lucide:box",[1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126],"01.fluent-validation","02.mapster","03.erroror-result-pattern","04.serilog","05.mediatr","06.polly","07.health-checks","08.feature-management","09.fluent-email","10.quest-pdf","11.bogus","12.humanizer-guard","/csharp/aspnet/libraries","01.csharp/11.aspnet/09.libraries",[1130,1134,1138,1142,1146,1150,1154,1158,1162,1166,1170,1174,1178],{"title":1131,"path":1132,"stem":1133},"Валідація з FluentValidation в ASP.NET Core","/csharp/aspnet/libraries/fluent-validation","01.csharp/11.aspnet/09.libraries/01.fluent-validation",{"title":1135,"path":1136,"stem":1137},"Маппінг об","/csharp/aspnet/libraries/mapster","01.csharp/11.aspnet/09.libraries/02.mapster",{"title":1139,"path":1140,"stem":1141},"Обробка помилок з ErrorOr та Result Pattern в ASP.NET Core","/csharp/aspnet/libraries/erroror-result-pattern","01.csharp/11.aspnet/09.libraries/03.erroror-result-pattern",{"title":1143,"path":1144,"stem":1145},"Структуроване логування з Serilog в ASP.NET Core","/csharp/aspnet/libraries/serilog","01.csharp/11.aspnet/09.libraries/04.serilog",{"title":1147,"path":1148,"stem":1149},"CQRS та Mediator з MediatR в ASP.NET Core","/csharp/aspnet/libraries/mediatr","01.csharp/11.aspnet/09.libraries/05.mediatr",{"title":1151,"path":1152,"stem":1153},"Відмовостійкість з Polly в ASP.NET Core","/csharp/aspnet/libraries/polly","01.csharp/11.aspnet/09.libraries/06.polly",{"title":1155,"path":1156,"stem":1157},"Health Checks в ASP.NET Core","/csharp/aspnet/libraries/health-checks","01.csharp/11.aspnet/09.libraries/07.health-checks",{"title":1159,"path":1160,"stem":1161},"Feature Management та Feature Flags в ASP.NET Core","/csharp/aspnet/libraries/feature-management","01.csharp/11.aspnet/09.libraries/08.feature-management",{"title":1163,"path":1164,"stem":1165},"Відправка Email з FluentEmail в ASP.NET Core","/csharp/aspnet/libraries/fluent-email","01.csharp/11.aspnet/09.libraries/09.fluent-email",{"title":1167,"path":1168,"stem":1169},"Генерація PDF з QuestPDF в ASP.NET Core","/csharp/aspnet/libraries/quest-pdf","01.csharp/11.aspnet/09.libraries/10.quest-pdf",{"title":1171,"path":1172,"stem":1173},"Генерація тестових даних з Bogus в ASP.NET Core","/csharp/aspnet/libraries/bogus","01.csharp/11.aspnet/09.libraries/11.bogus",{"title":1175,"path":1176,"stem":1177},"Humanizer та Guard Clauses в ASP.NET Core","/csharp/aspnet/libraries/humanizer-guard","01.csharp/11.aspnet/09.libraries/12.humanizer-guard",{"title":1179,"path":1180,"stem":1181},"План модуля 10.libraries — Популярні бібліотеки ASP.NET","/csharp/aspnet/libraries/plan","01.csharp/11.aspnet/09.libraries/plan",{"title":1183,"icon":1184,"path":1185,"stem":1186,"children":1187,"page":59},"Razor Pages","i-lucide-layout-template","/csharp/aspnet/razor-pages","01.csharp/11.aspnet/10.razor-pages",[1188,1192,1196,1200,1204,1208],{"title":1189,"path":1190,"stem":1191},"Від Minimal API до Razor Pages: концептуальний перехід","/csharp/aspnet/razor-pages/from-minimal-api","01.csharp/11.aspnet/10.razor-pages/01.from-minimal-api",{"title":1193,"path":1194,"stem":1195},"PageModel: логіка сторінки Razor Pages","/csharp/aspnet/razor-pages/page-model","01.csharp/11.aspnet/10.razor-pages/02.page-model",{"title":1197,"path":1198,"stem":1199},"Razor синтаксис: шаблонізатор у .cshtml","/csharp/aspnet/razor-pages/razor-syntax","01.csharp/11.aspnet/10.razor-pages/03.razor-syntax",{"title":1201,"path":1202,"stem":1203},"Tag Helpers: типізований HTML","/csharp/aspnet/razor-pages/tag-helpers","01.csharp/11.aspnet/10.razor-pages/04.tag-helpers",{"title":1205,"path":1206,"stem":1207},"Форми і валідація: повний цикл обробки даних","/csharp/aspnet/razor-pages/forms-validation","01.csharp/11.aspnet/10.razor-pages/05.forms-validation",{"title":1209,"path":1210,"stem":1211},"Практичний проєкт: TaskManager на Razor Pages","/csharp/aspnet/razor-pages/project-task-manager","01.csharp/11.aspnet/10.razor-pages/06.project-task-manager",{"title":1213,"path":1214,"stem":1215,"children":1216,"page":59},"ASP.NET Core MVC","/csharp/aspnet/mvc","01.csharp/11.aspnet/11.mvc",[1217,1221,1225,1229,1233,1237,1241,1245,1249,1253,1257,1261,1265,1269,1273,1277,1281,1285],{"title":1218,"path":1219,"stem":1220},"Патерн MVC: архітектура, що змінила веб","/csharp/aspnet/mvc/mvc-pattern","01.csharp/11.aspnet/11.mvc/01.mvc-pattern",{"title":1222,"path":1223,"stem":1224},"Від Razor Pages до MVC: концептуальний перехід","/csharp/aspnet/mvc/from-razor-pages","01.csharp/11.aspnet/11.mvc/02.from-razor-pages",{"title":1226,"path":1227,"stem":1228},"Controllers та Actions: серце MVC","/csharp/aspnet/mvc/controllers-actions","01.csharp/11.aspnet/11.mvc/03.controllers-actions",{"title":1230,"path":1231,"stem":1232},"Маршрутизація в MVC: Convention vs Attribute Routing","/csharp/aspnet/mvc/routing-mvc","01.csharp/11.aspnet/11.mvc/04.routing-mvc",{"title":1234,"path":1235,"stem":1236},"Model Binding: від HTTP до C#","/csharp/aspnet/mvc/model-binding","01.csharp/11.aspnet/11.mvc/05.model-binding",{"title":1238,"path":1239,"stem":1240},"Views, ViewData, ViewBag, TempData і ViewModel","/csharp/aspnet/mvc/views-viewdata-tempdata","01.csharp/11.aspnet/11.mvc/06.views-viewdata-tempdata",{"title":1242,"path":1243,"stem":1244},"Filters: аспектно-орієнтоване програмування в MVC","/csharp/aspnet/mvc/filters","01.csharp/11.aspnet/11.mvc/07.filters",{"title":1246,"path":1247,"stem":1248},"Areas: структурування великих застосунків","/csharp/aspnet/mvc/areas","01.csharp/11.aspnet/11.mvc/08.areas",{"title":1250,"path":1251,"stem":1252},"View Components: повторювані незалежні блоки UI","/csharp/aspnet/mvc/view-components","01.csharp/11.aspnet/11.mvc/09.view-components",{"title":1254,"path":1255,"stem":1256},"Display та Editor Templates","/csharp/aspnet/mvc/display-editor-templates","01.csharp/11.aspnet/11.mvc/10.display-editor-templates",{"title":1258,"path":1259,"stem":1260},"Валідація: IValidatableObject та FluentValidation","/csharp/aspnet/mvc/validation-advanced","01.csharp/11.aspnet/11.mvc/11.validation-advanced",{"title":1262,"path":1263,"stem":1264},"HTMX: інтерактивність через HTML-атрибути","/csharp/aspnet/mvc/htmx","01.csharp/11.aspnet/11.mvc/12.htmx",{"title":1266,"path":1267,"stem":1268},"HTMX у ASP.NET Core MVC: серверна інтеграція","/csharp/aspnet/mvc/ajax-htmx-mvc","01.csharp/11.aspnet/11.mvc/13.ajax-htmx-mvc",{"title":1270,"path":1271,"stem":1272},"Практичний проєкт: Каталог товарів з HTMX","/csharp/aspnet/mvc/htmx-project","01.csharp/11.aspnet/11.mvc/14.htmx-project",{"title":1274,"path":1275,"stem":1276},"Завантаження та обробка файлів","/csharp/aspnet/mvc/file-upload","01.csharp/11.aspnet/11.mvc/15.file-upload",{"title":1278,"path":1279,"stem":1280},"Глобалізація та Локалізація MVC","/csharp/aspnet/mvc/globalization-localization","01.csharp/11.aspnet/11.mvc/16.globalization-localization",{"title":1282,"path":1283,"stem":1284},"Підсумковий проєкт: Блог-платформа","/csharp/aspnet/mvc/mvc-project","01.csharp/11.aspnet/11.mvc/17.mvc-project",{"title":1286,"path":1287,"stem":1288},"План курсу: ASP.NET Core MVC","/csharp/aspnet/mvc/plan","01.csharp/11.aspnet/11.mvc/plan",{"title":1290,"path":1291,"stem":1292,"children":1293,"page":59},"Web Api","/csharp/aspnet/web-api","01.csharp/11.aspnet/12.web-api",[1294,1298,1302,1306,1310,1314,1318,1322,1326,1330,1334,1338,1342],{"title":1295,"path":1296,"stem":1297},"Від Minimal API до Controller-based API","/csharp/aspnet/web-api/from-minimal-api-to-controllers","01.csharp/11.aspnet/12.web-api/01.from-minimal-api-to-controllers",{"title":1299,"path":1300,"stem":1301},"ControllerBase, ActionResult\u003CT> та Response Types","/csharp/aspnet/web-api/controller-base-actionresult","01.csharp/11.aspnet/12.web-api/02.controller-base-actionresult",{"title":1303,"path":1304,"stem":1305},"Content Negotiation - JSON, XML та власні форматери","/csharp/aspnet/web-api/content-negotiation","01.csharp/11.aspnet/12.web-api/03.content-negotiation",{"title":1307,"path":1308,"stem":1309},"Версіонування API","/csharp/aspnet/web-api/api-versioning","01.csharp/11.aspnet/12.web-api/04.api-versioning",{"title":1311,"path":1312,"stem":1313},"ProblemDetails та структурована обробка помилок","/csharp/aspnet/web-api/problemdetails-error-handling","01.csharp/11.aspnet/12.web-api/05.problemdetails-error-handling",{"title":1315,"path":1316,"stem":1317},"Фільтри у Web API контексті","/csharp/aspnet/web-api/filters-for-api","01.csharp/11.aspnet/12.web-api/06.filters-for-api",{"title":1319,"path":1320,"stem":1321},"Пагінація, фільтрація та сортування","/csharp/aspnet/web-api/pagination-filtering-sorting","01.csharp/11.aspnet/12.web-api/07.pagination-filtering-sorting",{"title":1323,"path":1324,"stem":1325},"HATEOAS та Resource Expansion","/csharp/aspnet/web-api/hateoas-resource-expansion","01.csharp/11.aspnet/12.web-api/08.hateoas-resource-expansion",{"title":1327,"path":1328,"stem":1329},"Гібридна архітектура - Minimal API + Controllers","/csharp/aspnet/web-api/minimal-api-vs-controllers-hybrid","01.csharp/11.aspnet/12.web-api/09.minimal-api-vs-controllers-hybrid",{"title":1331,"path":1332,"stem":1333},"Документація API - Swashbuckle, NSwag та генерація клієнтів","/csharp/aspnet/web-api/api-documentation-generation","01.csharp/11.aspnet/12.web-api/10.api-documentation-generation",{"title":1335,"path":1336,"stem":1337},"Health Checks та моніторинг API","/csharp/aspnet/web-api/health-checks-monitoring","01.csharp/11.aspnet/12.web-api/11.health-checks-monitoring",{"title":1339,"path":1340,"stem":1341},"Підсумковий проєкт - Production-Ready REST API","/csharp/aspnet/web-api/web-api-project","01.csharp/11.aspnet/12.web-api/12.web-api-project",{"title":1343,"path":1344,"stem":1345},"План курсу: ASP.NET Core Web API (Controllers)","/csharp/aspnet/web-api/plan","01.csharp/11.aspnet/12.web-api/plan",{"title":1347,"icon":1348,"path":1349,"stem":1350,"children":1351,"page":59},"Desktop UI","i-lucide-app-window","/csharp/desktop-ui","01.csharp/12.desktop-ui",[1352,1356,1360,1364,1368,1372,1376,1380,1384,1388,1392,1396,1400,1404,1408,1412,1416,1420,1424,1428,1432,1436,1440,1444,1448,1452,1456,1460,1464,1468,1472,1476,1480,1484,1488,1492,1496,1500,1504,1508,1512,1516,1520,1524,1528,1532,1536,1540,1544,1548,1552,1556,1560,1564,1568,1572,1576,1580,1584,1588,1592,1596,1600,1604,1608,1612,1616,1620,1624,1628,1632],{"title":1353,"path":1354,"stem":1355},"Що таке десктопна розробка?","/csharp/desktop-ui/what-is-desktop-dev","01.csharp/12.desktop-ui/01.what-is-desktop-dev",{"title":1357,"path":1358,"stem":1359},"Архітектура WPF — як влаштований графічний інтерфейс","/csharp/desktop-ui/wpf-architecture","01.csharp/12.desktop-ui/02.wpf-architecture",{"title":1361,"path":1362,"stem":1363},"Перший WPF-проєкт — від нуля до вікна","/csharp/desktop-ui/first-wpf-app","01.csharp/12.desktop-ui/03.first-wpf-app",{"title":1365,"path":1366,"stem":1367},"Перший Avalonia-проєкт: WPF для всіх платформ","/csharp/desktop-ui/03a.first-avalonia-app","01.csharp/12.desktop-ui/03a.first-avalonia-app",{"title":1369,"path":1370,"stem":1371},"XAML: декларативний інтерфейс","/csharp/desktop-ui/xaml-basics","01.csharp/12.desktop-ui/04.xaml-basics",{"title":1373,"path":1374,"stem":1375},"Fluent UI у WPF — сучасний дизайн Windows 11","/csharp/desktop-ui/04a.wpf-fluent-ui","01.csharp/12.desktop-ui/04a.wpf-fluent-ui",{"title":1377,"path":1378,"stem":1379},"WPF UI — сучасна бібліотека Fluent контролів","/csharp/desktop-ui/04b.wpf-ui-library","01.csharp/12.desktop-ui/04b.wpf-ui-library",{"title":1381,"path":1382,"stem":1383},"HandyControl — велика бібліотека UI контролів для WPF","/csharp/desktop-ui/04c.handycontrol-library","01.csharp/12.desktop-ui/04c.handycontrol-library",{"title":1385,"path":1386,"stem":1387},"Простори імен та ресурси XAML","/csharp/desktop-ui/xaml-namespaces-resources","01.csharp/12.desktop-ui/05.xaml-namespaces-resources",{"title":1389,"path":1390,"stem":1391},"XAML в Avalonia: ключові відмінності від WPF","/csharp/desktop-ui/05a.avalonia-xaml-differences","01.csharp/12.desktop-ui/05a.avalonia-xaml-differences",{"title":1393,"path":1394,"stem":1395},"Розширення розмітки XAML (Markup Extensions)","/csharp/desktop-ui/xaml-markup-extensions","01.csharp/12.desktop-ui/06.xaml-markup-extensions",{"title":1397,"path":1398,"stem":1399},"Панелі Layout: StackPanel, WrapPanel, DockPanel","/csharp/desktop-ui/layout-panels-part1","01.csharp/12.desktop-ui/07.layout-panels-part1",{"title":1401,"path":1402,"stem":1403},"Grid, Canvas, UniformGrid","/csharp/desktop-ui/layout-panels-part2","01.csharp/12.desktop-ui/07.layout-panels-part2",{"title":1405,"path":1406,"stem":1407},"Просунуті техніки Layout","/csharp/desktop-ui/layout-advanced","01.csharp/12.desktop-ui/08.layout-advanced",{"title":1409,"path":1410,"stem":1411},"Адаптивний Layout та найкращі практики","/csharp/desktop-ui/layout-responsive","01.csharp/12.desktop-ui/09.layout-responsive",{"title":1413,"path":1414,"stem":1415},"Layout в Avalonia: відмінності та нові можливості","/csharp/desktop-ui/09a.layout-avalonia","01.csharp/12.desktop-ui/09a.layout-avalonia",{"title":1417,"path":1418,"stem":1419},"Button, Image, ProgressBar та інші базові контроли","/csharp/desktop-ui/basic-controls","01.csharp/12.desktop-ui/10.basic-controls",{"title":1421,"path":1422,"stem":1423},"Контроли в Avalonia: відмінності від WPF","/csharp/desktop-ui/10a.controls-avalonia","01.csharp/12.desktop-ui/10a.controls-avalonia",{"title":1425,"path":1426,"stem":1427},"Текстові контроли — TextBlock, TextBox, RichTextBox","/csharp/desktop-ui/text-controls","01.csharp/12.desktop-ui/11.text-controls",{"title":1429,"path":1430,"stem":1431},"Контроли вибору — CheckBox, RadioButton, ComboBox, ListBox, DatePicker","/csharp/desktop-ui/selection-controls","01.csharp/12.desktop-ui/12.selection-controls",{"title":1433,"path":1434,"stem":1435},"Content Model — GroupBox, Expander, TabControl, StatusBar","/csharp/desktop-ui/content-controls","01.csharp/12.desktop-ui/13.content-controls",{"title":1437,"path":1438,"stem":1439},"UI/UX принципи десктопних застосунків","/csharp/desktop-ui/13a.ui-ux-principles","01.csharp/12.desktop-ui/13a.ui-ux-principles",{"title":1441,"path":1442,"stem":1443},"Dependency Properties — Концепція та Value Resolution","/csharp/desktop-ui/dependency-properties-part1","01.csharp/12.desktop-ui/14.dependency-properties-part1",{"title":1445,"path":1446,"stem":1447},"Avalonia Property System — StyledProperty та DirectProperty","/csharp/desktop-ui/14a.avalonia-property-system","01.csharp/12.desktop-ui/14a.avalonia-property-system",{"title":1449,"path":1450,"stem":1451},"Attached Properties — Властивості без меж","/csharp/desktop-ui/attached-properties","01.csharp/12.desktop-ui/15.attached-properties",{"title":1453,"path":1454,"stem":1455},"Routed Events — Маршрутизація подій у WPF","/csharp/desktop-ui/routed-events","01.csharp/12.desktop-ui/16.routed-events",{"title":1457,"path":1458,"stem":1459},"Data Binding — Від Code-Behind до Декларативності","/csharp/desktop-ui/data-binding-basics-part1","01.csharp/12.desktop-ui/17.data-binding-basics-part1",{"title":1461,"path":1462,"stem":1463},"INotifyPropertyChanged — Живе оновлення UI","/csharp/desktop-ui/data-binding-basics-part2","01.csharp/12.desktop-ui/17.data-binding-basics-part2",{"title":1465,"path":1466,"stem":1467},"Compiled Bindings в Avalonia — Безпека на етапі компіляції","/csharp/desktop-ui/17a.avalonia-compiled-bindings","01.csharp/12.desktop-ui/17a.avalonia-compiled-bindings",{"title":1469,"path":1470,"stem":1471},"Просунутий Data Binding — ElementName, RelativeSource, MultiBinding","/csharp/desktop-ui/data-binding-advanced","01.csharp/12.desktop-ui/18.data-binding-advanced",{"title":1473,"path":1474,"stem":1475},"Value Converters — Перетворення типів даних у Data Binding","/csharp/desktop-ui/value-converters","01.csharp/12.desktop-ui/19.value-converters",{"title":1477,"path":1478,"stem":1479},"Data Templates — Візуалізація об'єктів у WPF","/csharp/desktop-ui/data-templates","01.csharp/12.desktop-ui/20.data-templates",{"title":1481,"path":1482,"stem":1483},"Collections Binding Part 1 — ObservableCollection та ItemsControl","/csharp/desktop-ui/collections-binding-part1","01.csharp/12.desktop-ui/21.collections-binding-part1",{"title":1485,"path":1486,"stem":1487},"Collections Binding Part 2 — ICollectionView, Filtering, Sorting та Virtualization","/csharp/desktop-ui/collections-binding-part2","01.csharp/12.desktop-ui/21.collections-binding-part2",{"title":1489,"path":1490,"stem":1491},"MVVM Pattern — Від Spaghetti Code до архітектури","/csharp/desktop-ui/mvvm-pattern","01.csharp/12.desktop-ui/22.mvvm-pattern",{"title":1493,"path":1494,"stem":1495},"ViewModel Implementation — Від BaseViewModel до валідації","/csharp/desktop-ui/viewmodel-implementation","01.csharp/12.desktop-ui/23.viewmodel-implementation",{"title":1497,"path":1498,"stem":1499},"Commands — Від event handlers до декларативних команд","/csharp/desktop-ui/commands","01.csharp/12.desktop-ui/24.commands",{"title":1501,"path":1502,"stem":1503},"MVVM Toolkit — MVVM без boilerplate через Source Generators","/csharp/desktop-ui/mvvm-toolkit","01.csharp/12.desktop-ui/25.mvvm-toolkit",{"title":1505,"path":1506,"stem":1507},"Messenger Pattern — Комунікація між ViewModel без прямих посилань","/csharp/desktop-ui/messenger-pattern","01.csharp/12.desktop-ui/26.messenger-pattern",{"title":1509,"path":1510,"stem":1511},"Стилі WPF — CSS для десктопу","/csharp/desktop-ui/styles-basics","01.csharp/12.desktop-ui/27.styles-basics",{"title":1513,"path":1514,"stem":1515},"CSS-like стилі Avalonia","/csharp/desktop-ui/27a.avalonia-css-styling","01.csharp/12.desktop-ui/27a.avalonia-css-styling",{"title":1517,"path":1518,"stem":1519},"Control Templates — Частина 1. Концепція та TemplateBinding","/csharp/desktop-ui/control-templates-part1","01.csharp/12.desktop-ui/28.control-templates-part1",{"title":1521,"path":1522,"stem":1523},"Control Templates — Частина 2. Named Parts та ContentPresenter","/csharp/desktop-ui/control-templates-part2","01.csharp/12.desktop-ui/28.control-templates-part2",{"title":1525,"path":1526,"stem":1527},"Control Themes в Avalonia — нова ера стилізації","/csharp/desktop-ui/28a.avalonia-control-themes","01.csharp/12.desktop-ui/28a.avalonia-control-themes",{"title":1529,"path":1530,"stem":1531},"Triggers та Visual State Manager у WPF","/csharp/desktop-ui/triggers-visual-states","01.csharp/12.desktop-ui/29.triggers-visual-states",{"title":1533,"path":1534,"stem":1535},"Pseudo-classes в Avalonia — замість WPF Triggers","/csharp/desktop-ui/29a.avalonia-pseudo-classes","01.csharp/12.desktop-ui/29a.avalonia-pseudo-classes",{"title":1537,"path":1538,"stem":1539},"Теми та ресурсні словники у WPF","/csharp/desktop-ui/resources-themes","01.csharp/12.desktop-ui/30.resources-themes",{"title":1541,"path":1542,"stem":1543},"Avalonia Themes — Fluent Design та система тематизації","/csharp/desktop-ui/30a.avalonia-themes-fluent","01.csharp/12.desktop-ui/30a.avalonia-themes-fluent",{"title":1545,"path":1546,"stem":1547},"Контроли колекцій — глибоке занурення","/csharp/desktop-ui/collection-controls","01.csharp/12.desktop-ui/31.collection-controls",{"title":1549,"path":1550,"stem":1551},"DataGrid — колонки та базове відображення","/csharp/desktop-ui/datagrid-part1","01.csharp/12.desktop-ui/32.datagrid-part1",{"title":1553,"path":1554,"stem":1555},"DataGrid — сортування, фільтрація, редагування","/csharp/desktop-ui/datagrid-part2","01.csharp/12.desktop-ui/32.datagrid-part2",{"title":1557,"path":1558,"stem":1559},"TreeView та GridView","/csharp/desktop-ui/treeview-listview","01.csharp/12.desktop-ui/33.treeview-listview",{"title":1561,"path":1562,"stem":1563},"Меню, Toolbar, ContextMenu, StatusBar","/csharp/desktop-ui/menus-toolbars","01.csharp/12.desktop-ui/34.menus-toolbars",{"title":1565,"path":1566,"stem":1567},"Навігація та керування вікнами. Частина 1: вікна та сторінки","/csharp/desktop-ui/navigation-windows-part1","01.csharp/12.desktop-ui/35.navigation-windows-part1",{"title":1569,"path":1570,"stem":1571},"Навігація та керування вікнами. Частина 2: MVVM-навігація","/csharp/desktop-ui/navigation-windows-part2","01.csharp/12.desktop-ui/35.navigation-windows-part2",{"title":1573,"path":1574,"stem":1575},"Avalonia — Навігація та діалоги","/csharp/desktop-ui/35a.avalonia-navigation-dialogs","01.csharp/12.desktop-ui/35a.avalonia-navigation-dialogs",{"title":1577,"path":1578,"stem":1579},"Діалоги та File Pickers у WPF","/csharp/desktop-ui/dialogs-file-pickers","01.csharp/12.desktop-ui/36.dialogs-file-pickers",{"title":1581,"path":1582,"stem":1583},"UserControl: компонентний підхід у WPF","/csharp/desktop-ui/user-controls","01.csharp/12.desktop-ui/37.user-controls",{"title":1585,"path":1586,"stem":1587},"Custom Controls: Lookless Controls у WPF","/csharp/desktop-ui/custom-controls","01.csharp/12.desktop-ui/38.custom-controls",{"title":1589,"path":1590,"stem":1591},"Avalonia TemplatedControl — Lookless Controls","/csharp/desktop-ui/38a.avalonia-templated-controls","01.csharp/12.desktop-ui/38a.avalonia-templated-controls",{"title":1593,"path":1594,"stem":1595},"Анімації у WPF: Storyboard та Easing Functions","/csharp/desktop-ui/animations-transitions","01.csharp/12.desktop-ui/39.animations-transitions",{"title":1597,"path":1598,"stem":1599},"Анімації в Avalonia","/csharp/desktop-ui/39a.avalonia-animations","01.csharp/12.desktop-ui/39a.avalonia-animations",{"title":1601,"path":1602,"stem":1603},"2D Графіка та Мультимедіа у WPF","/csharp/desktop-ui/media-graphics","01.csharp/12.desktop-ui/40.media-graphics",{"title":1605,"path":1606,"stem":1607},"Dependency Injection у WPF та Avalonia","/csharp/desktop-ui/di-integration","01.csharp/12.desktop-ui/41.di-integration",{"title":1609,"path":1610,"stem":1611},"SQLite та EF Core у десктопних додатках","/csharp/desktop-ui/data-persistence-part1","01.csharp/12.desktop-ui/42.data-persistence-part1",{"title":1613,"path":1614,"stem":1615},"Repository Pattern та Unit of Work","/csharp/desktop-ui/data-persistence-part2","01.csharp/12.desktop-ui/43.data-persistence-part2",{"title":1617,"path":1618,"stem":1619},"Тестування ViewModels","/csharp/desktop-ui/viewmodel-testing","01.csharp/12.desktop-ui/44.viewmodel-testing",{"title":1621,"path":1622,"stem":1623},"Avalonia Headless Testing — тестування UI без вікон","/csharp/desktop-ui/44a.avalonia-headless-testing","01.csharp/12.desktop-ui/44a.avalonia-headless-testing",{"title":1625,"path":1626,"stem":1627},"Кросплатформна розробка з Avalonia","/csharp/desktop-ui/avalonia-cross-platform","01.csharp/12.desktop-ui/45.avalonia-cross-platform",{"title":1629,"path":1630,"stem":1631},"Пакування та розгортання Avalonia додатків","/csharp/desktop-ui/avalonia-packaging-deployment","01.csharp/12.desktop-ui/46.avalonia-packaging-deployment",{"title":1633,"path":1634,"stem":1635},"Розгортання WPF застосунків","/csharp/desktop-ui/wpf-packaging-deployment","01.csharp/12.desktop-ui/47.wpf-packaging-deployment",{"title":1637,"path":1638,"stem":1639},"C# & .NET: The Ultimate Roadmap","/csharp/roadmap","01.csharp/roadmap",{"title":1641,"icon":1642,"path":1643,"stem":1644,"children":1645,"page":59},"C++","i-devicon-cplusplus","/cpp","02.cpp",[1646,1650,1654,1658,1662,1666,1670,1674,1678,1681,1685,1689,1693,1697,1701,1705,1709,1713,1717,1721,1725,1729,1733,1737,1741,1745,1749,1753,1757,1761],{"title":1647,"path":1648,"stem":1649},"Вступ у програмування та алгоритми","/cpp/intro-algorithms","02.cpp/01.intro-algorithms",{"title":1651,"path":1652,"stem":1653},"Code Style: угоди про оформлення коду","/cpp/code-style","02.cpp/02.code-style",{"title":1655,"path":1656,"stem":1657},"Середовище розробки та перший проєкт","/cpp/ide-setup","02.cpp/03.ide-setup",{"title":1659,"path":1660,"stem":1661},"Вивід даних на екран","/cpp/data-output","02.cpp/04.data-output",{"title":1663,"path":1664,"stem":1665},"Типи даних, змінні та константи","/cpp/data-types-variables","02.cpp/05.data-types-variables",{"title":1667,"path":1668,"stem":1669},"Ввід даних з клавіатури","/cpp/data-input","02.cpp/06.data-input",{"title":1671,"path":1672,"stem":1673},"Оператори, перетворення типів та логічні операції","/cpp/operators-type-conversion","02.cpp/07.operators-type-conversion",{"title":1675,"path":1676,"stem":1677},"Цикли","/cpp/loops","02.cpp/08.loops",{"title":32,"path":1679,"stem":1680},"/cpp/arrays","02.cpp/09.arrays",{"title":1682,"path":1683,"stem":1684},"Алгоритми сортування та аналіз складності","/cpp/sorting","02.cpp/10.sorting",{"title":1686,"path":1687,"stem":1688},"Алгоритми пошуку","/cpp/searching","02.cpp/11.searching",{"title":1690,"path":1691,"stem":1692},"Функції: основи","/cpp/functions-basics","02.cpp/12.functions-basics",{"title":1694,"path":1695,"stem":1696},"Функції: прототипи, область видимості та додаткові можливості","/cpp/functions-scope","02.cpp/13.functions-scope",{"title":1698,"path":1699,"stem":1700},"Функції: перевантаження та шаблони","/cpp/functions-overloading-templates","02.cpp/14.functions-overloading-templates",{"title":1702,"path":1703,"stem":1704},"Вказівники: основи","/cpp/pointers-basics","02.cpp/15.pointers-basics",{"title":1706,"path":1707,"stem":1708},"Посилання (References)","/cpp/references","02.cpp/16.references",{"title":1710,"path":1711,"stem":1712},"Вказівники, const і масиви","/cpp/pointers-const-arrays","02.cpp/17.pointers-const-arrays",{"title":1714,"path":1715,"stem":1716},"Адресна арифметика","/cpp/pointer-arithmetic","02.cpp/18.pointer-arithmetic",{"title":1718,"path":1719,"stem":1720},"Динамічна пам'ять","/cpp/dynamic-memory","02.cpp/19.dynamic-memory",{"title":1722,"path":1723,"stem":1724},"Вказівники типу void","/cpp/void-pointers","02.cpp/20.void-pointers",{"title":1726,"path":1727,"stem":1728},"Вказівники на вказівники","/cpp/pointers-to-pointers","02.cpp/21.pointers-to-pointers",{"title":1730,"path":1731,"stem":1732},"Оператор доступу до членів через вказівник (->)","/cpp/member-access-operator","02.cpp/22.member-access-operator",{"title":1734,"path":1735,"stem":1736},"Цикл for-each (Range-based for)","/cpp/foreach-loop","02.cpp/23.foreach-loop",{"title":1738,"path":1739,"stem":1740},"Вказівники на функції","/cpp/function-pointers","02.cpp/24.function-pointers",{"title":1742,"path":1743,"stem":1744},"Лямбда-вирази","/cpp/lambdas","02.cpp/25.lambdas",{"title":1746,"path":1747,"stem":1748},"Лямбда-захоплення","/cpp/lambda-captures","02.cpp/26.lambda-captures",{"title":1750,"path":1751,"stem":1752},"Еліпсис","/cpp/ellipsis","02.cpp/27.ellipsis",{"title":1754,"path":1755,"stem":1756},"Аргументи командного рядка","/cpp/command-line-arguments","02.cpp/28.command-line-arguments",{"title":1758,"path":1759,"stem":1760},"Перерахування (enum)","/cpp/enum","02.cpp/29.enum",{"title":1762,"path":1763,"stem":1764},"План навчання: Курс C++ — Продовження (Статті 29–60+)","/cpp/curriculum-plan","02.cpp/curriculum-plan",{"title":1766,"icon":1767,"path":1768,"stem":1769,"children":1770,"page":59},"JavaScript","i-devicon-javascript","/javascript","03.javascript",[1771,1797,1851,1873,2177,2215],{"title":1772,"icon":1773,"path":1774,"stem":1775,"children":1776,"page":59},"Events","i-lucide-mouse-pointer-click","/javascript/events","03.javascript/01.events",[1777,1781,1785,1789,1793],{"title":1778,"path":1779,"stem":1780},"Вступ до подій браузера","/javascript/events/intro","03.javascript/01.events/01.intro",{"title":1782,"path":1783,"stem":1784},"Бульбашковий механізм (Bubbling) та занурення (Capturing)","/javascript/events/bubbling-capturing","03.javascript/01.events/02.bubbling-capturing",{"title":1786,"path":1787,"stem":1788},"Делегування подій (Event Delegation)","/javascript/events/delegate-events","03.javascript/01.events/03.delegate-events",{"title":1790,"path":1791,"stem":1792},"Типові дії браузера та preventDefault()","/javascript/events/prevent-default","03.javascript/01.events/04.prevent-default",{"title":1794,"path":1795,"stem":1796},"Запуск користувацьких подій (Custom Events)","/javascript/events/custom-events","03.javascript/01.events/05.custom-events",{"title":1798,"icon":1799,"path":1800,"stem":1801,"children":1802,"page":59},"Network","i-lucide-globe","/javascript/network","03.javascript/02.network",[1803,1807,1811,1815,1819,1823,1827,1831,1835,1839,1843,1847],{"title":1804,"path":1805,"stem":1806},"Fetch API - Сучасний підхід до HTTP-запитів","/javascript/network/01-fetch-api","03.javascript/02.network/01-fetch-api",{"title":1808,"path":1809,"stem":1810},"FormData - Робота з формами та файлами","/javascript/network/02-formdata","03.javascript/02.network/02-formdata",{"title":1812,"path":1813,"stem":1814},"Відстеження прогресу завантаження","/javascript/network/03-download-progress","03.javascript/02.network/03-download-progress",{"title":1816,"path":1817,"stem":1818},"Переривання fetch-запитів","/javascript/network/04-abort-requests","03.javascript/02.network/04-abort-requests",{"title":1820,"path":1821,"stem":1822},"CORS - Запити між різними джерелами","/javascript/network/05-cors","03.javascript/02.network/05-cors",{"title":1824,"path":1825,"stem":1826},"Fetch API - Повний довідник опцій","/javascript/network/06-fetch-options","03.javascript/02.network/06-fetch-options",{"title":1828,"path":1829,"stem":1830},"URL Objects - Робота з посиланнями","/javascript/network/07-url-objects","03.javascript/02.network/07-url-objects",{"title":1832,"path":1833,"stem":1834},"XMLHttpRequest - AJAX та низькорівневі запити","/javascript/network/08-xmlhttprequest","03.javascript/02.network/08-xmlhttprequest",{"title":1836,"path":1837,"stem":1838},"Відновлюване завантаження файлів","/javascript/network/09-resumable-upload","03.javascript/02.network/09-resumable-upload",{"title":1840,"path":1841,"stem":1842},"Cookies, document.cookie та світ після \"Cookiepocalypse\"","/javascript/network/10-cookies","03.javascript/02.network/10-cookies",{"title":1844,"path":1845,"stem":1846},"js-cookie: Керування Cookies без Болю","/javascript/network/11-js-cookie","03.javascript/02.network/11-js-cookie",{"title":1848,"path":1849,"stem":1850},"Axios: Потужний HTTP-клієнт для JavaScript","/javascript/network/12-axios","03.javascript/02.network/12-axios",{"title":1852,"icon":1853,"path":1854,"stem":1855,"children":1856,"page":59},"Bom","i-lucide-monitor","/javascript/bom","03.javascript/03.bom",[1857,1861,1865,1869],{"title":1858,"path":1859,"stem":1860},"LocalStorage, SessionStorage та patterns збереження даних","/javascript/bom/01-localstorage","03.javascript/03.bom/01-localstorage",{"title":1862,"path":1863,"stem":1864},"Location Object - Керування адресою сторінки","/javascript/bom/02-location-object","03.javascript/03.bom/02-location-object",{"title":1866,"path":1867,"stem":1868},"History API - Керування історією браузера","/javascript/bom/03-history-api","03.javascript/03.bom/03-history-api",{"title":1870,"path":1871,"stem":1872},"Navigator Object - Ідентифікація та Можливості Пристрою","/javascript/bom/04-navigator-object","03.javascript/03.bom/04-navigator-object",{"title":1874,"icon":1875,"path":1876,"stem":1877,"children":1878},"React","i-devicon-react","/javascript/react","03.javascript/04.react/index",[1879,1880,1884,1888,1892,1896,1959,1994,2146],{"title":1874,"path":1876,"stem":1877},{"title":1881,"path":1882,"stem":1883},"Робота з Формами в React","/javascript/react/react-forms","03.javascript/04.react/01.react-forms",{"title":1885,"path":1886,"stem":1887},"React Hook Form: Професійна Робота з Формами","/javascript/react/react-hook-form","03.javascript/04.react/02.react-hook-form",{"title":1889,"path":1890,"stem":1891},"React Hook Form: Глибоке Розуміння Архітектури та Оптимізації","/javascript/react/react-hook-form-new","03.javascript/04.react/02.react-hook-form-new",{"title":1893,"path":1894,"stem":1895},"Axios та React: Професійна Архітектура Запитів","/javascript/react/data-fetching-axios","03.javascript/04.react/03.data-fetching-axios",{"title":1897,"icon":132,"path":1898,"stem":1899,"children":1900},"Tanstack Query","/javascript/react/tanstack-query","03.javascript/04.react/04.tanstack-query/index",[1901,1903,1907,1911,1915,1919,1923,1927,1931,1935,1939,1943,1947,1951,1955],{"title":1902,"path":1898,"stem":1899},"TanStack Query: Майстерність Керування Станом Сервера",{"title":1904,"path":1905,"stem":1906},"Парадигма Server State: Чому useEffect недостатньо","/javascript/react/tanstack-query/server-state-paradigm","03.javascript/04.react/04.tanstack-query/01.server-state-paradigm",{"title":1908,"path":1909,"stem":1910},"Встановлення та Налаштування: Фундамент","/javascript/react/tanstack-query/installation-and-devtools","03.javascript/04.react/04.tanstack-query/02.installation-and-devtools",{"title":1912,"path":1913,"stem":1914},"Основи Запитів та Магія Ключів","/javascript/react/tanstack-query/query-basics-and-keys","03.javascript/04.react/04.tanstack-query/03.query-basics-and-keys",{"title":1916,"path":1917,"stem":1918},"Синхронізація Даних: Життєвий Цикл Запиту","/javascript/react/tanstack-query/data-synchronization","03.javascript/04.react/04.tanstack-query/04.data-synchronization",{"title":1920,"path":1921,"stem":1922},"Мутації та Інвалідація: Зміна Даних","/javascript/react/tanstack-query/mutations-and-invalidation","03.javascript/04.react/04.tanstack-query/05.mutations-and-invalidation",{"title":1924,"path":1925,"stem":1926},"Оптимістичні Оновлення: Швидше за Світло","/javascript/react/tanstack-query/optimistic-updates","03.javascript/04.react/04.tanstack-query/06.optimistic-updates",{"title":1928,"path":1929,"stem":1930},"Пагінація та Infinite Scroll","/javascript/react/tanstack-query/pagination-and-load-more","03.javascript/04.react/04.tanstack-query/07.pagination-and-load-more",{"title":1932,"path":1933,"stem":1934},"Просунуті Патерни та Оптимізація","/javascript/react/tanstack-query/advanced-patterns","03.javascript/04.react/04.tanstack-query/08.advanced-patterns",{"title":1936,"path":1937,"stem":1938},"Архітектура та Best Practices","/javascript/react/tanstack-query/architecture-and-best-practices","03.javascript/04.react/04.tanstack-query/09.architecture-and-best-practices",{"title":1940,"path":1941,"stem":1942},"Server-Side Rendering (SSR) та Гідратація","/javascript/react/tanstack-query/server-side-rendering","03.javascript/04.react/04.tanstack-query/10.server-side-rendering",{"title":1944,"path":1945,"stem":1946},"Стратегії Тестування","/javascript/react/tanstack-query/testing-strategies","03.javascript/04.react/04.tanstack-query/11.testing-strategies",{"title":1948,"path":1949,"stem":1950},"Аутентифікація та Обробка Помилок","/javascript/react/tanstack-query/authentication-and-errors","03.javascript/04.react/04.tanstack-query/12.authentication-and-errors",{"title":1952,"path":1953,"stem":1954},"React Suspense та Майбутнє","/javascript/react/tanstack-query/react-suspense","03.javascript/04.react/04.tanstack-query/13.react-suspense",{"title":1956,"path":1957,"stem":1958},"Глибоке Занурення в Продуктивність","/javascript/react/tanstack-query/performance-deep-dive","03.javascript/04.react/04.tanstack-query/14.performance-deep-dive",{"title":1960,"icon":1875,"path":1961,"stem":1962,"children":1963},"React Router","/javascript/react/react-router","03.javascript/04.react/05.react-router/index",[1964,1966,1970,1974,1978,1982,1986,1990],{"title":1965,"path":1961,"stem":1962},"React Router: Навігаційна система сучасного вебу",{"title":1967,"path":1968,"stem":1969},"Налаштування та Базовий Роутинг","/javascript/react/react-router/setup-and-basic-routing","03.javascript/04.react/05.react-router/01.setup-and-basic-routing",{"title":1971,"path":1972,"stem":1973},"Динамічна Навігація","/javascript/react/react-router/navigation-and-links","03.javascript/04.react/05.react-router/02.navigation-and-links",{"title":1975,"path":1976,"stem":1977},"Вкладені Маршрути та Макети","/javascript/react/react-router/nested-routes-and-layouts","03.javascript/04.react/05.react-router/03.nested-routes-and-layouts",{"title":1979,"path":1980,"stem":1981},"Динамічні Маршрути та Параметри","/javascript/react/react-router/dynamic-routing","03.javascript/04.react/05.react-router/04.dynamic-routing",{"title":1983,"path":1984,"stem":1985},"Data APIs: Loaders та Actions","/javascript/react/react-router/data-loading","03.javascript/04.react/05.react-router/05.data-loading",{"title":1987,"path":1988,"stem":1989},"Просунуті Патерни","/javascript/react/react-router/advanced-patterns","03.javascript/04.react/05.react-router/06.advanced-patterns",{"title":1991,"path":1992,"stem":1993},"Legacy Routing: Компонентний підхід","/javascript/react/react-router/legacy-routing","03.javascript/04.react/05.react-router/07.legacy-routing",{"title":1995,"icon":132,"path":1996,"stem":1997,"children":1998},"Redux","/javascript/react/redux","03.javascript/04.react/06.redux/index",[1999,2001,2017,2046,2055,2076,2092,2121],{"title":2000,"path":1996,"stem":1997},"Redux: Еволюція управління станом",{"title":14,"icon":15,"path":2002,"stem":2003,"children":2004,"page":59},"/javascript/react/redux/fundamentals","03.javascript/04.react/06.redux/01.fundamentals",[2005,2009,2013],{"title":2006,"path":2007,"stem":2008},"Вступ до State Management","/javascript/react/redux/fundamentals/intro-state-management","03.javascript/04.react/06.redux/01.fundamentals/01.intro-state-management",{"title":2010,"path":2011,"stem":2012},"Філософія Redux та Три Принципи","/javascript/react/redux/fundamentals/redux-philosophy","03.javascript/04.react/06.redux/01.fundamentals/02.redux-philosophy",{"title":2014,"path":2015,"stem":2016},"Чисті функції та Іммутабельність","/javascript/react/redux/fundamentals/pure-functions-immutability","03.javascript/04.react/06.redux/01.fundamentals/03.pure-functions-immutability",{"title":2018,"icon":132,"path":2019,"stem":2020,"children":2021,"page":59},"Classic Redux","/javascript/react/redux/classic-redux","03.javascript/04.react/06.redux/02.classic-redux",[2022,2026,2030,2034,2038,2042],{"title":2023,"path":2024,"stem":2025},"Створення Store (Classic Redux)","/javascript/react/redux/classic-redux/store-setup","03.javascript/04.react/06.redux/02.classic-redux/01.store-setup",{"title":2027,"path":2028,"stem":2029},"Actions, Constants та Action Creators","/javascript/react/redux/classic-redux/actions-constants","03.javascript/04.react/06.redux/02.classic-redux/02.actions-constants",{"title":2031,"path":2032,"stem":2033},"Логіка Reducers","/javascript/react/redux/classic-redux/reducers","03.javascript/04.react/06.redux/02.classic-redux/03.reducers",{"title":2035,"path":2036,"stem":2037},"Комбінування Reducers (Root Reducer)","/javascript/react/redux/classic-redux/data-flow","03.javascript/04.react/06.redux/02.classic-redux/04.data-flow",{"title":2039,"path":2040,"stem":2041},"Підключення до React (React-Redux)","/javascript/react/redux/classic-redux/react-redux-connection","03.javascript/04.react/06.redux/02.classic-redux/05.react-redux-connection",{"title":2043,"path":2044,"stem":2045},"Middleware та Асинхронність (Redux Thunk)","/javascript/react/redux/classic-redux/middleware-thunk","03.javascript/04.react/06.redux/02.classic-redux/06.middleware-thunk",{"title":2047,"icon":132,"path":2048,"stem":2049,"children":2050,"page":59},"Transition To Rtk","/javascript/react/redux/transition-to-rtk","03.javascript/04.react/06.redux/03.transition-to-rtk",[2051],{"title":2052,"path":2053,"stem":2054},"Проблеми класичного Redux","/javascript/react/redux/transition-to-rtk/problems-with-classic","03.javascript/04.react/06.redux/03.transition-to-rtk/01.problems-with-classic",{"title":2056,"icon":132,"path":2057,"stem":2058,"children":2059,"page":59},"Redux Toolkit","/javascript/react/redux/redux-toolkit","03.javascript/04.react/06.redux/04.redux-toolkit",[2060,2064,2068,2072],{"title":2061,"path":2062,"stem":2063},"Налаштування Store з configureStore","/javascript/react/redux/redux-toolkit/configure-store","03.javascript/04.react/06.redux/04.redux-toolkit/01.configure-store",{"title":2065,"path":2066,"stem":2067},"createSlice: Революція в Redux","/javascript/react/redux/redux-toolkit/create-slice","03.javascript/04.react/06.redux/04.redux-toolkit/02.create-slice",{"title":2069,"path":2070,"stem":2071},"Асинхронність з createAsyncThunk","/javascript/react/redux/redux-toolkit/async-thunks","03.javascript/04.react/06.redux/04.redux-toolkit/03.async-thunks",{"title":2073,"path":2074,"stem":2075},"04. Entity Adapter: Керування нормалізованим станом","/javascript/react/redux/redux-toolkit/entity-adapter","03.javascript/04.react/06.redux/04.redux-toolkit/04.entity-adapter",{"title":2077,"icon":92,"path":2078,"stem":2079,"children":2080,"page":59},"Advanced","/javascript/react/redux/advanced","03.javascript/04.react/06.redux/05.advanced",[2081,2085,2089],{"title":2082,"path":2083,"stem":2084},"Мемоізація та Селектори: Повний Гайд по Reselect","/javascript/react/redux/advanced/selectors-reselect","03.javascript/04.react/06.redux/05.advanced/01.selectors-reselect",{"title":2086,"path":2087,"stem":2088},"RTK Query: Архітектура Серверного Кешу","/javascript/react/redux/advanced/rtk-query-intro","03.javascript/04.react/06.redux/05.advanced/02.rtk-query-intro",{"title":1936,"path":2090,"stem":2091},"/javascript/react/redux/advanced/architecture-best-practices","03.javascript/04.react/06.redux/05.advanced/03.architecture-best-practices",{"title":2093,"icon":132,"path":2094,"stem":2095,"children":2096,"page":59},"Project Kanban","/javascript/react/redux/project-kanban","03.javascript/04.react/06.redux/06.project-kanban",[2097,2101,2105,2109,2113,2117],{"title":2098,"path":2099,"stem":2100},"Проєкт: Kanban Board (Trello Clone)","/javascript/react/redux/project-kanban/project-overview","03.javascript/04.react/06.redux/06.project-kanban/01.project-overview",{"title":2102,"path":2103,"stem":2104},"Налаштування та Типізація","/javascript/react/redux/project-kanban/setup-and-types","03.javascript/04.react/06.redux/06.project-kanban/02.setup-and-types",{"title":2106,"path":2107,"stem":2108},"Board Slice: Серце Дошки","/javascript/react/redux/project-kanban/board-slice","03.javascript/04.react/06.redux/06.project-kanban/03.board-slice",{"title":2110,"path":2111,"stem":2112},"Логіка Drag & Drop","/javascript/react/redux/project-kanban/drag-and-drop-logic","03.javascript/04.react/06.redux/06.project-kanban/04.drag-and-drop-logic",{"title":2114,"path":2115,"stem":2116},"Інтеграція з RTK Query","/javascript/react/redux/project-kanban/rtk-query-integration","03.javascript/04.react/06.redux/06.project-kanban/05.rtk-query-integration",{"title":2118,"path":2119,"stem":2120},"Optimistic Updates","/javascript/react/redux/project-kanban/optimistic-updates","03.javascript/04.react/06.redux/06.project-kanban/06.optimistic-updates",{"title":2122,"icon":132,"path":2123,"stem":2124,"children":2125,"page":59},"Testing","/javascript/react/redux/testing","03.javascript/04.react/06.redux/07.testing",[2126,2130,2134,2138,2142],{"title":2127,"path":2128,"stem":2129},"Тестування Redux","/javascript/react/redux/testing/intro-testing","03.javascript/04.react/06.redux/07.testing/01.intro-testing",{"title":2131,"path":2132,"stem":2133},"Тестування Reducers","/javascript/react/redux/testing/testing-reducers","03.javascript/04.react/06.redux/07.testing/02.testing-reducers",{"title":2135,"path":2136,"stem":2137},"Тестування Селекторів","/javascript/react/redux/testing/testing-selectors","03.javascript/04.react/06.redux/07.testing/03.testing-selectors",{"title":2139,"path":2140,"stem":2141},"Тестування Компонентів (Integration)","/javascript/react/redux/testing/testing-components","03.javascript/04.react/06.redux/07.testing/04.testing-components",{"title":2143,"path":2144,"stem":2145},"Тестування Async Thunks","/javascript/react/redux/testing/testing-thunks","03.javascript/04.react/06.redux/07.testing/05.testing-thunks",{"title":2147,"icon":132,"path":2148,"stem":2149,"children":2150},"Ui Libraries","/javascript/react/ui-libraries","03.javascript/04.react/07.ui-libraries/index",[2151,2153,2157,2161,2165,2169,2173],{"title":2152,"path":2148,"stem":2149},"UI Бібліотеки в React",{"title":2154,"path":2155,"stem":2156},"Вступ до UI Бібліотек: Навіщо Винаходити Велосипед Двічі?","/javascript/react/ui-libraries/introduction-to-ui-libraries","03.javascript/04.react/07.ui-libraries/01.introduction-to-ui-libraries",{"title":2158,"path":2159,"stem":2160},"Філософія shadcn/ui: \"Not a Component Library\"","/javascript/react/ui-libraries/shadcn-philosophy","03.javascript/04.react/07.ui-libraries/02.shadcn-philosophy",{"title":2162,"path":2163,"stem":2164},"Установка та Налаштування shadcn/ui","/javascript/react/ui-libraries/shadcn-installation","03.javascript/04.react/07.ui-libraries/03.shadcn-installation",{"title":2166,"path":2167,"stem":2168},"Базові Компоненти shadcn/ui: Фундамент Інтерфейсу","/javascript/react/ui-libraries/shadcn-components-basics","03.javascript/04.react/07.ui-libraries/04.shadcn-components-basics",{"title":2170,"path":2171,"stem":2172},"Компоненти Форм: Побудова Інтерактивних Form","/javascript/react/ui-libraries/shadcn-components-forms","03.javascript/04.react/07.ui-libraries/05.shadcn-components-forms",{"title":2174,"path":2175,"stem":2176},"Складні Компоненти: Dialog, Dropdown, Table та Command","/javascript/react/ui-libraries/shadcn-components-advanced","03.javascript/04.react/07.ui-libraries/06.shadcn-components-advanced",{"title":2178,"icon":2179,"path":2180,"stem":2181,"children":2182,"page":59},"TypeScript","i-devicon-typescript","/javascript/typescript","03.javascript/05.typescript",[2183,2187,2191,2195,2199,2203,2207,2211],{"title":2184,"path":2185,"stem":2186},"TypeScript: Броня для вашого коду","/javascript/typescript/intro-and-basic-types","03.javascript/05.typescript/01.intro-and-basic-types",{"title":2188,"path":2189,"stem":2190},"Майстерність Моделювання Даних: Інтерфейси та Просунуті Типи","/javascript/typescript/interfaces-and-advanced-types","03.javascript/05.typescript/02.interfaces-and-advanced-types",{"title":2192,"path":2193,"stem":2194},"Алхімія Типів: Generics та Utility Types","/javascript/typescript/generics-and-utilities","03.javascript/05.typescript/03.generics-and-utilities",{"title":2196,"path":2197,"stem":2198},"Архітектура та Шаблони: Класи в TypeScript","/javascript/typescript/classes-and-oop","03.javascript/05.typescript/04.classes-and-oop",{"title":2200,"path":2201,"stem":2202},"Продакшн та Екосистема: Advanced Config & Workflow","/javascript/typescript/advanced-patterns-and-config","03.javascript/05.typescript/05.advanced-patterns-and-config",{"title":2204,"path":2205,"stem":2206},"TypeScript у світі React","/javascript/typescript/react-basics","03.javascript/05.typescript/06.react-basics",{"title":2208,"path":2209,"stem":2210},"React + TypeScript: Продвинуті патерни","/javascript/typescript/react-advanced","03.javascript/05.typescript/07.react-advanced",{"title":2212,"path":2213,"stem":2214},"React + TypeScript: Екосистема та бібліотеки","/javascript/typescript/react-ecosystem","03.javascript/05.typescript/08.react-ecosystem",{"title":2216,"path":2217,"stem":2218},"Atomic Design","/javascript/atomic-design","03.javascript/2.atomic-design",{"title":2220,"icon":2221,"path":2222,"stem":2223,"children":2224,"page":59},"Java","i-devicon-java","/java","04.java",[2225,2228,2231,2235,2239,2243,2247],{"title":162,"path":2226,"stem":2227},"/java/data-mapper-part1","04.java/01.data-mapper-part1",{"title":166,"path":2229,"stem":2230},"/java/data-mapper-part2","04.java/02.data-mapper-part2",{"title":2232,"path":2233,"stem":2234},"Service Layer: Організація бізнес-логіки","/java/service-layer","04.java/03.service-layer",{"title":2236,"path":2237,"stem":2238},"Rich Domain Model та State Pattern","/java/rich-domain-model","04.java/04.rich-domain-model",{"title":2240,"path":2241,"stem":2242},"Патерни для складної бізнес-логіки","/java/business-logic-patterns","04.java/05.business-logic-patterns",{"title":2244,"path":2245,"stem":2246},"Обробка помилок та валідація","/java/error-handling-validation","04.java/06.error-handling-validation",{"title":2248,"path":2249,"stem":2250,"children":2251,"page":59},"Проектування баз даних","/java/pr2","04.java/pr2",[2252,2256,2260,2264,2268,2272,2276,2280,2284,2288,2292,2296,2300,2304,2308,2312,2316,2320,2324,2328,2332,2336,2340,2344,2348],{"title":2253,"path":2254,"stem":2255},"Концептуальне моделювання: Мистецтво розуміння предметної області","/java/pr2/conceptual-modeling","04.java/pr2/01.conceptual-modeling",{"title":2257,"path":2258,"stem":2259},"Логічне моделювання: Від бізнес-ідей до структур даних","/java/pr2/logical-modeling","04.java/pr2/02.logical-modeling",{"title":2261,"path":2262,"stem":2263},"Нормалізація: Гігієна даних та боротьба з аномаліями","/java/pr2/normalization","04.java/pr2/03.normalization",{"title":2265,"path":2266,"stem":2267},"Фізична схема: Від абстракції до DDL","/java/pr2/physical-schema","04.java/pr2/04.physical-schema",{"title":2269,"path":2270,"stem":2271},"Архітектурна класифікація таблиць","/java/pr2/table-classification","04.java/pr2/05.table-classification",{"title":2273,"path":2274,"stem":2275},"Database Migrations: Версіонування схеми з Flyway","/java/pr2/database-migrations","04.java/pr2/06.database-migrations",{"title":2277,"path":2278,"stem":2279},"А що, якби це була не реляційна БД?","/java/pr2/beyond-relational","04.java/pr2/07.beyond-relational",{"title":2281,"path":2282,"stem":2283},"Object-Relational Impedance Mismatch: Два світи, що не хочуть дружити","/java/pr2/impedance-mismatch","04.java/pr2/09.impedance-mismatch",{"title":2285,"path":2286,"stem":2287},"JDBC: Перший контакт із базою даних","/java/pr2/jdbc-fundamentals","04.java/pr2/10.jdbc-fundamentals",{"title":2289,"path":2290,"stem":2291},"Якість коду: Spotless, SpotBugs та SonarQube","/java/pr2/10a.code-quality","04.java/pr2/10a.code-quality",{"title":2293,"path":2294,"stem":2295},"Connection Pool: Патерн Object Pool для JDBC-з'єднань","/java/pr2/connection-pool","04.java/pr2/11.connection-pool",{"title":2297,"path":2298,"stem":2299},"Row Data Gateway: Об'єкт як обгортка рядка таблиці","/java/pr2/row-data-gateway","04.java/pr2/12.row-data-gateway",{"title":2301,"path":2302,"stem":2303},"Table Data Gateway: Фасад таблиці як архітектурний відступ","/java/pr2/table-data-gateway","04.java/pr2/13.table-data-gateway",{"title":2305,"path":2306,"stem":2307},"Repository + Data Mapper: Правильна шарова архітектура з JDBC","/java/pr2/repository-data-mapper","04.java/pr2/14.repository-data-mapper",{"title":2309,"path":2310,"stem":2311},"Identity Map: Кешування сутностей у рамках сесії","/java/pr2/identity-map","04.java/pr2/15.identity-map",{"title":2313,"path":2314,"stem":2315},"Unit of Work: Відстеження змін і координація JDBC-транзакцій","/java/pr2/unit-of-work","04.java/pr2/16.unit-of-work",{"title":2317,"path":2318,"stem":2319},"Strategy: Замінювані SQL-стратегії для підтримки різних СУБД","/java/pr2/strategy-sql","04.java/pr2/17.strategy-sql",{"title":2321,"path":2322,"stem":2323},"Proxy: Lazy Loading для One-To-Many колекцій","/java/pr2/proxy-lazy-loading","04.java/pr2/18.proxy-lazy-loading",{"title":2325,"path":2326,"stem":2327},"Generic Repository через Java Reflection: анотації та динамічний SQL","/java/pr2/generic-repository-reflection","04.java/pr2/19.generic-repository-reflection",{"title":2329,"path":2330,"stem":2331},"Specification Pattern: Композиція бізнес-правил для складних запитів","/java/pr2/specification-pattern","04.java/pr2/20.specification-pattern",{"title":2333,"path":2334,"stem":2335},"Розширені можливості Specification Pattern: підзапити, агрегації та гібридний підхід","/java/pr2/20a.advanced-specifications","04.java/pr2/20a.advanced-specifications",{"title":2337,"path":2338,"stem":2339},"Асинхронність у JDBC: Від блокуючих викликів до CompletableFuture","/java/pr2/asynchronous-jdbc","04.java/pr2/21.asynchronous-jdbc",{"title":2341,"path":2342,"stem":2343},"Інтеграційне тестування JDBC-репозиторіїв: Embedded H2 та патерн AAA","/java/pr2/integration-testing-h2","04.java/pr2/22.integration-testing-h2",{"title":2345,"path":2346,"stem":2347},"Testcontainers: Тестування з реальною PostgreSQL у Docker-контейнерах","/java/pr2/integration-testing-testcontainers","04.java/pr2/23.integration-testing-testcontainers",{"title":2349,"path":2350,"stem":2351},"Модуль \"Проектування реляційних баз даних\" для 04.java/pr2","/java/pr2/implementation_plan","04.java/pr2/implementation_plan",{"title":2353,"icon":2354,"path":2355,"stem":2356,"children":2357,"page":59},"Бази даних","i-lucide-database","/databases","06.databases",[2358,2388,2411,2448,2477,2495,2529,2541,2550],{"title":2359,"icon":2360,"path":2361,"stem":2362,"children":2363,"page":59},"Intro","i-lucide-play","/databases/intro","06.databases/01.intro",[2364,2368,2372,2376,2380,2384],{"title":2365,"path":2366,"stem":2367},"Введення в теорію баз даних","/databases/intro/introduction-to-databases","06.databases/01.intro/01.introduction-to-databases",{"title":2369,"path":2370,"stem":2371},"Реляційна модель даних","/databases/intro/relational-model-theory","06.databases/01.intro/02.relational-model-theory",{"title":2373,"path":2374,"stem":2375},"ER-моделювання","/databases/intro/er-modeling","06.databases/01.intro/03.er-modeling",{"title":2377,"path":2378,"stem":2379},"Логічне проектування БД","/databases/intro/logical-schema","06.databases/01.intro/04.logical-schema",{"title":2381,"path":2382,"stem":2383},"Класифікація таблиць","/databases/intro/table-classification","06.databases/01.intro/05.table-classification",{"title":2385,"path":2386,"stem":2387},"PlantUML для баз даних","/databases/intro/plantuml-diagrams","06.databases/01.intro/06.plantuml-diagrams",{"title":2389,"icon":2354,"path":2390,"stem":2391,"children":2392,"page":59},"MS SQL Server Start","/databases/ms-sql-server-start","06.databases/02.ms-sql-server-start",[2393,2397,2403,2407],{"title":2394,"path":2395,"stem":2396},"Типи даних у MS SQL Server","/databases/ms-sql-server-start/data-types","06.databases/02.ms-sql-server-start/01.data-types",{"title":2398,"path":2399,"stem":2400,"children":2401},"Індекси у MS SQL Server","/databases/ms-sql-server-start/sql-indexes","06.databases/02.ms-sql-server-start/02.sql-indexes",[2402],{"title":2398,"path":2399,"stem":2400},{"title":2404,"path":2405,"stem":2406},"Системні бази даних MS SQL Server","/databases/ms-sql-server-start/system-databases","06.databases/02.ms-sql-server-start/03.system-databases",{"title":2408,"path":2409,"stem":2410},"Огляд мови SQL та запитів","/databases/ms-sql-server-start/sql-queries-overview","06.databases/02.ms-sql-server-start/04.sql-queries-overview",{"title":2412,"icon":2354,"path":2413,"stem":2414,"children":2415,"page":59},"SQL","/databases/sql","06.databases/03.sql",[2416,2420,2424,2428,2432,2436,2440,2444],{"title":2417,"path":2418,"stem":2419},"Налаштування демонстраційної бази даних","/databases/sql/sample-database-setup","06.databases/03.sql/00.sample-database-setup",{"title":2421,"path":2422,"stem":2423},"DDL - Створення таблиць (CREATE TABLE)","/databases/sql/ddl-create-table","06.databases/03.sql/01.ddl-create-table",{"title":2425,"path":2426,"stem":2427},"DDL - Зміна та видалення таблиць (ALTER, DROP)","/databases/sql/ddl-alter-drop-table","06.databases/03.sql/02.ddl-alter-drop-table",{"title":2429,"path":2430,"stem":2431},"SELECT запити - Основи","/databases/sql/select-queries-fundamentals","06.databases/03.sql/03.select-queries-fundamentals",{"title":2433,"path":2434,"stem":2435},"SELECT запити - Розширені можливості","/databases/sql/select-queries-advanced","06.databases/03.sql/04.select-queries-advanced",{"title":2437,"path":2438,"stem":2439},"INSERT запити - Додавання даних","/databases/sql/insert-queries","06.databases/03.sql/05.insert-queries",{"title":2441,"path":2442,"stem":2443},"UPDATE та DELETE запити","/databases/sql/update-delete-queries","06.databases/03.sql/06.update-delete-queries",{"title":2445,"path":2446,"stem":2447},"Транзакції в SQL","/databases/sql/transactions","06.databases/03.sql/07.transactions",{"title":2449,"icon":2354,"path":2450,"stem":2451,"children":2452,"page":59},"Multi Table Databases","/databases/multi-table-databases","06.databases/04.multi-table-databases",[2453,2457,2461,2465,2469,2473],{"title":2454,"path":2455,"stem":2456},"Зв'язки та нормалізація БД","/databases/multi-table-databases/relationships-and-normalization","06.databases/04.multi-table-databases/00.relationships-and-normalization",{"title":2458,"path":2459,"stem":2460},"INNER JOIN - З'єднання таблиць","/databases/multi-table-databases/inner-join","06.databases/04.multi-table-databases/01.inner-join",{"title":2462,"path":2463,"stem":2464},"OUTER JOINs - LEFT, RIGHT, FULL","/databases/multi-table-databases/outer-joins","06.databases/04.multi-table-databases/02.outer-joins",{"title":2466,"path":2467,"stem":2468},"CROSS та SELF JOINs","/databases/multi-table-databases/cross-self-joins","06.databases/04.multi-table-databases/03.cross-self-joins",{"title":2470,"path":2471,"stem":2472},"Підзапити (Subqueries)","/databases/multi-table-databases/subqueries","06.databases/04.multi-table-databases/04.subqueries",{"title":2474,"path":2475,"stem":2476},"Агрегації з JOIN","/databases/multi-table-databases/aggregations-with-joins","06.databases/04.multi-table-databases/05.aggregations-with-joins",{"title":2478,"icon":2479,"path":2480,"stem":2481,"children":2482,"page":59},"Aggregate Functions","i-lucide-calculator","/databases/aggregate-functions","06.databases/05.aggregate-functions",[2483,2487,2491],{"title":2484,"path":2485,"stem":2486},"Функції агрегування в MS SQL Server","/databases/aggregate-functions/introduction-aggregate-functions","06.databases/05.aggregate-functions/01.introduction-aggregate-functions",{"title":2488,"path":2489,"stem":2490},"Групування даних в MS SQL Server","/databases/aggregate-functions/grouping-data","06.databases/05.aggregate-functions/02.grouping-data",{"title":2492,"path":2493,"stem":2494},"Підзапити з агрегатними функціями","/databases/aggregate-functions/subqueries-aggregates","06.databases/05.aggregate-functions/03.subqueries-aggregates",{"title":2496,"icon":2497,"path":2498,"stem":2499,"children":2500,"page":59},"Тригери та зберігаємі процедури","i-lucide-database-zap","/databases/triggers-stored-procedures","06.databases/07.triggers-stored-procedures",[2501,2505,2509,2513,2517,2521,2525],{"title":2502,"path":2503,"stem":2504},"DML-тригери","/databases/triggers-stored-procedures/dml-triggers","06.databases/07.triggers-stored-procedures/01.dml-triggers",{"title":2506,"path":2507,"stem":2508},"DDL-тригери","/databases/triggers-stored-procedures/ddl-triggers","06.databases/07.triggers-stored-procedures/02.ddl-triggers",{"title":2510,"path":2511,"stem":2512},"Transact-SQL розширення","/databases/triggers-stored-procedures/transact-sql-extensions","06.databases/07.triggers-stored-procedures/03.transact-sql-extensions",{"title":2514,"path":2515,"stem":2516},"Транзакції","/databases/triggers-stored-procedures/transactions","06.databases/07.triggers-stored-procedures/04.transactions",{"title":2518,"path":2519,"stem":2520},"Зберігаємі процедури","/databases/triggers-stored-procedures/stored-procedures","06.databases/07.triggers-stored-procedures/05.stored-procedures",{"title":2522,"path":2523,"stem":2524},"Користувацькі функції","/databases/triggers-stored-procedures/user-defined-functions","06.databases/07.triggers-stored-procedures/06.user-defined-functions",{"title":2526,"path":2527,"stem":2528},"Безпека баз даних","/databases/triggers-stored-procedures/security","06.databases/07.triggers-stored-procedures/08.security",{"title":2526,"icon":793,"path":2530,"stem":2531,"children":2532,"page":59},"/databases/security","06.databases/08.security",[2533,2537],{"title":2534,"path":2535,"stem":2536},"Вступ до безпеки баз даних","/databases/security/introduction","06.databases/08.security/01.introduction",{"title":2538,"path":2539,"stem":2540},"Системні представлення та метадані","/databases/security/system-views","06.databases/08.security/02.system-views",{"title":2542,"icon":2543,"path":2544,"stem":2545,"children":2546,"page":59},"Резервне копіювання та відновлення","i-lucide-database-backup","/databases/backup-recovery","06.databases/09.backup-recovery",[2547],{"title":2542,"path":2548,"stem":2549},"/databases/backup-recovery/backup-restore","06.databases/09.backup-recovery/01.backup-restore",{"title":2551,"icon":2552,"path":2553,"stem":2554,"children":2555,"page":59},"Повнотекстовий пошук","i-lucide-search","/databases/full-text-search","06.databases/10.full-text-search",[2556],{"title":2551,"path":2557,"stem":2558},"/databases/full-text-search/full-text-search","06.databases/10.full-text-search/01.full-text-search",{"title":2560,"icon":2561,"path":2562,"stem":2563,"children":2564,"page":59},"Tools","i-lucide-wrench","/tools","07.tools",[2565],{"title":2566,"icon":2567,"path":2568,"stem":2569,"children":2570},"Docker","i-simple-icons-docker","/tools/docker","07.tools/01.docker/index",[2571,2573,2577,2581,2585,2589,2593,2597,2601,2605,2609,2613,2617,2621,2625,2629,2633,2637],{"title":2572,"path":2568,"stem":2569},"Docker: від нуля до production",{"title":2574,"path":2575,"stem":2576},"Контейнеризація — від проблеми до рішення","/tools/docker/containerization-concept","07.tools/01.docker/01.containerization-concept",{"title":2578,"path":2579,"stem":2580},"Docker — що це і навіщо?","/tools/docker/docker-what-and-why","07.tools/01.docker/02.docker-what-and-why",{"title":2582,"path":2583,"stem":2584},"Архітектура Docker Engine","/tools/docker/docker-architecture","07.tools/01.docker/03.docker-architecture",{"title":2586,"path":2587,"stem":2588},"Встановлення Docker","/tools/docker/installation","07.tools/01.docker/04.installation",{"title":2590,"path":2591,"stem":2592},"Перший контейнер — docker run","/tools/docker/first-container","07.tools/01.docker/05.first-container",{"title":2594,"path":2595,"stem":2596},"Життєвий цикл контейнера","/tools/docker/container-lifecycle","07.tools/01.docker/06.container-lifecycle",{"title":2598,"path":2599,"stem":2600},"Docker Images — фундаментальні концепції","/tools/docker/docker-images-fundamentals","07.tools/01.docker/07.docker-images-fundamentals",{"title":2602,"path":2603,"stem":2604},"Dockerfile — основи","/tools/docker/dockerfile-basics","07.tools/01.docker/08.dockerfile-basics",{"title":2606,"path":2607,"stem":2608},"Dockerfile — просунуті техніки","/tools/docker/dockerfile-advanced","07.tools/01.docker/09.dockerfile-advanced",{"title":2610,"path":2611,"stem":2612},"Build Context та кешування шарів","/tools/docker/build-context-and-cache","07.tools/01.docker/10.build-context-and-cache",{"title":2614,"path":2615,"stem":2616},"Реєстри Docker-образів","/tools/docker/image-registries","07.tools/01.docker/11.image-registries",{"title":2618,"path":2619,"stem":2620},"Контейнеризація .NET додатків","/tools/docker/dotnet-containerization","07.tools/01.docker/12.dotnet-containerization",{"title":2622,"path":2623,"stem":2624},"Томи та збереження даних","/tools/docker/volumes-and-data","07.tools/01.docker/13.volumes-and-data",{"title":2626,"path":2627,"stem":2628},"Основи мережі в Docker","/tools/docker/networking-basics","07.tools/01.docker/14.networking-basics",{"title":2630,"path":2631,"stem":2632},"Змінні оточення та конфігурація","/tools/docker/environment-and-configuration","07.tools/01.docker/15.environment-and-configuration",{"title":2634,"path":2635,"stem":2636},"Docker Compose — оркестрація контейнерів","/tools/docker/docker-compose-basics","07.tools/01.docker/16.docker-compose-basics",{"title":2638,"path":2639,"stem":2640},"Docker Compose — Multi-Service застосунки","/tools/docker/compose-multi-service","07.tools/01.docker/17.compose-multi-service",{"title":2642,"icon":2643,"path":2644,"stem":2645,"children":2646,"page":59},"Software Engineering","i-lucide-code-2","/software-engineering","09.software-engineering",[2647,2651,2655,2659,2663,2667,2671,2675,2679,2683,2687],{"title":2648,"path":2649,"stem":2650},"1. Аналіз предметної області. Експертні знання та складність","/software-engineering/intro.subdomains","09.software-engineering/01.intro.subdomains",{"title":2652,"path":2653,"stem":2654},"2. Обмежені контексти. Інтеграція обмежених контекстів","/software-engineering/integrating-limited-contexts","09.software-engineering/02.integrating-limited-contexts",{"title":2656,"path":2657,"stem":2658},"3. Реалізація простої бізнес-логіки","/software-engineering/simple","09.software-engineering/03.simple",{"title":2660,"path":2661,"stem":2662},"4. Опрацювання складної бізнес-логіки","/software-engineering/complex-business-logic","09.software-engineering/04.complex-business-logic",{"title":2664,"path":2665,"stem":2666},"5. Моделювання фактора часу. Подієво-орієнтована архітектура.","/software-engineering/modelling-the-time-factor","09.software-engineering/05.modelling-the-time-factor",{"title":2668,"path":2669,"stem":2670},"6. Архітектурні патерни","/software-engineering/architectural-patterns","09.software-engineering/06.architectural-patterns",{"title":2672,"path":2673,"stem":2674},"Паттерни взаємодії","/software-engineering/patterns-of-interaction","09.software-engineering/07.patterns-of-interaction",{"title":2676,"path":2677,"stem":2678},"Евристика проєктування","/software-engineering/design-heuristics","09.software-engineering/08.design-heuristics",{"title":2680,"path":2681,"stem":2682},"Еволюція проєктних рішень","/software-engineering/evolution-of-design-solutions","09.software-engineering/09.evolution-of-design-solutions",{"title":2684,"path":2685,"stem":2686},"EventStorming","/software-engineering/eventstorming","09.software-engineering/10.eventstorming",{"title":2688,"path":2689,"stem":2690},"DDD на практиці","/software-engineering/ddd-in-practice","09.software-engineering/11.ddd-in-practice",{"title":2692,"icon":943,"path":2693,"stem":2694,"children":2695,"page":59},"DDD","/ddd","10.ddd",[2696,2700,2704,2708,2712,2716,2720,2724,2728,2732,2736,2740,2744],{"title":2697,"path":2698,"stem":2699},"Аналіз предметної області","/ddd/domain-analysis","10.ddd/01.domain-analysis",{"title":2701,"path":2702,"stem":2703},"Експертні знання про предметну область","/ddd/domain-expert-knowledge","10.ddd/02.domain-expert-knowledge",{"title":2705,"path":2706,"stem":2707},"Як осмислити складність предметної області","/ddd/managing-domain-complexity","10.ddd/03.managing-domain-complexity",{"title":2709,"path":2710,"stem":2711},"Інтеграція обмежених контекстів","/ddd/bounded-context-integration","10.ddd/04.bounded-context-integration",{"title":2713,"path":2714,"stem":2715},"Реалізація простої бізнес-логіки","/ddd/simple-business-logic","10.ddd/05.simple-business-logic",{"title":2717,"path":2718,"stem":2719},"Обробка складної бізнес-логіки","/ddd/complex-business-logic","10.ddd/06.complex-business-logic",{"title":2721,"path":2722,"stem":2723},"Моделювання фактора часу","/ddd/time-modeling","10.ddd/07.time-modeling",{"title":2725,"path":2726,"stem":2727},"Глава 8. Архітектурні Патерни","/ddd/architectural-patterns","10.ddd/08.architectural-patterns",{"title":2729,"path":2730,"stem":2731},"Глава 9. Патерни Взаємодії","/ddd/interaction-patterns","10.ddd/09.interaction-patterns",{"title":2733,"path":2734,"stem":2735},"Глава 10. Проектні Евристики","/ddd/design-heuristics","10.ddd/10.design-heuristics",{"title":2737,"path":2738,"stem":2739},"Глава 11. Еволюція Проектних Рішень","/ddd/evolution-of-design-decisions","10.ddd/11.evolution-of-design-decisions",{"title":2741,"path":2742,"stem":2743},"Глава 12. EventStorming","/ddd/event-storming","10.ddd/12.event-storming",{"title":2745,"path":2746,"stem":2747},"Глава 13. DDD на Практиці","/ddd/ddd-in-practice","10.ddd/13.ddd-in-practice",{"title":2749,"icon":2750,"path":2751,"stem":2752,"children":2753,"page":59},"Media Streaming","i-lucide-video","/media-streaming","11.media-streaming",[2754,2758,2762,2766,2770,2774,2778],{"title":2755,"path":2756,"stem":2757},"01. Магія Стрімінгу: Що відбувається, коли ви натискаєте \"Play\"","/media-streaming/introduction","11.media-streaming/01.introduction",{"title":2759,"path":2760,"stem":2761},"02. Анатомія Медіа: Кодеки, Контейнери та Стиснення","/media-streaming/audio-video-anatomy","11.media-streaming/02.audio-video-anatomy",{"title":2763,"path":2764,"stem":2765},"03. The Gym: FFmpeg Deep Dive","/media-streaming/ffmpeg-gym","11.media-streaming/03.ffmpeg-gym",{"title":2767,"path":2768,"stem":2769},"04. HLS Protocol: HTTP Live Streaming у Деталях","/media-streaming/hls-protocol","11.media-streaming/04.hls-protocol",{"title":2771,"path":2772,"stem":2773},"05. DASH Protocol: Відкритий Стандарт","/media-streaming/dash-protocol","11.media-streaming/05.dash-protocol",{"title":2775,"path":2776,"stem":2777},"06. Масштабування: CDN та Adaptive Bitrate","/media-streaming/cdn-and-adaptive-bitrate","11.media-streaming/06.cdn-and-adaptive-bitrate",{"title":2779,"path":2780,"stem":2781},"07. Війна із Затримкою (Latency)","/media-streaming/realtime-latency","11.media-streaming/07.realtime-latency",{"title":2783,"icon":2784,"path":2785,"stem":2786,"children":2787,"page":59},"HTML & CSS","i-devicon-html5","/html-css","12.html-css",[2788,2792,2796,2800,2804,2808,2812,2816,2820,2824,2828,2832,2836,2840,2844,2848,2852,2856,2860,2864,2868,2872,2876,2880,2884,2888,2892,2896,2900,2904],{"title":2789,"path":2790,"stem":2791},"Вступ до HTML. Структура документа","/html-css/intro-html-structure","12.html-css/01.intro-html-structure",{"title":2793,"path":2794,"stem":2795},"Форматування тексту в HTML","/html-css/html-text-formatting","12.html-css/02.html-text-formatting",{"title":2797,"path":2798,"stem":2799},"Посилання та зображення в HTML","/html-css/html-links-images","12.html-css/03.html-links-images",{"title":2801,"path":2802,"stem":2803},"Списки та таблиці в HTML","/html-css/html-lists-tables","12.html-css/04.html-lists-tables",{"title":2805,"path":2806,"stem":2807},"Форми в HTML","/html-css/html-forms","12.html-css/05.html-forms",{"title":2809,"path":2810,"stem":2811},"Семантичні елементи HTML5","/html-css/html-semantic-elements","12.html-css/06.html-semantic-elements",{"title":2813,"path":2814,"stem":2815},"Мультимедіа та розширені елементи HTML","/html-css/html-multimedia-advanced","12.html-css/07.html-multimedia-advanced",{"title":2817,"path":2818,"stem":2819},"Мікророзмітка та SEO в HTML","/html-css/html-microdata-seo","12.html-css/08.html-microdata-seo",{"title":2821,"path":2822,"stem":2823},"Вступ до CSS. Селектори та специфічність","/html-css/css-intro-selectors","12.html-css/09.css-intro-selectors",{"title":2825,"path":2826,"stem":2827},"Блокова модель CSS. Відступи. Box Sizing","/html-css/css-box-model","12.html-css/10.css-box-model",{"title":2829,"path":2830,"stem":2831},"Розміри у CSS: повний довідник одиниць і ключових слів","/html-css/10a.css-sizing","12.html-css/10a.css-sizing",{"title":2833,"path":2834,"stem":2835},"Типографіка в CSS. Шрифти та текст","/html-css/css-typography","12.html-css/11.css-typography",{"title":2837,"path":2838,"stem":2839},"Кольори та фони в CSS","/html-css/css-colors-backgrounds","12.html-css/12.css-colors-backgrounds",{"title":2841,"path":2842,"stem":2843},"Тіні та фільтри в CSS","/html-css/12b.css-shadows-filters","12.html-css/12b.css-shadows-filters",{"title":2845,"path":2846,"stem":2847},"CSS Flexbox: Фундамент гнучких макетів","/html-css/css-flexbox-fundamentals","12.html-css/13.css-flexbox-fundamentals",{"title":2849,"path":2850,"stem":2851},"CSS Flexbox: Вирівнювання та Позиціонування","/html-css/css-flexbox-alignment-sizing-and-patterns","12.html-css/14.css-flexbox-alignment-sizing-and-patterns",{"title":2853,"path":2854,"stem":2855},"CSS Grid. Двовимірний макет. Частина 1","/html-css/css-layout-grid","12.html-css/15.css-layout-grid",{"title":2857,"path":2858,"stem":2859},"CSS Grid. Двовимірний макет. Частина 2","/html-css/css-layout-grid-advanced","12.html-css/16.css-layout-grid-advanced",{"title":2861,"path":2862,"stem":2863},"Позиціонування в CSS. Z-index. Stacking Context","/html-css/css-positioning","12.html-css/17.css-positioning",{"title":2865,"path":2866,"stem":2867},"CSS Анімації та Переходи","/html-css/css-animations-transitions","12.html-css/18.css-animations-transitions",{"title":2869,"path":2870,"stem":2871},"Адаптивний дизайн. Media Queries. Частина 1","/html-css/css-responsive-media-queries","12.html-css/19.css-responsive-media-queries",{"title":2873,"path":2874,"stem":2875},"Адаптивний дизайн. Частина 2: clamp(), Container Queries, @layer","/html-css/css-responsive-advanced","12.html-css/20.css-responsive-advanced",{"title":2877,"path":2878,"stem":2879},"CSS Custom Properties. Методології. Сучасний CSS","/html-css/css-variables-methodologies","12.html-css/21.css-variables-methodologies",{"title":2881,"path":2882,"stem":2883},"Сучасний CSS 2023–2025: Нові можливості","/html-css/css-modern-features","12.html-css/22.css-modern-features",{"title":2885,"path":2886,"stem":2887},"CSS Nesting, @layer, @scope та @property: нативний препроцесор","/html-css/22a.css-nesting-modern-syntax","12.html-css/22a.css-nesting-modern-syntax",{"title":2889,"path":2890,"stem":2891},"CSS для форм та інтерактивних станів","/html-css/css-forms-interactive-states","12.html-css/23.css-forms-interactive-states",{"title":2893,"path":2894,"stem":2895},"Доступність у CSS (CSS Accessibility)","/html-css/css-accessibility","12.html-css/24.css-accessibility",{"title":2897,"path":2898,"stem":2899},"CSS-функції та сучасні sizing primitives","/html-css/css-functions-sizing","12.html-css/25.css-functions-sizing",{"title":2901,"path":2902,"stem":2903},"Rendering Pipeline і CSS Performance","/html-css/css-rendering-performance","12.html-css/26.css-rendering-performance",{"title":2905,"path":2906,"stem":2907},"CSS Best Practices: типові ситуації та правильні рішення","/html-css/css-best-practices","12.html-css/27.css-best-practices",{"title":2909,"path":2910,"stem":2911,"children":2912,"page":59},"Tailwind","/tailwind","21.tailwind",[2913,2917,2921,2925,2929,2933,2937,2941],{"title":2914,"path":2915,"stem":2916},"Що таке Tailwind CSS і навіщо він потрібен","/tailwind/tailwind-intro-philosophy","21.tailwind/01.tailwind-intro-philosophy",{"title":2918,"path":2919,"stem":2920},"Встановлення та налаштування Tailwind CSS v4","/tailwind/tailwind-installation-setup","21.tailwind/02.tailwind-installation-setup",{"title":2922,"path":2923,"stem":2924},"Utility-класи: основи та система Tailwind","/tailwind/tailwind-utility-classes-core","21.tailwind/03.tailwind-utility-classes-core",{"title":2926,"path":2927,"stem":2928},"Layout: Flexbox та Grid через Tailwind","/tailwind/tailwind-flexbox-grid","21.tailwind/04.tailwind-flexbox-grid",{"title":2930,"path":2931,"stem":2932},"Кастомізація теми через @theme у Tailwind v4","/tailwind/tailwind-theme-customization","21.tailwind/05.tailwind-theme-customization",{"title":2934,"path":2935,"stem":2936},"Варіанти: hover, focus, responsive, dark mode та нові v4","/tailwind/tailwind-variants-states","21.tailwind/06.tailwind-variants-states",{"title":2938,"path":2939,"stem":2940},"Типографіка та система кольорів у Tailwind v4","/tailwind/tailwind-typography-colors","21.tailwind/07.tailwind-typography-colors",{"title":2942,"path":2943,"stem":2944},"Компоненти та повторюваність: @apply, @utility та патерни","/tailwind/tailwind-components-patterns","21.tailwind/08.tailwind-components-patterns",{"title":2946,"path":2947,"stem":2948},"Showcase Компонентів kostyl.dev","/test-new-components","98.test-new-components",{"id":2950,"title":1299,"body":2951,"description":18780,"extension":18781,"links":18782,"meta":18783,"navigation":3192,"path":1300,"seo":18784,"stem":1301,"__hash__":18785},"docs/01.csharp/11.aspnet/12.web-api/02.controller-base-actionresult.md",{"type":2952,"value":2953,"toc":18727},"minimark",[2954,2958,2963,2976,2979,3019,3030,3037,3042,3053,3076,3079,3108,3111,3115,3119,3137,3143,3148,3326,3330,3528,3532,3610,3614,3815,3830,3834,3846,4267,4272,4319,4323,4332,4336,4497,4502,4510,4515,4542,4546,4670,4674,4715,4719,4724,4736,4740,4846,4850,4865,5105,5118,5147,5149,5153,5159,5163,6355,6359,6364,7092,7096,7693,7702,7704,7708,7720,12038,12041,12099,12101,12105,12108,12112,12197,12235,12239,12244,12772,12777,12801,12805,12812,12832,12835,13278,13282,13285,13834,13838,13844,14057,14103,14105,14109,14116,14120,14123,14250,14255,14272,14276,14279,14448,14453,14502,14506,14509,14661,14666,14677,14681,14684,14900,14905,14978,14982,14985,15244,15255,15257,15261,15271,15275,15381,15386,15406,15410,15416,15424,15428,15431,15530,15534,15743,15745,15749,15752,15756,16141,16143,16147,17102,17104,17108,18592,18594,18598,18605,18610,18670,18677,18679,18683,18711,18713,18723],[2955,2956,1299],"h1",{"id":2957},"controllerbase-actionresultt-та-response-types",[2959,2960,2962],"h2",{"id":2961},"вступ-мова-спілкування-з-клієнтом","Вступ: Мова спілкування з клієнтом",[2964,2965,2966,2967,2971,2972,2975],"p",{},"Якщо контролер — це серце вашого API, то ",[2968,2969,2970],"strong",{},"типи повернення"," (response types) — це його мова спілкування з клієнтом. Кожна відповідь API — це не просто дані; це ",[2968,2973,2974],{},"структурована розмова",", де HTTP-код каже \"що сталося\", заголовки надають метадані, а тіло містить корисне навантаження. Неправильно обраний тип повернення або статус-код може зруйнувати user experience, навіть якщо ваша бізнес-логіка бездоганна.",[2964,2977,2978],{},"Уявіть, що ви замовляєте каву в кав'ярні. Бариста може відповісти по-різному:",[2980,2981,2982,2989,2995,3001,3007,3013],"ul",{},[2983,2984,2985,2988],"li",{},[2968,2986,2987],{},"200 OK"," + кава в руках: \"Ось ваше замовлення\" ☕",[2983,2990,2991,2994],{},[2968,2992,2993],{},"201 Created"," + чек: \"Замовлення створено, ось номер для відстеження\" 🧾",[2983,2996,2997,3000],{},[2968,2998,2999],{},"204 No Content",": \"Готово\" (без додаткової інформації) ✅",[2983,3002,3003,3006],{},[2968,3004,3005],{},"404 Not Found",": \"Вибачте, такого напою немає в меню\" ❌",[2983,3008,3009,3012],{},[2968,3010,3011],{},"400 Bad Request",": \"Не зрозумів ваше замовлення, повторіть, будь ласка\" ⚠️",[2983,3014,3015,3018],{},[2968,3016,3017],{},"409 Conflict",": \"Ви вже маєте активне замовлення\" 🚫",[2964,3020,3021,3022,3025,3026,3029],{},"Кожна з цих відповідей несе ",[2968,3023,3024],{},"семантичне значення",", і клієнт (мобільний додаток, веб-інтерфейс, інший сервіс) повинен розуміти, як реагувати. У попередній статті ми навчилися створювати контролери; тепер настав час опанувати ",[2968,3027,3028],{},"мистецтво формування відповідей",".",[3031,3032,3033,3036],"note",{},[2968,3034,3035],{},"Передумови:"," Ця стаття базується на знаннях з попередньої статті (01. Від Minimal API до Controllers), а також на розумінні HTTP-методів та статус-кодів з курсу API Design (статті 03-05).",[3038,3039,3041],"h3",{"id":3040},"що-ви-створите-в-цій-статті","Що ви створите в цій статті",[2964,3043,3044,3045,3048,3049,3052],{},"Ми побудуємо ",[2968,3046,3047],{},"Products API"," — сервіс управління товарами інтернет-магазину. Цей API демонструватиме ",[2968,3050,3051],{},"всі типи відповідей"," у реальних сценаріях:",[2980,3054,3055,3058,3061,3064,3067,3070,3073],{},[2983,3056,3057],{},"Успішне отримання даних (200 OK)",[2983,3059,3060],{},"Створення ресурсу з Location header (201 Created)",[2983,3062,3063],{},"Оновлення без повернення даних (204 No Content)",[2983,3065,3066],{},"Обробка відсутніх ресурсів (404 Not Found)",[2983,3068,3069],{},"Валідаційні помилки (400 Bad Request)",[2983,3071,3072],{},"Конфлікти бізнес-логіки (409 Conflict)",[2983,3074,3075],{},"Повернення файлів (File Download)",[2964,3077,3078],{},"До кінця статті ви зможете:",[2980,3080,3081,3084,3096,3099,3105],{},[2983,3082,3083],{},"Обирати правильний тип повернення для кожного сценарію",[2983,3085,3086,3087,3091,3092,3095],{},"Використовувати ",[3088,3089,3090],"code",{},"ActionResult\u003CT>"," vs ",[3088,3093,3094],{},"IActionResult"," обґрунтовано",[2983,3097,3098],{},"Формувати відповіді з правильними HTTP-кодами",[2983,3100,3101,3102],{},"Документувати API через ",[3088,3103,3104],{},"[ProducesResponseType]",[2983,3106,3107],{},"Повертати файли з API (PDF, зображення, CSV)",[3109,3110],"hr",{},[2959,3112,3114],{"id":3113},"фундаментальні-концепції-ієрархія-результатів","Фундаментальні концепції: Ієрархія результатів",[3038,3116,3118],{"id":3117},"базовий-клас-controllerbase-фабрика-результатів","Базовий клас ControllerBase: Фабрика результатів",[2964,3120,3121,3124,3125,3128,3129,3132,3133,3136],{},[3088,3122,3123],{},"ControllerBase"," — це не просто базовий клас для успадкування. Це ",[2968,3126,3127],{},"фабрика допоміжних методів",", що спрощують створення HTTP-відповідей. Замість ручного конструювання об'єктів ",[3088,3130,3131],{},"ObjectResult",", ",[3088,3134,3135],{},"StatusCodeResult"," та інших, ви використовуєте лаконічні методи.",[2964,3138,3139,3140,3142],{},"Розглянемо ключові методи ",[3088,3141,3123],{},":",[3144,3145,3147],"h4",{"id":3146},"успішні-відповіді-2xx","Успішні відповіді (2xx)",[3149,3150,3155],"pre",{"className":3151,"code":3152,"language":3153,"meta":3154,"style":3154},"language-csharp shiki shiki-themes light-plus dark-plus dark-plus","// 200 OK - Успішна операція з даними\nOk(data)                    // ObjectResult з StatusCode = 200\n\n// 201 Created - Ресурс створено\nCreated(uri, data)          // CreatedResult з Location header\nCreatedAtAction(actionName, routeValues, data)  // Автоматична генерація URI\nCreatedAtRoute(routeName, routeValues, data)    // URI через іменований маршрут\n\n// 202 Accepted - Запит прийнято до обробки (асинхронні операції)\nAccepted(uri, data)         // AcceptedResult\n\n// 204 No Content - Успішно, але без даних у відповіді\nNoContent()                 // NoContentResult\n","csharp","",[3088,3156,3157,3166,3187,3194,3200,3221,3247,3272,3277,3283,3303,3308,3314],{"__ignoreMap":3154},[3158,3159,3162],"span",{"class":3160,"line":3161},"line",1,[3158,3163,3165],{"class":3164},"spJ8K","// 200 OK - Успішна операція з даними\n",[3158,3167,3169,3173,3177,3181,3184],{"class":3160,"line":3168},2,[3158,3170,3172],{"class":3171},"s8Opu","Ok",[3158,3174,3176],{"class":3175},"sHH4Y","(",[3158,3178,3180],{"class":3179},"siwwj","data",[3158,3182,3183],{"class":3175},")                    ",[3158,3185,3186],{"class":3164},"// ObjectResult з StatusCode = 200\n",[3158,3188,3190],{"class":3160,"line":3189},3,[3158,3191,3193],{"emptyLinePlaceholder":3192},true,"\n",[3158,3195,3197],{"class":3160,"line":3196},4,[3158,3198,3199],{"class":3164},"// 201 Created - Ресурс створено\n",[3158,3201,3203,3206,3208,3211,3213,3215,3218],{"class":3160,"line":3202},5,[3158,3204,3205],{"class":3171},"Created",[3158,3207,3176],{"class":3175},[3158,3209,3210],{"class":3179},"uri",[3158,3212,3132],{"class":3175},[3158,3214,3180],{"class":3179},[3158,3216,3217],{"class":3175},")          ",[3158,3219,3220],{"class":3164},"// CreatedResult з Location header\n",[3158,3222,3224,3227,3229,3232,3234,3237,3239,3241,3244],{"class":3160,"line":3223},6,[3158,3225,3226],{"class":3171},"CreatedAtAction",[3158,3228,3176],{"class":3175},[3158,3230,3231],{"class":3179},"actionName",[3158,3233,3132],{"class":3175},[3158,3235,3236],{"class":3179},"routeValues",[3158,3238,3132],{"class":3175},[3158,3240,3180],{"class":3179},[3158,3242,3243],{"class":3175},")  ",[3158,3245,3246],{"class":3164},"// Автоматична генерація URI\n",[3158,3248,3250,3253,3255,3258,3260,3262,3264,3266,3269],{"class":3160,"line":3249},7,[3158,3251,3252],{"class":3171},"CreatedAtRoute",[3158,3254,3176],{"class":3175},[3158,3256,3257],{"class":3179},"routeName",[3158,3259,3132],{"class":3175},[3158,3261,3236],{"class":3179},[3158,3263,3132],{"class":3175},[3158,3265,3180],{"class":3179},[3158,3267,3268],{"class":3175},")    ",[3158,3270,3271],{"class":3164},"// URI через іменований маршрут\n",[3158,3273,3275],{"class":3160,"line":3274},8,[3158,3276,3193],{"emptyLinePlaceholder":3192},[3158,3278,3280],{"class":3160,"line":3279},9,[3158,3281,3282],{"class":3164},"// 202 Accepted - Запит прийнято до обробки (асинхронні операції)\n",[3158,3284,3286,3289,3291,3293,3295,3297,3300],{"class":3160,"line":3285},10,[3158,3287,3288],{"class":3171},"Accepted",[3158,3290,3176],{"class":3175},[3158,3292,3210],{"class":3179},[3158,3294,3132],{"class":3175},[3158,3296,3180],{"class":3179},[3158,3298,3299],{"class":3175},")         ",[3158,3301,3302],{"class":3164},"// AcceptedResult\n",[3158,3304,3306],{"class":3160,"line":3305},11,[3158,3307,3193],{"emptyLinePlaceholder":3192},[3158,3309,3311],{"class":3160,"line":3310},12,[3158,3312,3313],{"class":3164},"// 204 No Content - Успішно, але без даних у відповіді\n",[3158,3315,3317,3320,3323],{"class":3160,"line":3316},13,[3158,3318,3319],{"class":3171},"NoContent",[3158,3321,3322],{"class":3175},"()                 ",[3158,3324,3325],{"class":3164},"// NoContentResult\n",[3144,3327,3329],{"id":3328},"помилки-клієнта-4xx","Помилки клієнта (4xx)",[3149,3331,3333],{"className":3151,"code":3332,"language":3153,"meta":3154,"style":3154},"// 400 Bad Request - Невалідний запит\nBadRequest()                // BadRequestResult\nBadRequest(error)           // BadRequestObjectResult з деталями\nBadRequest(ModelState)      // Автоматичні помилки валідації\n\n// 401 Unauthorized - Не автентифікований\nUnauthorized()              // UnauthorizedResult\n\n// 403 Forbidden - Автентифікований, але немає прав\nForbid()                    // ForbidResult\n\n// 404 Not Found - Ресурс не знайдено\nNotFound()                  // NotFoundResult\nNotFound(message)           // NotFoundObjectResult з повідомленням\n\n// 409 Conflict - Конфлікт бізнес-логіки\nConflict()                  // ConflictResult\nConflict(error)             // ConflictObjectResult\n\n// 422 Unprocessable Entity - Семантично невалідний запит\nUnprocessableEntity()       // UnprocessableEntityResult\nUnprocessableEntity(ModelState)\n",[3088,3334,3335,3340,3351,3366,3381,3385,3390,3401,3405,3410,3421,3425,3430,3441,3456,3461,3467,3478,3493,3498,3504,3516],{"__ignoreMap":3154},[3158,3336,3337],{"class":3160,"line":3161},[3158,3338,3339],{"class":3164},"// 400 Bad Request - Невалідний запит\n",[3158,3341,3342,3345,3348],{"class":3160,"line":3168},[3158,3343,3344],{"class":3171},"BadRequest",[3158,3346,3347],{"class":3175},"()                ",[3158,3349,3350],{"class":3164},"// BadRequestResult\n",[3158,3352,3353,3355,3357,3360,3363],{"class":3160,"line":3189},[3158,3354,3344],{"class":3171},[3158,3356,3176],{"class":3175},[3158,3358,3359],{"class":3179},"error",[3158,3361,3362],{"class":3175},")           ",[3158,3364,3365],{"class":3164},"// BadRequestObjectResult з деталями\n",[3158,3367,3368,3370,3372,3375,3378],{"class":3160,"line":3196},[3158,3369,3344],{"class":3171},[3158,3371,3176],{"class":3175},[3158,3373,3374],{"class":3179},"ModelState",[3158,3376,3377],{"class":3175},")      ",[3158,3379,3380],{"class":3164},"// Автоматичні помилки валідації\n",[3158,3382,3383],{"class":3160,"line":3202},[3158,3384,3193],{"emptyLinePlaceholder":3192},[3158,3386,3387],{"class":3160,"line":3223},[3158,3388,3389],{"class":3164},"// 401 Unauthorized - Не автентифікований\n",[3158,3391,3392,3395,3398],{"class":3160,"line":3249},[3158,3393,3394],{"class":3171},"Unauthorized",[3158,3396,3397],{"class":3175},"()              ",[3158,3399,3400],{"class":3164},"// UnauthorizedResult\n",[3158,3402,3403],{"class":3160,"line":3274},[3158,3404,3193],{"emptyLinePlaceholder":3192},[3158,3406,3407],{"class":3160,"line":3279},[3158,3408,3409],{"class":3164},"// 403 Forbidden - Автентифікований, але немає прав\n",[3158,3411,3412,3415,3418],{"class":3160,"line":3285},[3158,3413,3414],{"class":3171},"Forbid",[3158,3416,3417],{"class":3175},"()                    ",[3158,3419,3420],{"class":3164},"// ForbidResult\n",[3158,3422,3423],{"class":3160,"line":3305},[3158,3424,3193],{"emptyLinePlaceholder":3192},[3158,3426,3427],{"class":3160,"line":3310},[3158,3428,3429],{"class":3164},"// 404 Not Found - Ресурс не знайдено\n",[3158,3431,3432,3435,3438],{"class":3160,"line":3316},[3158,3433,3434],{"class":3171},"NotFound",[3158,3436,3437],{"class":3175},"()                  ",[3158,3439,3440],{"class":3164},"// NotFoundResult\n",[3158,3442,3444,3446,3448,3451,3453],{"class":3160,"line":3443},14,[3158,3445,3434],{"class":3171},[3158,3447,3176],{"class":3175},[3158,3449,3450],{"class":3179},"message",[3158,3452,3362],{"class":3175},[3158,3454,3455],{"class":3164},"// NotFoundObjectResult з повідомленням\n",[3158,3457,3459],{"class":3160,"line":3458},15,[3158,3460,3193],{"emptyLinePlaceholder":3192},[3158,3462,3464],{"class":3160,"line":3463},16,[3158,3465,3466],{"class":3164},"// 409 Conflict - Конфлікт бізнес-логіки\n",[3158,3468,3470,3473,3475],{"class":3160,"line":3469},17,[3158,3471,3472],{"class":3171},"Conflict",[3158,3474,3437],{"class":3175},[3158,3476,3477],{"class":3164},"// ConflictResult\n",[3158,3479,3481,3483,3485,3487,3490],{"class":3160,"line":3480},18,[3158,3482,3472],{"class":3171},[3158,3484,3176],{"class":3175},[3158,3486,3359],{"class":3179},[3158,3488,3489],{"class":3175},")             ",[3158,3491,3492],{"class":3164},"// ConflictObjectResult\n",[3158,3494,3496],{"class":3160,"line":3495},19,[3158,3497,3193],{"emptyLinePlaceholder":3192},[3158,3499,3501],{"class":3160,"line":3500},20,[3158,3502,3503],{"class":3164},"// 422 Unprocessable Entity - Семантично невалідний запит\n",[3158,3505,3507,3510,3513],{"class":3160,"line":3506},21,[3158,3508,3509],{"class":3171},"UnprocessableEntity",[3158,3511,3512],{"class":3175},"()       ",[3158,3514,3515],{"class":3164},"// UnprocessableEntityResult\n",[3158,3517,3519,3521,3523,3525],{"class":3160,"line":3518},22,[3158,3520,3509],{"class":3171},[3158,3522,3176],{"class":3175},[3158,3524,3374],{"class":3179},[3158,3526,3527],{"class":3175},")\n",[3144,3529,3531],{"id":3530},"помилки-сервера-5xx","Помилки сервера (5xx)",[3149,3533,3535],{"className":3151,"code":3534,"language":3153,"meta":3154,"style":3154},"// 500 Internal Server Error - Загальна помилка сервера\nStatusCode(500)             // StatusCodeResult\nStatusCode(500, error)      // ObjectResult з кодом 500\n\n// Загальний метод для будь-якого коду\nStatusCode(statusCode)\nStatusCode(statusCode, value)\n",[3088,3536,3537,3542,3558,3575,3579,3584,3595],{"__ignoreMap":3154},[3158,3538,3539],{"class":3160,"line":3161},[3158,3540,3541],{"class":3164},"// 500 Internal Server Error - Загальна помилка сервера\n",[3158,3543,3544,3547,3549,3553,3555],{"class":3160,"line":3168},[3158,3545,3546],{"class":3171},"StatusCode",[3158,3548,3176],{"class":3175},[3158,3550,3552],{"class":3551},"sJj4R","500",[3158,3554,3489],{"class":3175},[3158,3556,3557],{"class":3164},"// StatusCodeResult\n",[3158,3559,3560,3562,3564,3566,3568,3570,3572],{"class":3160,"line":3189},[3158,3561,3546],{"class":3171},[3158,3563,3176],{"class":3175},[3158,3565,3552],{"class":3551},[3158,3567,3132],{"class":3175},[3158,3569,3359],{"class":3179},[3158,3571,3377],{"class":3175},[3158,3573,3574],{"class":3164},"// ObjectResult з кодом 500\n",[3158,3576,3577],{"class":3160,"line":3196},[3158,3578,3193],{"emptyLinePlaceholder":3192},[3158,3580,3581],{"class":3160,"line":3202},[3158,3582,3583],{"class":3164},"// Загальний метод для будь-якого коду\n",[3158,3585,3586,3588,3590,3593],{"class":3160,"line":3223},[3158,3587,3546],{"class":3171},[3158,3589,3176],{"class":3175},[3158,3591,3592],{"class":3179},"statusCode",[3158,3594,3527],{"class":3175},[3158,3596,3597,3599,3601,3603,3605,3608],{"class":3160,"line":3249},[3158,3598,3546],{"class":3171},[3158,3600,3176],{"class":3175},[3158,3602,3592],{"class":3179},[3158,3604,3132],{"class":3175},[3158,3606,3607],{"class":3179},"value",[3158,3609,3527],{"class":3175},[3144,3611,3613],{"id":3612},"спеціальні-результати","Спеціальні результати",[3149,3615,3617],{"className":3151,"code":3616,"language":3153,"meta":3154,"style":3154},"// Повернення файлів\nFile(bytes, contentType)                    // FileContentResult\nFile(stream, contentType)                   // FileStreamResult\nPhysicalFile(path, contentType)             // PhysicalFileResult\nFile(bytes, contentType, fileDownloadName)  // З ім'ям для завантаження\n\n// Перенаправлення\nRedirect(url)               // RedirectResult (302)\nRedirectPermanent(url)      // RedirectResult (301)\nLocalRedirect(url)          // LocalRedirectResult (безпечніше)\n\n// Проблемні деталі (RFC 9457)\nProblem(detail, instance, statusCode, title, type)  // ProblemDetails\nValidationProblem(ModelState)                       // ValidationProblemDetails\n",[3088,3618,3619,3624,3644,3663,3682,3704,3708,3713,3729,3743,3757,3761,3766,3800],{"__ignoreMap":3154},[3158,3620,3621],{"class":3160,"line":3161},[3158,3622,3623],{"class":3164},"// Повернення файлів\n",[3158,3625,3626,3629,3631,3634,3636,3639,3641],{"class":3160,"line":3168},[3158,3627,3628],{"class":3171},"File",[3158,3630,3176],{"class":3175},[3158,3632,3633],{"class":3179},"bytes",[3158,3635,3132],{"class":3175},[3158,3637,3638],{"class":3179},"contentType",[3158,3640,3183],{"class":3175},[3158,3642,3643],{"class":3164},"// FileContentResult\n",[3158,3645,3646,3648,3650,3653,3655,3657,3660],{"class":3160,"line":3189},[3158,3647,3628],{"class":3171},[3158,3649,3176],{"class":3175},[3158,3651,3652],{"class":3179},"stream",[3158,3654,3132],{"class":3175},[3158,3656,3638],{"class":3179},[3158,3658,3659],{"class":3175},")                   ",[3158,3661,3662],{"class":3164},"// FileStreamResult\n",[3158,3664,3665,3668,3670,3673,3675,3677,3679],{"class":3160,"line":3196},[3158,3666,3667],{"class":3171},"PhysicalFile",[3158,3669,3176],{"class":3175},[3158,3671,3672],{"class":3179},"path",[3158,3674,3132],{"class":3175},[3158,3676,3638],{"class":3179},[3158,3678,3489],{"class":3175},[3158,3680,3681],{"class":3164},"// PhysicalFileResult\n",[3158,3683,3684,3686,3688,3690,3692,3694,3696,3699,3701],{"class":3160,"line":3202},[3158,3685,3628],{"class":3171},[3158,3687,3176],{"class":3175},[3158,3689,3633],{"class":3179},[3158,3691,3132],{"class":3175},[3158,3693,3638],{"class":3179},[3158,3695,3132],{"class":3175},[3158,3697,3698],{"class":3179},"fileDownloadName",[3158,3700,3243],{"class":3175},[3158,3702,3703],{"class":3164},"// З ім'ям для завантаження\n",[3158,3705,3706],{"class":3160,"line":3223},[3158,3707,3193],{"emptyLinePlaceholder":3192},[3158,3709,3710],{"class":3160,"line":3249},[3158,3711,3712],{"class":3164},"// Перенаправлення\n",[3158,3714,3715,3718,3720,3723,3726],{"class":3160,"line":3274},[3158,3716,3717],{"class":3171},"Redirect",[3158,3719,3176],{"class":3175},[3158,3721,3722],{"class":3179},"url",[3158,3724,3725],{"class":3175},")               ",[3158,3727,3728],{"class":3164},"// RedirectResult (302)\n",[3158,3730,3731,3734,3736,3738,3740],{"class":3160,"line":3279},[3158,3732,3733],{"class":3171},"RedirectPermanent",[3158,3735,3176],{"class":3175},[3158,3737,3722],{"class":3179},[3158,3739,3377],{"class":3175},[3158,3741,3742],{"class":3164},"// RedirectResult (301)\n",[3158,3744,3745,3748,3750,3752,3754],{"class":3160,"line":3285},[3158,3746,3747],{"class":3171},"LocalRedirect",[3158,3749,3176],{"class":3175},[3158,3751,3722],{"class":3179},[3158,3753,3217],{"class":3175},[3158,3755,3756],{"class":3164},"// LocalRedirectResult (безпечніше)\n",[3158,3758,3759],{"class":3160,"line":3305},[3158,3760,3193],{"emptyLinePlaceholder":3192},[3158,3762,3763],{"class":3160,"line":3310},[3158,3764,3765],{"class":3164},"// Проблемні деталі (RFC 9457)\n",[3158,3767,3768,3771,3773,3776,3778,3781,3783,3785,3787,3790,3792,3795,3797],{"class":3160,"line":3316},[3158,3769,3770],{"class":3171},"Problem",[3158,3772,3176],{"class":3175},[3158,3774,3775],{"class":3179},"detail",[3158,3777,3132],{"class":3175},[3158,3779,3780],{"class":3179},"instance",[3158,3782,3132],{"class":3175},[3158,3784,3592],{"class":3179},[3158,3786,3132],{"class":3175},[3158,3788,3789],{"class":3179},"title",[3158,3791,3132],{"class":3175},[3158,3793,3794],{"class":3179},"type",[3158,3796,3243],{"class":3175},[3158,3798,3799],{"class":3164},"// ProblemDetails\n",[3158,3801,3802,3805,3807,3809,3812],{"class":3160,"line":3443},[3158,3803,3804],{"class":3171},"ValidationProblem",[3158,3806,3176],{"class":3175},[3158,3808,3374],{"class":3179},[3158,3810,3811],{"class":3175},")                       ",[3158,3813,3814],{"class":3164},"// ValidationProblemDetails\n",[3816,3817,3818,3821,3822,3825,3826,3829],"tip",{},[2968,3819,3820],{},"Правило вибору методу:"," Завжди використовуйте найспецифічніший метод. Замість ",[3088,3823,3824],{},"StatusCode(200, data)"," пишіть ",[3088,3827,3828],{},"Ok(data)"," — це робить код самодокументованим та зрозумілим.",[3038,3831,3833],{"id":3832},"ієрархія-типів-результатів","Ієрархія типів результатів",[2964,3835,3836,3837,3839,3840,3842,3843,3845],{},"Всі методи ",[3088,3838,3123],{}," повертають об'єкти, що успадковуються від ",[3088,3841,3094],{}," або ",[3088,3844,3090],{},". Розуміння цієї ієрархії критично важливе для правильного вибору типу повернення.",[3847,3848,3849],"mermaid",{},[3149,3850,3853],{"className":3851,"code":3852,"language":3847,"meta":3154,"style":3154},"language-mermaid shiki shiki-themes light-plus dark-plus dark-plus","classDiagram\n    class IActionResult {\n        \u003C\u003Cinterface>>\n        +ExecuteResultAsync()\n    }\n    \n    class ActionResult {\n        \u003C\u003Cabstract>>\n    }\n    \n    class ObjectResult {\n        +Value: object\n        +StatusCode: int\n        +Formatters\n    }\n    \n    class StatusCodeResult {\n        +StatusCode: int\n    }\n    \n    class FileResult {\n        \u003C\u003Cabstract>>\n        +ContentType: string\n        +FileDownloadName: string\n    }\n    \n    class OkObjectResult {\n        StatusCode = 200\n    }\n    \n    class CreatedResult {\n        StatusCode = 201\n        +Location: string\n    }\n    \n    class NotFoundObjectResult {\n        StatusCode = 404\n    }\n    \n    class BadRequestObjectResult {\n        StatusCode = 400\n    }\n    \n    class NoContentResult {\n        StatusCode = 204\n    }\n    \n    class FileContentResult {\n        +FileContents: byte[]\n    }\n    \n    class PhysicalFileResult {\n        +FileName: string\n    }\n    \n    IActionResult \u003C|-- ActionResult\n    ActionResult \u003C|-- ObjectResult\n    ActionResult \u003C|-- StatusCodeResult\n    ActionResult \u003C|-- FileResult\n    \n    ObjectResult \u003C|-- OkObjectResult\n    ObjectResult \u003C|-- CreatedResult\n    ObjectResult \u003C|-- NotFoundObjectResult\n    ObjectResult \u003C|-- BadRequestObjectResult\n    \n    StatusCodeResult \u003C|-- NoContentResult\n    \n    FileResult \u003C|-- FileContentResult\n    FileResult \u003C|-- PhysicalFileResult\n    \n    style IActionResult fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n    style ActionResult fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n    style ObjectResult fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n    style OkObjectResult fill:#10b981,stroke:#059669,color:#ffffff\n    style CreatedResult fill:#10b981,stroke:#059669,color:#ffffff\n    style NotFoundObjectResult fill:#ef4444,stroke:#b91c1c,color:#ffffff\n    style BadRequestObjectResult fill:#f59e0b,stroke:#b45309,color:#ffffff\n",[3088,3854,3855,3860,3865,3870,3875,3880,3885,3890,3895,3899,3903,3908,3913,3918,3923,3927,3931,3936,3940,3944,3948,3953,3957,3963,3969,3974,3979,3985,3991,3996,4001,4007,4013,4019,4024,4029,4035,4041,4046,4051,4057,4063,4068,4073,4079,4085,4090,4095,4101,4107,4112,4117,4123,4129,4134,4139,4145,4151,4157,4163,4168,4174,4180,4186,4192,4197,4203,4208,4214,4220,4225,4231,4237,4243,4249,4255,4261],{"__ignoreMap":3154},[3158,3856,3857],{"class":3160,"line":3161},[3158,3858,3859],{},"classDiagram\n",[3158,3861,3862],{"class":3160,"line":3168},[3158,3863,3864],{},"    class IActionResult {\n",[3158,3866,3867],{"class":3160,"line":3189},[3158,3868,3869],{},"        \u003C\u003Cinterface>>\n",[3158,3871,3872],{"class":3160,"line":3196},[3158,3873,3874],{},"        +ExecuteResultAsync()\n",[3158,3876,3877],{"class":3160,"line":3202},[3158,3878,3879],{},"    }\n",[3158,3881,3882],{"class":3160,"line":3223},[3158,3883,3884],{},"    \n",[3158,3886,3887],{"class":3160,"line":3249},[3158,3888,3889],{},"    class ActionResult {\n",[3158,3891,3892],{"class":3160,"line":3274},[3158,3893,3894],{},"        \u003C\u003Cabstract>>\n",[3158,3896,3897],{"class":3160,"line":3279},[3158,3898,3879],{},[3158,3900,3901],{"class":3160,"line":3285},[3158,3902,3884],{},[3158,3904,3905],{"class":3160,"line":3305},[3158,3906,3907],{},"    class ObjectResult {\n",[3158,3909,3910],{"class":3160,"line":3310},[3158,3911,3912],{},"        +Value: object\n",[3158,3914,3915],{"class":3160,"line":3316},[3158,3916,3917],{},"        +StatusCode: int\n",[3158,3919,3920],{"class":3160,"line":3443},[3158,3921,3922],{},"        +Formatters\n",[3158,3924,3925],{"class":3160,"line":3458},[3158,3926,3879],{},[3158,3928,3929],{"class":3160,"line":3463},[3158,3930,3884],{},[3158,3932,3933],{"class":3160,"line":3469},[3158,3934,3935],{},"    class StatusCodeResult {\n",[3158,3937,3938],{"class":3160,"line":3480},[3158,3939,3917],{},[3158,3941,3942],{"class":3160,"line":3495},[3158,3943,3879],{},[3158,3945,3946],{"class":3160,"line":3500},[3158,3947,3884],{},[3158,3949,3950],{"class":3160,"line":3506},[3158,3951,3952],{},"    class FileResult {\n",[3158,3954,3955],{"class":3160,"line":3518},[3158,3956,3894],{},[3158,3958,3960],{"class":3160,"line":3959},23,[3158,3961,3962],{},"        +ContentType: string\n",[3158,3964,3966],{"class":3160,"line":3965},24,[3158,3967,3968],{},"        +FileDownloadName: string\n",[3158,3970,3972],{"class":3160,"line":3971},25,[3158,3973,3879],{},[3158,3975,3977],{"class":3160,"line":3976},26,[3158,3978,3884],{},[3158,3980,3982],{"class":3160,"line":3981},27,[3158,3983,3984],{},"    class OkObjectResult {\n",[3158,3986,3988],{"class":3160,"line":3987},28,[3158,3989,3990],{},"        StatusCode = 200\n",[3158,3992,3994],{"class":3160,"line":3993},29,[3158,3995,3879],{},[3158,3997,3999],{"class":3160,"line":3998},30,[3158,4000,3884],{},[3158,4002,4004],{"class":3160,"line":4003},31,[3158,4005,4006],{},"    class CreatedResult {\n",[3158,4008,4010],{"class":3160,"line":4009},32,[3158,4011,4012],{},"        StatusCode = 201\n",[3158,4014,4016],{"class":3160,"line":4015},33,[3158,4017,4018],{},"        +Location: string\n",[3158,4020,4022],{"class":3160,"line":4021},34,[3158,4023,3879],{},[3158,4025,4027],{"class":3160,"line":4026},35,[3158,4028,3884],{},[3158,4030,4032],{"class":3160,"line":4031},36,[3158,4033,4034],{},"    class NotFoundObjectResult {\n",[3158,4036,4038],{"class":3160,"line":4037},37,[3158,4039,4040],{},"        StatusCode = 404\n",[3158,4042,4044],{"class":3160,"line":4043},38,[3158,4045,3879],{},[3158,4047,4049],{"class":3160,"line":4048},39,[3158,4050,3884],{},[3158,4052,4054],{"class":3160,"line":4053},40,[3158,4055,4056],{},"    class BadRequestObjectResult {\n",[3158,4058,4060],{"class":3160,"line":4059},41,[3158,4061,4062],{},"        StatusCode = 400\n",[3158,4064,4066],{"class":3160,"line":4065},42,[3158,4067,3879],{},[3158,4069,4071],{"class":3160,"line":4070},43,[3158,4072,3884],{},[3158,4074,4076],{"class":3160,"line":4075},44,[3158,4077,4078],{},"    class NoContentResult {\n",[3158,4080,4082],{"class":3160,"line":4081},45,[3158,4083,4084],{},"        StatusCode = 204\n",[3158,4086,4088],{"class":3160,"line":4087},46,[3158,4089,3879],{},[3158,4091,4093],{"class":3160,"line":4092},47,[3158,4094,3884],{},[3158,4096,4098],{"class":3160,"line":4097},48,[3158,4099,4100],{},"    class FileContentResult {\n",[3158,4102,4104],{"class":3160,"line":4103},49,[3158,4105,4106],{},"        +FileContents: byte[]\n",[3158,4108,4110],{"class":3160,"line":4109},50,[3158,4111,3879],{},[3158,4113,4115],{"class":3160,"line":4114},51,[3158,4116,3884],{},[3158,4118,4120],{"class":3160,"line":4119},52,[3158,4121,4122],{},"    class PhysicalFileResult {\n",[3158,4124,4126],{"class":3160,"line":4125},53,[3158,4127,4128],{},"        +FileName: string\n",[3158,4130,4132],{"class":3160,"line":4131},54,[3158,4133,3879],{},[3158,4135,4137],{"class":3160,"line":4136},55,[3158,4138,3884],{},[3158,4140,4142],{"class":3160,"line":4141},56,[3158,4143,4144],{},"    IActionResult \u003C|-- ActionResult\n",[3158,4146,4148],{"class":3160,"line":4147},57,[3158,4149,4150],{},"    ActionResult \u003C|-- ObjectResult\n",[3158,4152,4154],{"class":3160,"line":4153},58,[3158,4155,4156],{},"    ActionResult \u003C|-- StatusCodeResult\n",[3158,4158,4160],{"class":3160,"line":4159},59,[3158,4161,4162],{},"    ActionResult \u003C|-- FileResult\n",[3158,4164,4166],{"class":3160,"line":4165},60,[3158,4167,3884],{},[3158,4169,4171],{"class":3160,"line":4170},61,[3158,4172,4173],{},"    ObjectResult \u003C|-- OkObjectResult\n",[3158,4175,4177],{"class":3160,"line":4176},62,[3158,4178,4179],{},"    ObjectResult \u003C|-- CreatedResult\n",[3158,4181,4183],{"class":3160,"line":4182},63,[3158,4184,4185],{},"    ObjectResult \u003C|-- NotFoundObjectResult\n",[3158,4187,4189],{"class":3160,"line":4188},64,[3158,4190,4191],{},"    ObjectResult \u003C|-- BadRequestObjectResult\n",[3158,4193,4195],{"class":3160,"line":4194},65,[3158,4196,3884],{},[3158,4198,4200],{"class":3160,"line":4199},66,[3158,4201,4202],{},"    StatusCodeResult \u003C|-- NoContentResult\n",[3158,4204,4206],{"class":3160,"line":4205},67,[3158,4207,3884],{},[3158,4209,4211],{"class":3160,"line":4210},68,[3158,4212,4213],{},"    FileResult \u003C|-- FileContentResult\n",[3158,4215,4217],{"class":3160,"line":4216},69,[3158,4218,4219],{},"    FileResult \u003C|-- PhysicalFileResult\n",[3158,4221,4223],{"class":3160,"line":4222},70,[3158,4224,3884],{},[3158,4226,4228],{"class":3160,"line":4227},71,[3158,4229,4230],{},"    style IActionResult fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n",[3158,4232,4234],{"class":3160,"line":4233},72,[3158,4235,4236],{},"    style ActionResult fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n",[3158,4238,4240],{"class":3160,"line":4239},73,[3158,4241,4242],{},"    style ObjectResult fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n",[3158,4244,4246],{"class":3160,"line":4245},74,[3158,4247,4248],{},"    style OkObjectResult fill:#10b981,stroke:#059669,color:#ffffff\n",[3158,4250,4252],{"class":3160,"line":4251},75,[3158,4253,4254],{},"    style CreatedResult fill:#10b981,stroke:#059669,color:#ffffff\n",[3158,4256,4258],{"class":3160,"line":4257},76,[3158,4259,4260],{},"    style NotFoundObjectResult fill:#ef4444,stroke:#b91c1c,color:#ffffff\n",[3158,4262,4264],{"class":3160,"line":4263},77,[3158,4265,4266],{},"    style BadRequestObjectResult fill:#f59e0b,stroke:#b45309,color:#ffffff\n",[2964,4268,4269],{},[2968,4270,4271],{},"Ключові класи:",[4273,4274,4275,4286,4297,4304,4311],"ol",{},[2983,4276,4277,4281,4282,4285],{},[2968,4278,4279],{},[3088,4280,3094],{}," — базовий інтерфейс для всіх результатів. Містить єдиний метод ",[3088,4283,4284],{},"ExecuteResultAsync()",", що виконує формування HTTP-відповіді.",[2983,4287,4288,4293,4294,4296],{},[2968,4289,4290],{},[3088,4291,4292],{},"ActionResult"," — абстрактний клас, що реалізує ",[3088,4295,3094],{},". Базовий клас для всіх конкретних результатів.",[2983,4298,4299,4303],{},[2968,4300,4301],{},[3088,4302,3131],{}," — результат з об'єктом у тілі відповіді. Автоматично серіалізується в JSON/XML через content negotiation.",[2983,4305,4306,4310],{},[2968,4307,4308],{},[3088,4309,3135],{}," — результат лише зі статус-кодом, без тіла.",[2983,4312,4313,4318],{},[2968,4314,4315],{},[3088,4316,4317],{},"FileResult"," — базовий клас для повернення файлів (зображення, PDF, CSV).",[3038,4320,4322],{"id":4321},"actionresultt-vs-iactionresult-критичний-вибір","ActionResult\u003CT> vs IActionResult: Критичний вибір",[2964,4324,4325,4326,4328,4329,4331],{},"Один з найважливіших рішень при проєктуванні API-методу — вибір між ",[3088,4327,3090],{}," та ",[3088,4330,3094],{},". Ця відмінність впливає на документацію OpenAPI, type safety та зручність використання.",[3144,4333,4335],{"id":4334},"iactionresult-гнучкість-без-типізації","IActionResult: Гнучкість без типізації",[3149,4337,4339],{"className":3151,"code":4338,"language":3153,"meta":3154,"style":3154},"[HttpGet(\"{id}\")]\npublic async Task\u003CIActionResult> GetById(int id)\n{\n    var product = await _db.Products.FindAsync(id);\n    \n    if (product is null)\n        return NotFound(); // Повертаємо NotFoundResult\n    \n    return Ok(product);    // Повертаємо OkObjectResult\n}\n",[3088,4340,4341,4359,4392,4397,4432,4436,4456,4470,4474,4492],{"__ignoreMap":3154},[3158,4342,4343,4346,4350,4352,4356],{"class":3160,"line":3161},[3158,4344,4345],{"class":3175},"[",[3158,4347,4349],{"class":4348},"sN1BT","HttpGet",[3158,4351,3176],{"class":3175},[3158,4353,4355],{"class":4354},"sbdoH","\"{id}\"",[3158,4357,4358],{"class":3175},")]\n",[3158,4360,4361,4365,4368,4371,4374,4376,4379,4382,4384,4387,4390],{"class":3160,"line":3168},[3158,4362,4364],{"class":4363},"su1O8","public",[3158,4366,4367],{"class":4363}," async",[3158,4369,4370],{"class":4348}," Task",[3158,4372,4373],{"class":3175},"\u003C",[3158,4375,3094],{"class":4348},[3158,4377,4378],{"class":3175},"> ",[3158,4380,4381],{"class":3171},"GetById",[3158,4383,3176],{"class":3175},[3158,4385,4386],{"class":4363},"int",[3158,4388,4389],{"class":3179}," id",[3158,4391,3527],{"class":3175},[3158,4393,4394],{"class":3160,"line":3189},[3158,4395,4396],{"class":3175},"{\n",[3158,4398,4399,4402,4405,4408,4411,4414,4416,4419,4421,4424,4426,4429],{"class":3160,"line":3196},[3158,4400,4401],{"class":4363},"    var",[3158,4403,4404],{"class":3179}," product",[3158,4406,4407],{"class":3175}," = ",[3158,4409,4410],{"class":4363},"await",[3158,4412,4413],{"class":3179}," _db",[3158,4415,3029],{"class":3175},[3158,4417,4418],{"class":3179},"Products",[3158,4420,3029],{"class":3175},[3158,4422,4423],{"class":3171},"FindAsync",[3158,4425,3176],{"class":3175},[3158,4427,4428],{"class":3179},"id",[3158,4430,4431],{"class":3175},");\n",[3158,4433,4434],{"class":3160,"line":3202},[3158,4435,3884],{"class":3175},[3158,4437,4438,4442,4445,4448,4451,4454],{"class":3160,"line":3223},[3158,4439,4441],{"class":4440},"sCDza","    if",[3158,4443,4444],{"class":3175}," (",[3158,4446,4447],{"class":3179},"product",[3158,4449,4450],{"class":4363}," is",[3158,4452,4453],{"class":4363}," null",[3158,4455,3527],{"class":3175},[3158,4457,4458,4461,4464,4467],{"class":3160,"line":3249},[3158,4459,4460],{"class":4440},"        return",[3158,4462,4463],{"class":3171}," NotFound",[3158,4465,4466],{"class":3175},"(); ",[3158,4468,4469],{"class":3164},"// Повертаємо NotFoundResult\n",[3158,4471,4472],{"class":3160,"line":3274},[3158,4473,3884],{"class":3175},[3158,4475,4476,4479,4482,4484,4486,4489],{"class":3160,"line":3279},[3158,4477,4478],{"class":4440},"    return",[3158,4480,4481],{"class":3171}," Ok",[3158,4483,3176],{"class":3175},[3158,4485,4447],{"class":3179},[3158,4487,4488],{"class":3175},");    ",[3158,4490,4491],{"class":3164},"// Повертаємо OkObjectResult\n",[3158,4493,4494],{"class":3160,"line":3285},[3158,4495,4496],{"class":3175},"}\n",[2964,4498,4499],{},[2968,4500,4501],{},"Переваги:",[2980,4503,4504,4507],{},[2983,4505,4506],{},"Максимальна гнучкість — можна повертати будь-який тип результату",[2983,4508,4509],{},"Підходить для методів з багатьма різними типами відповідей",[2964,4511,4512],{},[2968,4513,4514],{},"Недоліки:",[2980,4516,4517,4527,4533],{},[2983,4518,4519,4520,4523,4524],{},"❌ ",[2968,4521,4522],{},"Втрата типізації:"," Компілятор не знає, що метод повертає ",[3088,4525,4526],{},"Product",[2983,4528,4519,4529,4532],{},[2968,4530,4531],{},"Погана документація OpenAPI:"," Swagger не може автоматично визначити тип відповіді",[2983,4534,4519,4535,4541],{},[2968,4536,4537,4538,4540],{},"Потрібні явні ",[3088,4539,3104],{}," атрибути"," для документації",[3144,4543,4545],{"id":4544},"actionresultt-type-safety-openapi","ActionResult\u003CT>: Type Safety + OpenAPI",[3149,4547,4549],{"className":3151,"code":4548,"language":3153,"meta":3154,"style":3154},"[HttpGet(\"{id}\")]\npublic async Task\u003CActionResult\u003CProduct>> GetById(int id)\n{\n    var product = await _db.Products.FindAsync(id);\n    \n    if (product is null)\n        return NotFound(); // Повертаємо NotFoundResult\n    \n    return product;        // Неявна конвертація Product → OkObjectResult\n}\n",[3088,4550,4551,4563,4592,4596,4622,4626,4640,4650,4654,4666],{"__ignoreMap":3154},[3158,4552,4553,4555,4557,4559,4561],{"class":3160,"line":3161},[3158,4554,4345],{"class":3175},[3158,4556,4349],{"class":4348},[3158,4558,3176],{"class":3175},[3158,4560,4355],{"class":4354},[3158,4562,4358],{"class":3175},[3158,4564,4565,4567,4569,4571,4573,4575,4577,4579,4582,4584,4586,4588,4590],{"class":3160,"line":3168},[3158,4566,4364],{"class":4363},[3158,4568,4367],{"class":4363},[3158,4570,4370],{"class":4348},[3158,4572,4373],{"class":3175},[3158,4574,4292],{"class":4348},[3158,4576,4373],{"class":3175},[3158,4578,4526],{"class":4348},[3158,4580,4581],{"class":3175},">> ",[3158,4583,4381],{"class":3171},[3158,4585,3176],{"class":3175},[3158,4587,4386],{"class":4363},[3158,4589,4389],{"class":3179},[3158,4591,3527],{"class":3175},[3158,4593,4594],{"class":3160,"line":3189},[3158,4595,4396],{"class":3175},[3158,4597,4598,4600,4602,4604,4606,4608,4610,4612,4614,4616,4618,4620],{"class":3160,"line":3196},[3158,4599,4401],{"class":4363},[3158,4601,4404],{"class":3179},[3158,4603,4407],{"class":3175},[3158,4605,4410],{"class":4363},[3158,4607,4413],{"class":3179},[3158,4609,3029],{"class":3175},[3158,4611,4418],{"class":3179},[3158,4613,3029],{"class":3175},[3158,4615,4423],{"class":3171},[3158,4617,3176],{"class":3175},[3158,4619,4428],{"class":3179},[3158,4621,4431],{"class":3175},[3158,4623,4624],{"class":3160,"line":3202},[3158,4625,3884],{"class":3175},[3158,4627,4628,4630,4632,4634,4636,4638],{"class":3160,"line":3223},[3158,4629,4441],{"class":4440},[3158,4631,4444],{"class":3175},[3158,4633,4447],{"class":3179},[3158,4635,4450],{"class":4363},[3158,4637,4453],{"class":4363},[3158,4639,3527],{"class":3175},[3158,4641,4642,4644,4646,4648],{"class":3160,"line":3249},[3158,4643,4460],{"class":4440},[3158,4645,4463],{"class":3171},[3158,4647,4466],{"class":3175},[3158,4649,4469],{"class":3164},[3158,4651,4652],{"class":3160,"line":3274},[3158,4653,3884],{"class":3175},[3158,4655,4656,4658,4660,4663],{"class":3160,"line":3279},[3158,4657,4478],{"class":4440},[3158,4659,4404],{"class":3179},[3158,4661,4662],{"class":3175},";        ",[3158,4664,4665],{"class":3164},"// Неявна конвертація Product → OkObjectResult\n",[3158,4667,4668],{"class":3160,"line":3285},[3158,4669,4496],{"class":3175},[2964,4671,4672],{},[2968,4673,4501],{},[2980,4675,4676,4685,4694,4707],{},[2983,4677,4678,4679,4682,4683],{},"✅ ",[2968,4680,4681],{},"Type Safety:"," Компілятор знає, що успішна відповідь містить ",[3088,4684,4526],{},[2983,4686,4678,4687,4690,4691,4693],{},[2968,4688,4689],{},"Автоматична документація OpenAPI:"," Swagger бачить тип ",[3088,4692,4526],{}," для 200 OK",[2983,4695,4678,4696,4699,4700,4703,4704],{},[2968,4697,4698],{},"Неявна конвертація:"," Можна повертати ",[3088,4701,4702],{},"T"," напряму, без ",[3088,4705,4706],{},"Ok()",[2983,4708,4678,4709,4712,4713],{},[2968,4710,4711],{},"Intellisense:"," IDE підказує властивості типу ",[3088,4714,4702],{},[2964,4716,4717],{},[2968,4718,4514],{},[2980,4720,4721],{},[2983,4722,4723],{},"Трохи менша гнучкість (але це рідко є проблемою)",[3816,4725,4726,4729,4730,4732,4733,4735],{},[2968,4727,4728],{},"Рекомендація:"," Завжди використовуйте ",[3088,4731,3090],{}," для API-методів, де є чіткий \"успішний\" тип відповіді. Використовуйте ",[3088,4734,3094],{}," лише для методів, що повертають принципово різні типи (наприклад, файл або JSON залежно від параметра).",[3144,4737,4739],{"id":4738},"порівняльна-таблиця","Порівняльна таблиця",[4741,4742,4743,4757],"table",{},[4744,4745,4746],"thead",{},[4747,4748,4749,4753,4755],"tr",{},[4750,4751,4752],"th",{},"Аспект",[4750,4754,3094],{},[4750,4756,3090],{},[4758,4759,4760,4774,4787,4805,4818,4833],"tbody",{},[4747,4761,4762,4768,4771],{},[4763,4764,4765],"td",{},[2968,4766,4767],{},"Type Safety",[4763,4769,4770],{},"❌ Немає",[4763,4772,4773],{},"✅ Є",[4747,4775,4776,4781,4784],{},[4763,4777,4778],{},[2968,4779,4780],{},"OpenAPI документація",[4763,4782,4783],{},"⚠️ Потрібні атрибути",[4763,4785,4786],{},"✅ Автоматична",[4747,4788,4789,4794,4799],{},[4763,4790,4791],{},[2968,4792,4793],{},"Неявна конвертація",[4763,4795,4796,4797],{},"❌ Завжди ",[3088,4798,3828],{},[4763,4800,4801,4802],{},"✅ Можна ",[3088,4803,4804],{},"return data",[4747,4806,4807,4812,4815],{},[4763,4808,4809],{},[2968,4810,4811],{},"Гнучкість",[4763,4813,4814],{},"✅ Максимальна",[4763,4816,4817],{},"⚠️ Обмежена одним типом",[4747,4819,4820,4825,4828],{},[4763,4821,4822],{},[2968,4823,4824],{},"Intellisense",[4763,4826,4827],{},"❌ Немає підказок",[4763,4829,4830,4831],{},"✅ Підказки для ",[3088,4832,4702],{},[4747,4834,4835,4840,4843],{},[4763,4836,4837],{},[2968,4838,4839],{},"Використання",[4763,4841,4842],{},"Рідко (legacy)",[4763,4844,4845],{},"✅ За замовчуванням",[3144,4847,4849],{"id":4848},"неявна-конвертація-магія-actionresultt","Неявна конвертація: Магія ActionResult\u003CT>",[2964,4851,4852,4854,4855,4858,4859,4861,4862,4864],{},[3088,4853,3090],{}," підтримує ",[2968,4856,4857],{},"неявну конвертацію"," з типу ",[3088,4860,4702],{}," та з будь-якого ",[3088,4863,4292],{},". Це дозволяє писати лаконічніший код:",[3149,4866,4868],{"className":3151,"code":4867,"language":3153,"meta":3154,"style":3154},"// Варіант 1: Явне Ok()\n[HttpGet(\"{id}\")]\npublic async Task\u003CActionResult\u003CProduct>> GetById_Explicit(int id)\n{\n    var product = await _db.Products.FindAsync(id);\n    if (product is null) return NotFound();\n    return Ok(product); // Явно обгортаємо в OkObjectResult\n}\n\n// Варіант 2: Неявна конвертація (рекомендовано)\n[HttpGet(\"{id}\")]\npublic async Task\u003CActionResult\u003CProduct>> GetById_Implicit(int id)\n{\n    var product = await _db.Products.FindAsync(id);\n    if (product is null) return NotFound();\n    return product; // Неявна конвертація Product → ActionResult\u003CProduct>\n}\n",[3088,4869,4870,4875,4887,4916,4920,4946,4969,4985,4989,4993,4998,5010,5039,5043,5069,5089,5101],{"__ignoreMap":3154},[3158,4871,4872],{"class":3160,"line":3161},[3158,4873,4874],{"class":3164},"// Варіант 1: Явне Ok()\n",[3158,4876,4877,4879,4881,4883,4885],{"class":3160,"line":3168},[3158,4878,4345],{"class":3175},[3158,4880,4349],{"class":4348},[3158,4882,3176],{"class":3175},[3158,4884,4355],{"class":4354},[3158,4886,4358],{"class":3175},[3158,4888,4889,4891,4893,4895,4897,4899,4901,4903,4905,4908,4910,4912,4914],{"class":3160,"line":3189},[3158,4890,4364],{"class":4363},[3158,4892,4367],{"class":4363},[3158,4894,4370],{"class":4348},[3158,4896,4373],{"class":3175},[3158,4898,4292],{"class":4348},[3158,4900,4373],{"class":3175},[3158,4902,4526],{"class":4348},[3158,4904,4581],{"class":3175},[3158,4906,4907],{"class":3171},"GetById_Explicit",[3158,4909,3176],{"class":3175},[3158,4911,4386],{"class":4363},[3158,4913,4389],{"class":3179},[3158,4915,3527],{"class":3175},[3158,4917,4918],{"class":3160,"line":3196},[3158,4919,4396],{"class":3175},[3158,4921,4922,4924,4926,4928,4930,4932,4934,4936,4938,4940,4942,4944],{"class":3160,"line":3202},[3158,4923,4401],{"class":4363},[3158,4925,4404],{"class":3179},[3158,4927,4407],{"class":3175},[3158,4929,4410],{"class":4363},[3158,4931,4413],{"class":3179},[3158,4933,3029],{"class":3175},[3158,4935,4418],{"class":3179},[3158,4937,3029],{"class":3175},[3158,4939,4423],{"class":3171},[3158,4941,3176],{"class":3175},[3158,4943,4428],{"class":3179},[3158,4945,4431],{"class":3175},[3158,4947,4948,4950,4952,4954,4956,4958,4961,4964,4966],{"class":3160,"line":3223},[3158,4949,4441],{"class":4440},[3158,4951,4444],{"class":3175},[3158,4953,4447],{"class":3179},[3158,4955,4450],{"class":4363},[3158,4957,4453],{"class":4363},[3158,4959,4960],{"class":3175},") ",[3158,4962,4963],{"class":4440},"return",[3158,4965,4463],{"class":3171},[3158,4967,4968],{"class":3175},"();\n",[3158,4970,4971,4973,4975,4977,4979,4982],{"class":3160,"line":3249},[3158,4972,4478],{"class":4440},[3158,4974,4481],{"class":3171},[3158,4976,3176],{"class":3175},[3158,4978,4447],{"class":3179},[3158,4980,4981],{"class":3175},"); ",[3158,4983,4984],{"class":3164},"// Явно обгортаємо в OkObjectResult\n",[3158,4986,4987],{"class":3160,"line":3274},[3158,4988,4496],{"class":3175},[3158,4990,4991],{"class":3160,"line":3279},[3158,4992,3193],{"emptyLinePlaceholder":3192},[3158,4994,4995],{"class":3160,"line":3285},[3158,4996,4997],{"class":3164},"// Варіант 2: Неявна конвертація (рекомендовано)\n",[3158,4999,5000,5002,5004,5006,5008],{"class":3160,"line":3305},[3158,5001,4345],{"class":3175},[3158,5003,4349],{"class":4348},[3158,5005,3176],{"class":3175},[3158,5007,4355],{"class":4354},[3158,5009,4358],{"class":3175},[3158,5011,5012,5014,5016,5018,5020,5022,5024,5026,5028,5031,5033,5035,5037],{"class":3160,"line":3310},[3158,5013,4364],{"class":4363},[3158,5015,4367],{"class":4363},[3158,5017,4370],{"class":4348},[3158,5019,4373],{"class":3175},[3158,5021,4292],{"class":4348},[3158,5023,4373],{"class":3175},[3158,5025,4526],{"class":4348},[3158,5027,4581],{"class":3175},[3158,5029,5030],{"class":3171},"GetById_Implicit",[3158,5032,3176],{"class":3175},[3158,5034,4386],{"class":4363},[3158,5036,4389],{"class":3179},[3158,5038,3527],{"class":3175},[3158,5040,5041],{"class":3160,"line":3316},[3158,5042,4396],{"class":3175},[3158,5044,5045,5047,5049,5051,5053,5055,5057,5059,5061,5063,5065,5067],{"class":3160,"line":3443},[3158,5046,4401],{"class":4363},[3158,5048,4404],{"class":3179},[3158,5050,4407],{"class":3175},[3158,5052,4410],{"class":4363},[3158,5054,4413],{"class":3179},[3158,5056,3029],{"class":3175},[3158,5058,4418],{"class":3179},[3158,5060,3029],{"class":3175},[3158,5062,4423],{"class":3171},[3158,5064,3176],{"class":3175},[3158,5066,4428],{"class":3179},[3158,5068,4431],{"class":3175},[3158,5070,5071,5073,5075,5077,5079,5081,5083,5085,5087],{"class":3160,"line":3458},[3158,5072,4441],{"class":4440},[3158,5074,4444],{"class":3175},[3158,5076,4447],{"class":3179},[3158,5078,4450],{"class":4363},[3158,5080,4453],{"class":4363},[3158,5082,4960],{"class":3175},[3158,5084,4963],{"class":4440},[3158,5086,4463],{"class":3171},[3158,5088,4968],{"class":3175},[3158,5090,5091,5093,5095,5098],{"class":3160,"line":3463},[3158,5092,4478],{"class":4440},[3158,5094,4404],{"class":3179},[3158,5096,5097],{"class":3175},"; ",[3158,5099,5100],{"class":3164},"// Неявна конвертація Product → ActionResult\u003CProduct>\n",[3158,5102,5103],{"class":3160,"line":3469},[3158,5104,4496],{"class":3175},[2964,5106,5107,5108,5111,5112,5114,5115,3029],{},"Обидва варіанти працюють ідентично, але другий — ",[2968,5109,5110],{},"чистіший та ідіоматичніший",". Компілятор автоматично обгортає ",[3088,5113,4447],{}," у ",[3088,5116,5117],{},"OkObjectResult",[5119,5120,5121,5124,5125,5128,5129,5131,5132,5134,5135,5137,5138,5134,5140,5142,5143,5146],"warning",{},[2968,5122,5123],{},"Обережно з null:"," Якщо ви повертаєте ",[3088,5126,5127],{},"null"," напряму, це призведе до ",[3088,5130,2999],{},", а не ",[3088,5133,2987],{}," з ",[3088,5136,5127],{}," у тілі. Якщо потрібен саме ",[3088,5139,2987],{},[3088,5141,5127],{},", використовуйте ",[3088,5144,5145],{},"Ok(null)"," явно.",[3109,5148],{},[2959,5150,5152],{"id":5151},"практична-реалізація-products-api","Практична реалізація: Products API",[2964,5154,5155,5156,5158],{},"Настав час застосувати теорію на практиці. Створимо повноцінний API для управління товарами інтернет-магазину, демонструючи ",[2968,5157,3051],{}," у реальних сценаріях.",[3038,5160,5162],{"id":5161},"крок-1-налаштування-проєкту","Крок 1: Налаштування проєкту",[5164,5165,5166,5170,5229,5233,5239,5637,5641,5646],"steps",{},[3038,5167,5169],{"id":5168},"створення-проєкту","Створення проєкту",[5171,5172,5174,5189,5197,5200,5210,5220],"terminal-preview",{"title":5173},"bash",[5175,5176,5178,5183,5184],"div",{"className":5177},[3160],[3158,5179,5182],{"className":5180},[5181],"opacity-40","$"," ",[2968,5185,5188],{"className":5186},[5187],"font-bold","dotnet new webapi -n ProductsApi",[5175,5190,5192],{"className":5191},[3160],[3158,5193,5196],{"className":5194},[5195,5187],"text-green-400","The template \"ASP.NET Core Web API\" was created successfully.",[5175,5198],{"className":5199},[3160],[5175,5201,5203,5183,5206],{"className":5202},[3160],[3158,5204,5182],{"className":5205},[5181],[2968,5207,5209],{"className":5208},[5187],"cd ProductsApi",[5175,5211,5213,5183,5216],{"className":5212},[3160],[3158,5214,5182],{"className":5215},[5181],[2968,5217,5219],{"className":5218},[5187],"dotnet add package Microsoft.EntityFrameworkCore.InMemory",[5175,5221,5223,5228],{"className":5222},[3160],[3158,5224,5227],{"className":5225},[5226],"text-blue-400","info"," : PackageReference for package 'Microsoft.EntityFrameworkCore.InMemory' added",[3038,5230,5232],{"id":5231},"створення-моделі-product","Створення моделі Product",[2964,5234,5235,5236,3142],{},"Створіть файл ",[3088,5237,5238],{},"Models/Product.cs",[3149,5240,5242],{"className":3151,"code":5241,"language":3153,"meta":3154,"style":3154},"using System.ComponentModel.DataAnnotations;\n\nnamespace ProductsApi.Models;\n\npublic class Product\n{\n    public int Id { get; set; }\n    \n    [Required]\n    [MaxLength(200)]\n    public required string Name { get; set; }\n    \n    [MaxLength(1000)]\n    public string? Description { get; set; }\n    \n    [Range(0.01, 1_000_000)]\n    public decimal Price { get; set; }\n    \n    [Range(0, int.MaxValue)]\n    public int Stock { get; set; }\n    \n    [MaxLength(100)]\n    public string? Category { get; set; }\n    \n    public bool IsActive { get; set; } = true;\n    \n    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;\n    \n    public DateTime? UpdatedAt { get; set; }\n}\n",[3088,5243,5244,5265,5269,5284,5288,5298,5302,5327,5331,5342,5356,5379,5383,5396,5418,5422,5441,5461,5465,5487,5506,5510,5523,5544,5548,5574,5578,5608,5612,5633],{"__ignoreMap":3154},[3158,5245,5246,5249,5252,5254,5257,5259,5262],{"class":3160,"line":3161},[3158,5247,5248],{"class":4440},"using",[3158,5250,5251],{"class":4348}," System",[3158,5253,3029],{"class":3175},[3158,5255,5256],{"class":4348},"ComponentModel",[3158,5258,3029],{"class":3175},[3158,5260,5261],{"class":4348},"DataAnnotations",[3158,5263,5264],{"class":3175},";\n",[3158,5266,5267],{"class":3160,"line":3168},[3158,5268,3193],{"emptyLinePlaceholder":3192},[3158,5270,5271,5274,5277,5279,5282],{"class":3160,"line":3189},[3158,5272,5273],{"class":4363},"namespace",[3158,5275,5276],{"class":4348}," ProductsApi",[3158,5278,3029],{"class":3175},[3158,5280,5281],{"class":4348},"Models",[3158,5283,5264],{"class":3175},[3158,5285,5286],{"class":3160,"line":3196},[3158,5287,3193],{"emptyLinePlaceholder":3192},[3158,5289,5290,5292,5295],{"class":3160,"line":3202},[3158,5291,4364],{"class":4363},[3158,5293,5294],{"class":4363}," class",[3158,5296,5297],{"class":4348}," Product\n",[3158,5299,5300],{"class":3160,"line":3223},[3158,5301,4396],{"class":3175},[3158,5303,5304,5307,5310,5313,5316,5319,5321,5324],{"class":3160,"line":3249},[3158,5305,5306],{"class":4363},"    public",[3158,5308,5309],{"class":4363}," int",[3158,5311,5312],{"class":3179}," Id",[3158,5314,5315],{"class":3175}," { ",[3158,5317,5318],{"class":4363},"get",[3158,5320,5097],{"class":3175},[3158,5322,5323],{"class":4363},"set",[3158,5325,5326],{"class":3175},"; }\n",[3158,5328,5329],{"class":3160,"line":3274},[3158,5330,3884],{"class":3175},[3158,5332,5333,5336,5339],{"class":3160,"line":3279},[3158,5334,5335],{"class":3175},"    [",[3158,5337,5338],{"class":4348},"Required",[3158,5340,5341],{"class":3175},"]\n",[3158,5343,5344,5346,5349,5351,5354],{"class":3160,"line":3285},[3158,5345,5335],{"class":3175},[3158,5347,5348],{"class":4348},"MaxLength",[3158,5350,3176],{"class":3175},[3158,5352,5353],{"class":3551},"200",[3158,5355,4358],{"class":3175},[3158,5357,5358,5360,5363,5366,5369,5371,5373,5375,5377],{"class":3160,"line":3305},[3158,5359,5306],{"class":4363},[3158,5361,5362],{"class":4363}," required",[3158,5364,5365],{"class":4363}," string",[3158,5367,5368],{"class":3179}," Name",[3158,5370,5315],{"class":3175},[3158,5372,5318],{"class":4363},[3158,5374,5097],{"class":3175},[3158,5376,5323],{"class":4363},[3158,5378,5326],{"class":3175},[3158,5380,5381],{"class":3160,"line":3310},[3158,5382,3884],{"class":3175},[3158,5384,5385,5387,5389,5391,5394],{"class":3160,"line":3316},[3158,5386,5335],{"class":3175},[3158,5388,5348],{"class":4348},[3158,5390,3176],{"class":3175},[3158,5392,5393],{"class":3551},"1000",[3158,5395,4358],{"class":3175},[3158,5397,5398,5400,5402,5405,5408,5410,5412,5414,5416],{"class":3160,"line":3443},[3158,5399,5306],{"class":4363},[3158,5401,5365],{"class":4363},[3158,5403,5404],{"class":3175},"? ",[3158,5406,5407],{"class":3179},"Description",[3158,5409,5315],{"class":3175},[3158,5411,5318],{"class":4363},[3158,5413,5097],{"class":3175},[3158,5415,5323],{"class":4363},[3158,5417,5326],{"class":3175},[3158,5419,5420],{"class":3160,"line":3458},[3158,5421,3884],{"class":3175},[3158,5423,5424,5426,5429,5431,5434,5436,5439],{"class":3160,"line":3463},[3158,5425,5335],{"class":3175},[3158,5427,5428],{"class":4348},"Range",[3158,5430,3176],{"class":3175},[3158,5432,5433],{"class":3551},"0.01",[3158,5435,3132],{"class":3175},[3158,5437,5438],{"class":3551},"1_000_000",[3158,5440,4358],{"class":3175},[3158,5442,5443,5445,5448,5451,5453,5455,5457,5459],{"class":3160,"line":3469},[3158,5444,5306],{"class":4363},[3158,5446,5447],{"class":4363}," decimal",[3158,5449,5450],{"class":3179}," Price",[3158,5452,5315],{"class":3175},[3158,5454,5318],{"class":4363},[3158,5456,5097],{"class":3175},[3158,5458,5323],{"class":4363},[3158,5460,5326],{"class":3175},[3158,5462,5463],{"class":3160,"line":3480},[3158,5464,3884],{"class":3175},[3158,5466,5467,5469,5471,5473,5476,5478,5480,5482,5485],{"class":3160,"line":3495},[3158,5468,5335],{"class":3175},[3158,5470,5428],{"class":4348},[3158,5472,3176],{"class":3175},[3158,5474,5475],{"class":3551},"0",[3158,5477,3132],{"class":3175},[3158,5479,4386],{"class":4363},[3158,5481,3029],{"class":3175},[3158,5483,5484],{"class":3179},"MaxValue",[3158,5486,4358],{"class":3175},[3158,5488,5489,5491,5493,5496,5498,5500,5502,5504],{"class":3160,"line":3500},[3158,5490,5306],{"class":4363},[3158,5492,5309],{"class":4363},[3158,5494,5495],{"class":3179}," Stock",[3158,5497,5315],{"class":3175},[3158,5499,5318],{"class":4363},[3158,5501,5097],{"class":3175},[3158,5503,5323],{"class":4363},[3158,5505,5326],{"class":3175},[3158,5507,5508],{"class":3160,"line":3506},[3158,5509,3884],{"class":3175},[3158,5511,5512,5514,5516,5518,5521],{"class":3160,"line":3518},[3158,5513,5335],{"class":3175},[3158,5515,5348],{"class":4348},[3158,5517,3176],{"class":3175},[3158,5519,5520],{"class":3551},"100",[3158,5522,4358],{"class":3175},[3158,5524,5525,5527,5529,5531,5534,5536,5538,5540,5542],{"class":3160,"line":3959},[3158,5526,5306],{"class":4363},[3158,5528,5365],{"class":4363},[3158,5530,5404],{"class":3175},[3158,5532,5533],{"class":3179},"Category",[3158,5535,5315],{"class":3175},[3158,5537,5318],{"class":4363},[3158,5539,5097],{"class":3175},[3158,5541,5323],{"class":4363},[3158,5543,5326],{"class":3175},[3158,5545,5546],{"class":3160,"line":3965},[3158,5547,3884],{"class":3175},[3158,5549,5550,5552,5555,5558,5560,5562,5564,5566,5569,5572],{"class":3160,"line":3971},[3158,5551,5306],{"class":4363},[3158,5553,5554],{"class":4363}," bool",[3158,5556,5557],{"class":3179}," IsActive",[3158,5559,5315],{"class":3175},[3158,5561,5318],{"class":4363},[3158,5563,5097],{"class":3175},[3158,5565,5323],{"class":4363},[3158,5567,5568],{"class":3175},"; } = ",[3158,5570,5571],{"class":4363},"true",[3158,5573,5264],{"class":3175},[3158,5575,5576],{"class":3160,"line":3976},[3158,5577,3884],{"class":3175},[3158,5579,5580,5582,5585,5588,5590,5592,5594,5596,5598,5601,5603,5606],{"class":3160,"line":3981},[3158,5581,5306],{"class":4363},[3158,5583,5584],{"class":4348}," DateTime",[3158,5586,5587],{"class":3179}," CreatedAt",[3158,5589,5315],{"class":3175},[3158,5591,5318],{"class":4363},[3158,5593,5097],{"class":3175},[3158,5595,5323],{"class":4363},[3158,5597,5568],{"class":3175},[3158,5599,5600],{"class":3179},"DateTime",[3158,5602,3029],{"class":3175},[3158,5604,5605],{"class":3179},"UtcNow",[3158,5607,5264],{"class":3175},[3158,5609,5610],{"class":3160,"line":3987},[3158,5611,3884],{"class":3175},[3158,5613,5614,5616,5618,5620,5623,5625,5627,5629,5631],{"class":3160,"line":3993},[3158,5615,5306],{"class":4363},[3158,5617,5584],{"class":4348},[3158,5619,5404],{"class":3175},[3158,5621,5622],{"class":3179},"UpdatedAt",[3158,5624,5315],{"class":3175},[3158,5626,5318],{"class":4363},[3158,5628,5097],{"class":3175},[3158,5630,5323],{"class":4363},[3158,5632,5326],{"class":3175},[3158,5634,5635],{"class":3160,"line":3998},[3158,5636,4496],{"class":3175},[3038,5638,5640],{"id":5639},"створення-dtos","Створення DTOs",[2964,5642,5235,5643,3142],{},[3088,5644,5645],{},"DTOs/ProductDtos.cs",[3149,5647,5649],{"className":3151,"code":5648,"language":3153,"meta":3154,"style":3154},"using System.ComponentModel.DataAnnotations;\n\nnamespace ProductsApi.DTOs;\n\npublic record CreateProductDto\n{\n    [Required(ErrorMessage = \"Product name is required\")]\n    [MaxLength(200)]\n    public required string Name { get; init; }\n\n    [MaxLength(1000)]\n    public string? Description { get; init; }\n\n    [Range(0.01, 1_000_000, ErrorMessage = \"Price must be between 0.01 and 1,000,000\")]\n    public decimal Price { get; init; }\n\n    [Range(0, int.MaxValue, ErrorMessage = \"Stock cannot be negative\")]\n    public int Stock { get; init; }\n\n    [MaxLength(100)]\n    public string? Category { get; init; }\n}\n\npublic record UpdateProductDto\n{\n    [MaxLength(200)]\n    public string? Name { get; init; }\n\n    [MaxLength(1000)]\n    public string? Description { get; init; }\n\n    [Range(0.01, 1_000_000)]\n    public decimal? Price { get; init; }\n\n    [Range(0, int.MaxValue)]\n    public int? Stock { get; init; }\n\n    [MaxLength(100)]\n    public string? Category { get; init; }\n\n    public bool? IsActive { get; init; }\n}\n\npublic record ProductResponseDto\n{\n    public int Id { get; init; }\n    public required string Name { get; init; }\n    public string? Description { get; init; }\n    public decimal Price { get; init; }\n    public int Stock { get; init; }\n    public string? Category { get; init; }\n    public bool IsActive { get; init; }\n    public DateTime CreatedAt { get; init; }\n    public DateTime? UpdatedAt { get; init; }\n}\n",[3088,5650,5651,5667,5671,5684,5688,5698,5702,5720,5732,5753,5757,5769,5789,5793,5818,5836,5840,5869,5887,5891,5903,5923,5927,5931,5940,5944,5956,5977,5981,5993,6013,6017,6033,6054,6058,6078,6099,6103,6115,6135,6139,6160,6164,6168,6177,6181,6199,6219,6239,6257,6275,6295,6313,6331,6351],{"__ignoreMap":3154},[3158,5652,5653,5655,5657,5659,5661,5663,5665],{"class":3160,"line":3161},[3158,5654,5248],{"class":4440},[3158,5656,5251],{"class":4348},[3158,5658,3029],{"class":3175},[3158,5660,5256],{"class":4348},[3158,5662,3029],{"class":3175},[3158,5664,5261],{"class":4348},[3158,5666,5264],{"class":3175},[3158,5668,5669],{"class":3160,"line":3168},[3158,5670,3193],{"emptyLinePlaceholder":3192},[3158,5672,5673,5675,5677,5679,5682],{"class":3160,"line":3189},[3158,5674,5273],{"class":4363},[3158,5676,5276],{"class":4348},[3158,5678,3029],{"class":3175},[3158,5680,5681],{"class":4348},"DTOs",[3158,5683,5264],{"class":3175},[3158,5685,5686],{"class":3160,"line":3196},[3158,5687,3193],{"emptyLinePlaceholder":3192},[3158,5689,5690,5692,5695],{"class":3160,"line":3202},[3158,5691,4364],{"class":4363},[3158,5693,5694],{"class":4363}," record",[3158,5696,5697],{"class":4348}," CreateProductDto\n",[3158,5699,5700],{"class":3160,"line":3223},[3158,5701,4396],{"class":3175},[3158,5703,5704,5706,5708,5710,5713,5715,5718],{"class":3160,"line":3249},[3158,5705,5335],{"class":3175},[3158,5707,5338],{"class":4348},[3158,5709,3176],{"class":3175},[3158,5711,5712],{"class":3179},"ErrorMessage",[3158,5714,4407],{"class":3175},[3158,5716,5717],{"class":4354},"\"Product name is required\"",[3158,5719,4358],{"class":3175},[3158,5721,5722,5724,5726,5728,5730],{"class":3160,"line":3274},[3158,5723,5335],{"class":3175},[3158,5725,5348],{"class":4348},[3158,5727,3176],{"class":3175},[3158,5729,5353],{"class":3551},[3158,5731,4358],{"class":3175},[3158,5733,5734,5736,5738,5740,5742,5744,5746,5748,5751],{"class":3160,"line":3279},[3158,5735,5306],{"class":4363},[3158,5737,5362],{"class":4363},[3158,5739,5365],{"class":4363},[3158,5741,5368],{"class":3179},[3158,5743,5315],{"class":3175},[3158,5745,5318],{"class":4363},[3158,5747,5097],{"class":3175},[3158,5749,5750],{"class":4363},"init",[3158,5752,5326],{"class":3175},[3158,5754,5755],{"class":3160,"line":3285},[3158,5756,3193],{"emptyLinePlaceholder":3192},[3158,5758,5759,5761,5763,5765,5767],{"class":3160,"line":3305},[3158,5760,5335],{"class":3175},[3158,5762,5348],{"class":4348},[3158,5764,3176],{"class":3175},[3158,5766,5393],{"class":3551},[3158,5768,4358],{"class":3175},[3158,5770,5771,5773,5775,5777,5779,5781,5783,5785,5787],{"class":3160,"line":3310},[3158,5772,5306],{"class":4363},[3158,5774,5365],{"class":4363},[3158,5776,5404],{"class":3175},[3158,5778,5407],{"class":3179},[3158,5780,5315],{"class":3175},[3158,5782,5318],{"class":4363},[3158,5784,5097],{"class":3175},[3158,5786,5750],{"class":4363},[3158,5788,5326],{"class":3175},[3158,5790,5791],{"class":3160,"line":3316},[3158,5792,3193],{"emptyLinePlaceholder":3192},[3158,5794,5795,5797,5799,5801,5803,5805,5807,5809,5811,5813,5816],{"class":3160,"line":3443},[3158,5796,5335],{"class":3175},[3158,5798,5428],{"class":4348},[3158,5800,3176],{"class":3175},[3158,5802,5433],{"class":3551},[3158,5804,3132],{"class":3175},[3158,5806,5438],{"class":3551},[3158,5808,3132],{"class":3175},[3158,5810,5712],{"class":3179},[3158,5812,4407],{"class":3175},[3158,5814,5815],{"class":4354},"\"Price must be between 0.01 and 1,000,000\"",[3158,5817,4358],{"class":3175},[3158,5819,5820,5822,5824,5826,5828,5830,5832,5834],{"class":3160,"line":3458},[3158,5821,5306],{"class":4363},[3158,5823,5447],{"class":4363},[3158,5825,5450],{"class":3179},[3158,5827,5315],{"class":3175},[3158,5829,5318],{"class":4363},[3158,5831,5097],{"class":3175},[3158,5833,5750],{"class":4363},[3158,5835,5326],{"class":3175},[3158,5837,5838],{"class":3160,"line":3463},[3158,5839,3193],{"emptyLinePlaceholder":3192},[3158,5841,5842,5844,5846,5848,5850,5852,5854,5856,5858,5860,5862,5864,5867],{"class":3160,"line":3469},[3158,5843,5335],{"class":3175},[3158,5845,5428],{"class":4348},[3158,5847,3176],{"class":3175},[3158,5849,5475],{"class":3551},[3158,5851,3132],{"class":3175},[3158,5853,4386],{"class":4363},[3158,5855,3029],{"class":3175},[3158,5857,5484],{"class":3179},[3158,5859,3132],{"class":3175},[3158,5861,5712],{"class":3179},[3158,5863,4407],{"class":3175},[3158,5865,5866],{"class":4354},"\"Stock cannot be negative\"",[3158,5868,4358],{"class":3175},[3158,5870,5871,5873,5875,5877,5879,5881,5883,5885],{"class":3160,"line":3480},[3158,5872,5306],{"class":4363},[3158,5874,5309],{"class":4363},[3158,5876,5495],{"class":3179},[3158,5878,5315],{"class":3175},[3158,5880,5318],{"class":4363},[3158,5882,5097],{"class":3175},[3158,5884,5750],{"class":4363},[3158,5886,5326],{"class":3175},[3158,5888,5889],{"class":3160,"line":3495},[3158,5890,3193],{"emptyLinePlaceholder":3192},[3158,5892,5893,5895,5897,5899,5901],{"class":3160,"line":3500},[3158,5894,5335],{"class":3175},[3158,5896,5348],{"class":4348},[3158,5898,3176],{"class":3175},[3158,5900,5520],{"class":3551},[3158,5902,4358],{"class":3175},[3158,5904,5905,5907,5909,5911,5913,5915,5917,5919,5921],{"class":3160,"line":3506},[3158,5906,5306],{"class":4363},[3158,5908,5365],{"class":4363},[3158,5910,5404],{"class":3175},[3158,5912,5533],{"class":3179},[3158,5914,5315],{"class":3175},[3158,5916,5318],{"class":4363},[3158,5918,5097],{"class":3175},[3158,5920,5750],{"class":4363},[3158,5922,5326],{"class":3175},[3158,5924,5925],{"class":3160,"line":3518},[3158,5926,4496],{"class":3175},[3158,5928,5929],{"class":3160,"line":3959},[3158,5930,3193],{"emptyLinePlaceholder":3192},[3158,5932,5933,5935,5937],{"class":3160,"line":3965},[3158,5934,4364],{"class":4363},[3158,5936,5694],{"class":4363},[3158,5938,5939],{"class":4348}," UpdateProductDto\n",[3158,5941,5942],{"class":3160,"line":3971},[3158,5943,4396],{"class":3175},[3158,5945,5946,5948,5950,5952,5954],{"class":3160,"line":3976},[3158,5947,5335],{"class":3175},[3158,5949,5348],{"class":4348},[3158,5951,3176],{"class":3175},[3158,5953,5353],{"class":3551},[3158,5955,4358],{"class":3175},[3158,5957,5958,5960,5962,5964,5967,5969,5971,5973,5975],{"class":3160,"line":3981},[3158,5959,5306],{"class":4363},[3158,5961,5365],{"class":4363},[3158,5963,5404],{"class":3175},[3158,5965,5966],{"class":3179},"Name",[3158,5968,5315],{"class":3175},[3158,5970,5318],{"class":4363},[3158,5972,5097],{"class":3175},[3158,5974,5750],{"class":4363},[3158,5976,5326],{"class":3175},[3158,5978,5979],{"class":3160,"line":3987},[3158,5980,3193],{"emptyLinePlaceholder":3192},[3158,5982,5983,5985,5987,5989,5991],{"class":3160,"line":3993},[3158,5984,5335],{"class":3175},[3158,5986,5348],{"class":4348},[3158,5988,3176],{"class":3175},[3158,5990,5393],{"class":3551},[3158,5992,4358],{"class":3175},[3158,5994,5995,5997,5999,6001,6003,6005,6007,6009,6011],{"class":3160,"line":3998},[3158,5996,5306],{"class":4363},[3158,5998,5365],{"class":4363},[3158,6000,5404],{"class":3175},[3158,6002,5407],{"class":3179},[3158,6004,5315],{"class":3175},[3158,6006,5318],{"class":4363},[3158,6008,5097],{"class":3175},[3158,6010,5750],{"class":4363},[3158,6012,5326],{"class":3175},[3158,6014,6015],{"class":3160,"line":4003},[3158,6016,3193],{"emptyLinePlaceholder":3192},[3158,6018,6019,6021,6023,6025,6027,6029,6031],{"class":3160,"line":4009},[3158,6020,5335],{"class":3175},[3158,6022,5428],{"class":4348},[3158,6024,3176],{"class":3175},[3158,6026,5433],{"class":3551},[3158,6028,3132],{"class":3175},[3158,6030,5438],{"class":3551},[3158,6032,4358],{"class":3175},[3158,6034,6035,6037,6039,6041,6044,6046,6048,6050,6052],{"class":3160,"line":4015},[3158,6036,5306],{"class":4363},[3158,6038,5447],{"class":4363},[3158,6040,5404],{"class":3175},[3158,6042,6043],{"class":3179},"Price",[3158,6045,5315],{"class":3175},[3158,6047,5318],{"class":4363},[3158,6049,5097],{"class":3175},[3158,6051,5750],{"class":4363},[3158,6053,5326],{"class":3175},[3158,6055,6056],{"class":3160,"line":4021},[3158,6057,3193],{"emptyLinePlaceholder":3192},[3158,6059,6060,6062,6064,6066,6068,6070,6072,6074,6076],{"class":3160,"line":4026},[3158,6061,5335],{"class":3175},[3158,6063,5428],{"class":4348},[3158,6065,3176],{"class":3175},[3158,6067,5475],{"class":3551},[3158,6069,3132],{"class":3175},[3158,6071,4386],{"class":4363},[3158,6073,3029],{"class":3175},[3158,6075,5484],{"class":3179},[3158,6077,4358],{"class":3175},[3158,6079,6080,6082,6084,6086,6089,6091,6093,6095,6097],{"class":3160,"line":4031},[3158,6081,5306],{"class":4363},[3158,6083,5309],{"class":4363},[3158,6085,5404],{"class":3175},[3158,6087,6088],{"class":3179},"Stock",[3158,6090,5315],{"class":3175},[3158,6092,5318],{"class":4363},[3158,6094,5097],{"class":3175},[3158,6096,5750],{"class":4363},[3158,6098,5326],{"class":3175},[3158,6100,6101],{"class":3160,"line":4037},[3158,6102,3193],{"emptyLinePlaceholder":3192},[3158,6104,6105,6107,6109,6111,6113],{"class":3160,"line":4043},[3158,6106,5335],{"class":3175},[3158,6108,5348],{"class":4348},[3158,6110,3176],{"class":3175},[3158,6112,5520],{"class":3551},[3158,6114,4358],{"class":3175},[3158,6116,6117,6119,6121,6123,6125,6127,6129,6131,6133],{"class":3160,"line":4048},[3158,6118,5306],{"class":4363},[3158,6120,5365],{"class":4363},[3158,6122,5404],{"class":3175},[3158,6124,5533],{"class":3179},[3158,6126,5315],{"class":3175},[3158,6128,5318],{"class":4363},[3158,6130,5097],{"class":3175},[3158,6132,5750],{"class":4363},[3158,6134,5326],{"class":3175},[3158,6136,6137],{"class":3160,"line":4053},[3158,6138,3193],{"emptyLinePlaceholder":3192},[3158,6140,6141,6143,6145,6147,6150,6152,6154,6156,6158],{"class":3160,"line":4059},[3158,6142,5306],{"class":4363},[3158,6144,5554],{"class":4363},[3158,6146,5404],{"class":3175},[3158,6148,6149],{"class":3179},"IsActive",[3158,6151,5315],{"class":3175},[3158,6153,5318],{"class":4363},[3158,6155,5097],{"class":3175},[3158,6157,5750],{"class":4363},[3158,6159,5326],{"class":3175},[3158,6161,6162],{"class":3160,"line":4065},[3158,6163,4496],{"class":3175},[3158,6165,6166],{"class":3160,"line":4070},[3158,6167,3193],{"emptyLinePlaceholder":3192},[3158,6169,6170,6172,6174],{"class":3160,"line":4075},[3158,6171,4364],{"class":4363},[3158,6173,5694],{"class":4363},[3158,6175,6176],{"class":4348}," ProductResponseDto\n",[3158,6178,6179],{"class":3160,"line":4081},[3158,6180,4396],{"class":3175},[3158,6182,6183,6185,6187,6189,6191,6193,6195,6197],{"class":3160,"line":4087},[3158,6184,5306],{"class":4363},[3158,6186,5309],{"class":4363},[3158,6188,5312],{"class":3179},[3158,6190,5315],{"class":3175},[3158,6192,5318],{"class":4363},[3158,6194,5097],{"class":3175},[3158,6196,5750],{"class":4363},[3158,6198,5326],{"class":3175},[3158,6200,6201,6203,6205,6207,6209,6211,6213,6215,6217],{"class":3160,"line":4092},[3158,6202,5306],{"class":4363},[3158,6204,5362],{"class":4363},[3158,6206,5365],{"class":4363},[3158,6208,5368],{"class":3179},[3158,6210,5315],{"class":3175},[3158,6212,5318],{"class":4363},[3158,6214,5097],{"class":3175},[3158,6216,5750],{"class":4363},[3158,6218,5326],{"class":3175},[3158,6220,6221,6223,6225,6227,6229,6231,6233,6235,6237],{"class":3160,"line":4097},[3158,6222,5306],{"class":4363},[3158,6224,5365],{"class":4363},[3158,6226,5404],{"class":3175},[3158,6228,5407],{"class":3179},[3158,6230,5315],{"class":3175},[3158,6232,5318],{"class":4363},[3158,6234,5097],{"class":3175},[3158,6236,5750],{"class":4363},[3158,6238,5326],{"class":3175},[3158,6240,6241,6243,6245,6247,6249,6251,6253,6255],{"class":3160,"line":4103},[3158,6242,5306],{"class":4363},[3158,6244,5447],{"class":4363},[3158,6246,5450],{"class":3179},[3158,6248,5315],{"class":3175},[3158,6250,5318],{"class":4363},[3158,6252,5097],{"class":3175},[3158,6254,5750],{"class":4363},[3158,6256,5326],{"class":3175},[3158,6258,6259,6261,6263,6265,6267,6269,6271,6273],{"class":3160,"line":4109},[3158,6260,5306],{"class":4363},[3158,6262,5309],{"class":4363},[3158,6264,5495],{"class":3179},[3158,6266,5315],{"class":3175},[3158,6268,5318],{"class":4363},[3158,6270,5097],{"class":3175},[3158,6272,5750],{"class":4363},[3158,6274,5326],{"class":3175},[3158,6276,6277,6279,6281,6283,6285,6287,6289,6291,6293],{"class":3160,"line":4114},[3158,6278,5306],{"class":4363},[3158,6280,5365],{"class":4363},[3158,6282,5404],{"class":3175},[3158,6284,5533],{"class":3179},[3158,6286,5315],{"class":3175},[3158,6288,5318],{"class":4363},[3158,6290,5097],{"class":3175},[3158,6292,5750],{"class":4363},[3158,6294,5326],{"class":3175},[3158,6296,6297,6299,6301,6303,6305,6307,6309,6311],{"class":3160,"line":4119},[3158,6298,5306],{"class":4363},[3158,6300,5554],{"class":4363},[3158,6302,5557],{"class":3179},[3158,6304,5315],{"class":3175},[3158,6306,5318],{"class":4363},[3158,6308,5097],{"class":3175},[3158,6310,5750],{"class":4363},[3158,6312,5326],{"class":3175},[3158,6314,6315,6317,6319,6321,6323,6325,6327,6329],{"class":3160,"line":4125},[3158,6316,5306],{"class":4363},[3158,6318,5584],{"class":4348},[3158,6320,5587],{"class":3179},[3158,6322,5315],{"class":3175},[3158,6324,5318],{"class":4363},[3158,6326,5097],{"class":3175},[3158,6328,5750],{"class":4363},[3158,6330,5326],{"class":3175},[3158,6332,6333,6335,6337,6339,6341,6343,6345,6347,6349],{"class":3160,"line":4131},[3158,6334,5306],{"class":4363},[3158,6336,5584],{"class":4348},[3158,6338,5404],{"class":3175},[3158,6340,5622],{"class":3179},[3158,6342,5315],{"class":3175},[3158,6344,5318],{"class":4363},[3158,6346,5097],{"class":3175},[3158,6348,5750],{"class":4363},[3158,6350,5326],{"class":3175},[3158,6352,6353],{"class":3160,"line":4136},[3158,6354,4496],{"class":3175},[3038,6356,6358],{"id":6357},"створення-dbcontext","Створення DbContext",[2964,6360,5235,6361,3142],{},[3088,6362,6363],{},"Data/ProductDbContext.cs",[3149,6365,6367],{"className":3151,"code":6366,"language":3153,"meta":3154,"style":3154},"using Microsoft.EntityFrameworkCore;\nusing ProductsApi.Models;\n\nnamespace ProductsApi.Data;\n\npublic class ProductDbContext : DbContext\n{\n    public ProductDbContext(DbContextOptions\u003CProductDbContext> options) \n        : base(options)\n    {\n    }\n\n    public DbSet\u003CProduct> Products => Set\u003CProduct>();\n\n    protected override void OnModelCreating(ModelBuilder modelBuilder)\n    {\n        modelBuilder.Entity\u003CProduct>(entity =>\n        {\n            entity.HasKey(e => e.Id);\n            entity.Property(e => e.Name).IsRequired();\n            entity.Property(e => e.Price).HasPrecision(18, 2);\n            entity.HasIndex(e => e.Category);\n            entity.HasIndex(e => e.IsActive);\n            \n            // Seed data для демонстрації\n            entity.HasData(\n                new Product \n                { \n                    Id = 1, \n                    Name = \"Laptop Dell XPS 15\", \n                    Description = \"High-performance laptop for developers\",\n                    Price = 1499.99m, \n                    Stock = 10, \n                    Category = \"Electronics\",\n                    CreatedAt = DateTime.UtcNow.AddDays(-30)\n                },\n                new Product \n                { \n                    Id = 2, \n                    Name = \"Mechanical Keyboard\", \n                    Description = \"RGB mechanical keyboard with Cherry MX switches\",\n                    Price = 129.99m, \n                    Stock = 25, \n                    Category = \"Accessories\",\n                    CreatedAt = DateTime.UtcNow.AddDays(-15)\n                },\n                new Product \n                { \n                    Id = 3, \n                    Name = \"USB-C Hub\", \n                    Description = \"7-in-1 USB-C hub with HDMI and Ethernet\",\n                    Price = 49.99m, \n                    Stock = 0, \n                    Category = \"Accessories\",\n                    IsActive = false,\n                    CreatedAt = DateTime.UtcNow.AddDays(-60)\n                }\n            );\n        });\n    }\n}\n",[3088,6368,6369,6383,6395,6399,6412,6416,6431,6435,6459,6473,6478,6482,6486,6514,6518,6542,6546,6569,6574,6600,6629,6666,6689,6711,6716,6721,6733,6744,6749,6762,6774,6787,6799,6811,6823,6849,6854,6862,6866,6876,6887,6898,6909,6920,6931,6954,6958,6966,6970,6981,6992,7003,7014,7024,7034,7046,7069,7074,7079,7084,7088],{"__ignoreMap":3154},[3158,6370,6371,6373,6376,6378,6381],{"class":3160,"line":3161},[3158,6372,5248],{"class":4440},[3158,6374,6375],{"class":4348}," Microsoft",[3158,6377,3029],{"class":3175},[3158,6379,6380],{"class":4348},"EntityFrameworkCore",[3158,6382,5264],{"class":3175},[3158,6384,6385,6387,6389,6391,6393],{"class":3160,"line":3168},[3158,6386,5248],{"class":4440},[3158,6388,5276],{"class":4348},[3158,6390,3029],{"class":3175},[3158,6392,5281],{"class":4348},[3158,6394,5264],{"class":3175},[3158,6396,6397],{"class":3160,"line":3189},[3158,6398,3193],{"emptyLinePlaceholder":3192},[3158,6400,6401,6403,6405,6407,6410],{"class":3160,"line":3196},[3158,6402,5273],{"class":4363},[3158,6404,5276],{"class":4348},[3158,6406,3029],{"class":3175},[3158,6408,6409],{"class":4348},"Data",[3158,6411,5264],{"class":3175},[3158,6413,6414],{"class":3160,"line":3202},[3158,6415,3193],{"emptyLinePlaceholder":3192},[3158,6417,6418,6420,6422,6425,6428],{"class":3160,"line":3223},[3158,6419,4364],{"class":4363},[3158,6421,5294],{"class":4363},[3158,6423,6424],{"class":4348}," ProductDbContext",[3158,6426,6427],{"class":3175}," : ",[3158,6429,6430],{"class":4348},"DbContext\n",[3158,6432,6433],{"class":3160,"line":3249},[3158,6434,4396],{"class":3175},[3158,6436,6437,6439,6441,6443,6446,6448,6451,6453,6456],{"class":3160,"line":3274},[3158,6438,5306],{"class":4363},[3158,6440,6424],{"class":3171},[3158,6442,3176],{"class":3175},[3158,6444,6445],{"class":4348},"DbContextOptions",[3158,6447,4373],{"class":3175},[3158,6449,6450],{"class":4348},"ProductDbContext",[3158,6452,4378],{"class":3175},[3158,6454,6455],{"class":3179},"options",[3158,6457,6458],{"class":3175},") \n",[3158,6460,6461,6464,6467,6469,6471],{"class":3160,"line":3279},[3158,6462,6463],{"class":3175},"        : ",[3158,6465,6466],{"class":4363},"base",[3158,6468,3176],{"class":3175},[3158,6470,6455],{"class":3179},[3158,6472,3527],{"class":3175},[3158,6474,6475],{"class":3160,"line":3285},[3158,6476,6477],{"class":3175},"    {\n",[3158,6479,6480],{"class":3160,"line":3305},[3158,6481,3879],{"class":3175},[3158,6483,6484],{"class":3160,"line":3310},[3158,6485,3193],{"emptyLinePlaceholder":3192},[3158,6487,6488,6490,6493,6495,6497,6499,6501,6504,6507,6509,6511],{"class":3160,"line":3316},[3158,6489,5306],{"class":4363},[3158,6491,6492],{"class":4348}," DbSet",[3158,6494,4373],{"class":3175},[3158,6496,4526],{"class":4348},[3158,6498,4378],{"class":3175},[3158,6500,4418],{"class":3179},[3158,6502,6503],{"class":3175}," => ",[3158,6505,6506],{"class":3171},"Set",[3158,6508,4373],{"class":3175},[3158,6510,4526],{"class":4348},[3158,6512,6513],{"class":3175},">();\n",[3158,6515,6516],{"class":3160,"line":3443},[3158,6517,3193],{"emptyLinePlaceholder":3192},[3158,6519,6520,6523,6526,6529,6532,6534,6537,6540],{"class":3160,"line":3458},[3158,6521,6522],{"class":4363},"    protected",[3158,6524,6525],{"class":4363}," override",[3158,6527,6528],{"class":4363}," void",[3158,6530,6531],{"class":3171}," OnModelCreating",[3158,6533,3176],{"class":3175},[3158,6535,6536],{"class":4348},"ModelBuilder",[3158,6538,6539],{"class":3179}," modelBuilder",[3158,6541,3527],{"class":3175},[3158,6543,6544],{"class":3160,"line":3463},[3158,6545,6477],{"class":3175},[3158,6547,6548,6551,6553,6556,6558,6560,6563,6566],{"class":3160,"line":3469},[3158,6549,6550],{"class":3179},"        modelBuilder",[3158,6552,3029],{"class":3175},[3158,6554,6555],{"class":3171},"Entity",[3158,6557,4373],{"class":3175},[3158,6559,4526],{"class":4348},[3158,6561,6562],{"class":3175},">(",[3158,6564,6565],{"class":3179},"entity",[3158,6567,6568],{"class":3175}," =>\n",[3158,6570,6571],{"class":3160,"line":3480},[3158,6572,6573],{"class":3175},"        {\n",[3158,6575,6576,6579,6581,6584,6586,6589,6591,6593,6595,6598],{"class":3160,"line":3495},[3158,6577,6578],{"class":3179},"            entity",[3158,6580,3029],{"class":3175},[3158,6582,6583],{"class":3171},"HasKey",[3158,6585,3176],{"class":3175},[3158,6587,6588],{"class":3179},"e",[3158,6590,6503],{"class":3175},[3158,6592,6588],{"class":3179},[3158,6594,3029],{"class":3175},[3158,6596,6597],{"class":3179},"Id",[3158,6599,4431],{"class":3175},[3158,6601,6602,6604,6606,6609,6611,6613,6615,6617,6619,6621,6624,6627],{"class":3160,"line":3500},[3158,6603,6578],{"class":3179},[3158,6605,3029],{"class":3175},[3158,6607,6608],{"class":3171},"Property",[3158,6610,3176],{"class":3175},[3158,6612,6588],{"class":3179},[3158,6614,6503],{"class":3175},[3158,6616,6588],{"class":3179},[3158,6618,3029],{"class":3175},[3158,6620,5966],{"class":3179},[3158,6622,6623],{"class":3175},").",[3158,6625,6626],{"class":3171},"IsRequired",[3158,6628,4968],{"class":3175},[3158,6630,6631,6633,6635,6637,6639,6641,6643,6645,6647,6649,6651,6654,6656,6659,6661,6664],{"class":3160,"line":3506},[3158,6632,6578],{"class":3179},[3158,6634,3029],{"class":3175},[3158,6636,6608],{"class":3171},[3158,6638,3176],{"class":3175},[3158,6640,6588],{"class":3179},[3158,6642,6503],{"class":3175},[3158,6644,6588],{"class":3179},[3158,6646,3029],{"class":3175},[3158,6648,6043],{"class":3179},[3158,6650,6623],{"class":3175},[3158,6652,6653],{"class":3171},"HasPrecision",[3158,6655,3176],{"class":3175},[3158,6657,6658],{"class":3551},"18",[3158,6660,3132],{"class":3175},[3158,6662,6663],{"class":3551},"2",[3158,6665,4431],{"class":3175},[3158,6667,6668,6670,6672,6675,6677,6679,6681,6683,6685,6687],{"class":3160,"line":3518},[3158,6669,6578],{"class":3179},[3158,6671,3029],{"class":3175},[3158,6673,6674],{"class":3171},"HasIndex",[3158,6676,3176],{"class":3175},[3158,6678,6588],{"class":3179},[3158,6680,6503],{"class":3175},[3158,6682,6588],{"class":3179},[3158,6684,3029],{"class":3175},[3158,6686,5533],{"class":3179},[3158,6688,4431],{"class":3175},[3158,6690,6691,6693,6695,6697,6699,6701,6703,6705,6707,6709],{"class":3160,"line":3959},[3158,6692,6578],{"class":3179},[3158,6694,3029],{"class":3175},[3158,6696,6674],{"class":3171},[3158,6698,3176],{"class":3175},[3158,6700,6588],{"class":3179},[3158,6702,6503],{"class":3175},[3158,6704,6588],{"class":3179},[3158,6706,3029],{"class":3175},[3158,6708,6149],{"class":3179},[3158,6710,4431],{"class":3175},[3158,6712,6713],{"class":3160,"line":3965},[3158,6714,6715],{"class":3175},"            \n",[3158,6717,6718],{"class":3160,"line":3971},[3158,6719,6720],{"class":3164},"            // Seed data для демонстрації\n",[3158,6722,6723,6725,6727,6730],{"class":3160,"line":3976},[3158,6724,6578],{"class":3179},[3158,6726,3029],{"class":3175},[3158,6728,6729],{"class":3171},"HasData",[3158,6731,6732],{"class":3175},"(\n",[3158,6734,6735,6738,6741],{"class":3160,"line":3981},[3158,6736,6737],{"class":4363},"                new",[3158,6739,6740],{"class":4348}," Product",[3158,6742,6743],{"class":3175}," \n",[3158,6745,6746],{"class":3160,"line":3987},[3158,6747,6748],{"class":3175},"                { \n",[3158,6750,6751,6754,6756,6759],{"class":3160,"line":3993},[3158,6752,6753],{"class":3179},"                    Id",[3158,6755,4407],{"class":3175},[3158,6757,6758],{"class":3551},"1",[3158,6760,6761],{"class":3175},", \n",[3158,6763,6764,6767,6769,6772],{"class":3160,"line":3998},[3158,6765,6766],{"class":3179},"                    Name",[3158,6768,4407],{"class":3175},[3158,6770,6771],{"class":4354},"\"Laptop Dell XPS 15\"",[3158,6773,6761],{"class":3175},[3158,6775,6776,6779,6781,6784],{"class":3160,"line":4003},[3158,6777,6778],{"class":3179},"                    Description",[3158,6780,4407],{"class":3175},[3158,6782,6783],{"class":4354},"\"High-performance laptop for developers\"",[3158,6785,6786],{"class":3175},",\n",[3158,6788,6789,6792,6794,6797],{"class":3160,"line":4009},[3158,6790,6791],{"class":3179},"                    Price",[3158,6793,4407],{"class":3175},[3158,6795,6796],{"class":3551},"1499.99m",[3158,6798,6761],{"class":3175},[3158,6800,6801,6804,6806,6809],{"class":3160,"line":4015},[3158,6802,6803],{"class":3179},"                    Stock",[3158,6805,4407],{"class":3175},[3158,6807,6808],{"class":3551},"10",[3158,6810,6761],{"class":3175},[3158,6812,6813,6816,6818,6821],{"class":3160,"line":4021},[3158,6814,6815],{"class":3179},"                    Category",[3158,6817,4407],{"class":3175},[3158,6819,6820],{"class":4354},"\"Electronics\"",[3158,6822,6786],{"class":3175},[3158,6824,6825,6828,6830,6832,6834,6836,6838,6841,6844,6847],{"class":3160,"line":4026},[3158,6826,6827],{"class":3179},"                    CreatedAt",[3158,6829,4407],{"class":3175},[3158,6831,5600],{"class":3179},[3158,6833,3029],{"class":3175},[3158,6835,5605],{"class":3179},[3158,6837,3029],{"class":3175},[3158,6839,6840],{"class":3171},"AddDays",[3158,6842,6843],{"class":3175},"(-",[3158,6845,6846],{"class":3551},"30",[3158,6848,3527],{"class":3175},[3158,6850,6851],{"class":3160,"line":4031},[3158,6852,6853],{"class":3175},"                },\n",[3158,6855,6856,6858,6860],{"class":3160,"line":4037},[3158,6857,6737],{"class":4363},[3158,6859,6740],{"class":4348},[3158,6861,6743],{"class":3175},[3158,6863,6864],{"class":3160,"line":4043},[3158,6865,6748],{"class":3175},[3158,6867,6868,6870,6872,6874],{"class":3160,"line":4048},[3158,6869,6753],{"class":3179},[3158,6871,4407],{"class":3175},[3158,6873,6663],{"class":3551},[3158,6875,6761],{"class":3175},[3158,6877,6878,6880,6882,6885],{"class":3160,"line":4053},[3158,6879,6766],{"class":3179},[3158,6881,4407],{"class":3175},[3158,6883,6884],{"class":4354},"\"Mechanical Keyboard\"",[3158,6886,6761],{"class":3175},[3158,6888,6889,6891,6893,6896],{"class":3160,"line":4059},[3158,6890,6778],{"class":3179},[3158,6892,4407],{"class":3175},[3158,6894,6895],{"class":4354},"\"RGB mechanical keyboard with Cherry MX switches\"",[3158,6897,6786],{"class":3175},[3158,6899,6900,6902,6904,6907],{"class":3160,"line":4065},[3158,6901,6791],{"class":3179},[3158,6903,4407],{"class":3175},[3158,6905,6906],{"class":3551},"129.99m",[3158,6908,6761],{"class":3175},[3158,6910,6911,6913,6915,6918],{"class":3160,"line":4070},[3158,6912,6803],{"class":3179},[3158,6914,4407],{"class":3175},[3158,6916,6917],{"class":3551},"25",[3158,6919,6761],{"class":3175},[3158,6921,6922,6924,6926,6929],{"class":3160,"line":4075},[3158,6923,6815],{"class":3179},[3158,6925,4407],{"class":3175},[3158,6927,6928],{"class":4354},"\"Accessories\"",[3158,6930,6786],{"class":3175},[3158,6932,6933,6935,6937,6939,6941,6943,6945,6947,6949,6952],{"class":3160,"line":4081},[3158,6934,6827],{"class":3179},[3158,6936,4407],{"class":3175},[3158,6938,5600],{"class":3179},[3158,6940,3029],{"class":3175},[3158,6942,5605],{"class":3179},[3158,6944,3029],{"class":3175},[3158,6946,6840],{"class":3171},[3158,6948,6843],{"class":3175},[3158,6950,6951],{"class":3551},"15",[3158,6953,3527],{"class":3175},[3158,6955,6956],{"class":3160,"line":4087},[3158,6957,6853],{"class":3175},[3158,6959,6960,6962,6964],{"class":3160,"line":4092},[3158,6961,6737],{"class":4363},[3158,6963,6740],{"class":4348},[3158,6965,6743],{"class":3175},[3158,6967,6968],{"class":3160,"line":4097},[3158,6969,6748],{"class":3175},[3158,6971,6972,6974,6976,6979],{"class":3160,"line":4103},[3158,6973,6753],{"class":3179},[3158,6975,4407],{"class":3175},[3158,6977,6978],{"class":3551},"3",[3158,6980,6761],{"class":3175},[3158,6982,6983,6985,6987,6990],{"class":3160,"line":4109},[3158,6984,6766],{"class":3179},[3158,6986,4407],{"class":3175},[3158,6988,6989],{"class":4354},"\"USB-C Hub\"",[3158,6991,6761],{"class":3175},[3158,6993,6994,6996,6998,7001],{"class":3160,"line":4114},[3158,6995,6778],{"class":3179},[3158,6997,4407],{"class":3175},[3158,6999,7000],{"class":4354},"\"7-in-1 USB-C hub with HDMI and Ethernet\"",[3158,7002,6786],{"class":3175},[3158,7004,7005,7007,7009,7012],{"class":3160,"line":4119},[3158,7006,6791],{"class":3179},[3158,7008,4407],{"class":3175},[3158,7010,7011],{"class":3551},"49.99m",[3158,7013,6761],{"class":3175},[3158,7015,7016,7018,7020,7022],{"class":3160,"line":4125},[3158,7017,6803],{"class":3179},[3158,7019,4407],{"class":3175},[3158,7021,5475],{"class":3551},[3158,7023,6761],{"class":3175},[3158,7025,7026,7028,7030,7032],{"class":3160,"line":4131},[3158,7027,6815],{"class":3179},[3158,7029,4407],{"class":3175},[3158,7031,6928],{"class":4354},[3158,7033,6786],{"class":3175},[3158,7035,7036,7039,7041,7044],{"class":3160,"line":4136},[3158,7037,7038],{"class":3179},"                    IsActive",[3158,7040,4407],{"class":3175},[3158,7042,7043],{"class":4363},"false",[3158,7045,6786],{"class":3175},[3158,7047,7048,7050,7052,7054,7056,7058,7060,7062,7064,7067],{"class":3160,"line":4141},[3158,7049,6827],{"class":3179},[3158,7051,4407],{"class":3175},[3158,7053,5600],{"class":3179},[3158,7055,3029],{"class":3175},[3158,7057,5605],{"class":3179},[3158,7059,3029],{"class":3175},[3158,7061,6840],{"class":3171},[3158,7063,6843],{"class":3175},[3158,7065,7066],{"class":3551},"60",[3158,7068,3527],{"class":3175},[3158,7070,7071],{"class":3160,"line":4147},[3158,7072,7073],{"class":3175},"                }\n",[3158,7075,7076],{"class":3160,"line":4153},[3158,7077,7078],{"class":3175},"            );\n",[3158,7080,7081],{"class":3160,"line":4159},[3158,7082,7083],{"class":3175},"        });\n",[3158,7085,7086],{"class":3160,"line":4165},[3158,7087,3879],{"class":3175},[3158,7089,7090],{"class":3160,"line":4170},[3158,7091,4496],{"class":3175},[3038,7093,7095],{"id":7094},"налаштування-programcs","Налаштування Program.cs",[3149,7097,7099],{"className":3151,"code":7098,"language":3153,"meta":3154,"style":3154},"using Microsoft.EntityFrameworkCore;\nusing ProductsApi.Data;\n\nvar builder = WebApplication.CreateBuilder(args);\n\n// Реєстрація DbContext з InMemory провайдером\nbuilder.Services.AddDbContext\u003CProductDbContext>(options =>\n    options.UseInMemoryDatabase(\"ProductsDb\"));\n\nbuilder.Services.AddControllers();\nbuilder.Services.AddEndpointsApiExplorer();\nbuilder.Services.AddSwaggerGen(options =>\n{\n    options.SwaggerDoc(\"v1\", new() \n    { \n        Title = \"Products API\", \n        Version = \"v1\",\n        Description = \"API для управління товарами інтернет-магазину\"\n    });\n    \n    // Підключення XML-коментарів для документації\n    var xmlFile = $\"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}.xml\";\n    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);\n    if (File.Exists(xmlPath))\n    {\n        options.IncludeXmlComments(xmlPath);\n    }\n});\n\nvar app = builder.Build();\n\n// Ініціалізація бази даних\nusing (var scope = app.Services.CreateScope())\n{\n    var db = scope.ServiceProvider.GetRequiredService\u003CProductDbContext>();\n    db.Database.EnsureCreated();\n}\n\nif (app.Environment.IsDevelopment())\n{\n    app.UseSwagger();\n    app.UseSwaggerUI();\n}\n\napp.UseHttpsRedirection();\napp.UseAuthorization();\napp.MapControllers();\n\napp.Run();\n",[3088,7100,7101,7113,7125,7129,7154,7158,7163,7188,7206,7210,7225,7240,7259,7263,7285,7290,7302,7313,7323,7328,7332,7337,7389,7423,7444,7448,7464,7468,7473,7477,7495,7499,7504,7532,7536,7564,7581,7585,7589,7610,7614,7626,7637,7641,7645,7656,7667,7678,7682],{"__ignoreMap":3154},[3158,7102,7103,7105,7107,7109,7111],{"class":3160,"line":3161},[3158,7104,5248],{"class":4440},[3158,7106,6375],{"class":4348},[3158,7108,3029],{"class":3175},[3158,7110,6380],{"class":4348},[3158,7112,5264],{"class":3175},[3158,7114,7115,7117,7119,7121,7123],{"class":3160,"line":3168},[3158,7116,5248],{"class":4440},[3158,7118,5276],{"class":4348},[3158,7120,3029],{"class":3175},[3158,7122,6409],{"class":4348},[3158,7124,5264],{"class":3175},[3158,7126,7127],{"class":3160,"line":3189},[3158,7128,3193],{"emptyLinePlaceholder":3192},[3158,7130,7131,7134,7137,7139,7142,7144,7147,7149,7152],{"class":3160,"line":3196},[3158,7132,7133],{"class":4363},"var",[3158,7135,7136],{"class":3179}," builder",[3158,7138,4407],{"class":3175},[3158,7140,7141],{"class":3179},"WebApplication",[3158,7143,3029],{"class":3175},[3158,7145,7146],{"class":3171},"CreateBuilder",[3158,7148,3176],{"class":3175},[3158,7150,7151],{"class":3179},"args",[3158,7153,4431],{"class":3175},[3158,7155,7156],{"class":3160,"line":3202},[3158,7157,3193],{"emptyLinePlaceholder":3192},[3158,7159,7160],{"class":3160,"line":3223},[3158,7161,7162],{"class":3164},"// Реєстрація DbContext з InMemory провайдером\n",[3158,7164,7165,7168,7170,7173,7175,7178,7180,7182,7184,7186],{"class":3160,"line":3249},[3158,7166,7167],{"class":3179},"builder",[3158,7169,3029],{"class":3175},[3158,7171,7172],{"class":3179},"Services",[3158,7174,3029],{"class":3175},[3158,7176,7177],{"class":3171},"AddDbContext",[3158,7179,4373],{"class":3175},[3158,7181,6450],{"class":4348},[3158,7183,6562],{"class":3175},[3158,7185,6455],{"class":3179},[3158,7187,6568],{"class":3175},[3158,7189,7190,7193,7195,7198,7200,7203],{"class":3160,"line":3274},[3158,7191,7192],{"class":3179},"    options",[3158,7194,3029],{"class":3175},[3158,7196,7197],{"class":3171},"UseInMemoryDatabase",[3158,7199,3176],{"class":3175},[3158,7201,7202],{"class":4354},"\"ProductsDb\"",[3158,7204,7205],{"class":3175},"));\n",[3158,7207,7208],{"class":3160,"line":3279},[3158,7209,3193],{"emptyLinePlaceholder":3192},[3158,7211,7212,7214,7216,7218,7220,7223],{"class":3160,"line":3285},[3158,7213,7167],{"class":3179},[3158,7215,3029],{"class":3175},[3158,7217,7172],{"class":3179},[3158,7219,3029],{"class":3175},[3158,7221,7222],{"class":3171},"AddControllers",[3158,7224,4968],{"class":3175},[3158,7226,7227,7229,7231,7233,7235,7238],{"class":3160,"line":3305},[3158,7228,7167],{"class":3179},[3158,7230,3029],{"class":3175},[3158,7232,7172],{"class":3179},[3158,7234,3029],{"class":3175},[3158,7236,7237],{"class":3171},"AddEndpointsApiExplorer",[3158,7239,4968],{"class":3175},[3158,7241,7242,7244,7246,7248,7250,7253,7255,7257],{"class":3160,"line":3310},[3158,7243,7167],{"class":3179},[3158,7245,3029],{"class":3175},[3158,7247,7172],{"class":3179},[3158,7249,3029],{"class":3175},[3158,7251,7252],{"class":3171},"AddSwaggerGen",[3158,7254,3176],{"class":3175},[3158,7256,6455],{"class":3179},[3158,7258,6568],{"class":3175},[3158,7260,7261],{"class":3160,"line":3316},[3158,7262,4396],{"class":3175},[3158,7264,7265,7267,7269,7272,7274,7277,7279,7282],{"class":3160,"line":3443},[3158,7266,7192],{"class":3179},[3158,7268,3029],{"class":3175},[3158,7270,7271],{"class":3171},"SwaggerDoc",[3158,7273,3176],{"class":3175},[3158,7275,7276],{"class":4354},"\"v1\"",[3158,7278,3132],{"class":3175},[3158,7280,7281],{"class":4363},"new",[3158,7283,7284],{"class":3175},"() \n",[3158,7286,7287],{"class":3160,"line":3458},[3158,7288,7289],{"class":3175},"    { \n",[3158,7291,7292,7295,7297,7300],{"class":3160,"line":3463},[3158,7293,7294],{"class":3179},"        Title",[3158,7296,4407],{"class":3175},[3158,7298,7299],{"class":4354},"\"Products API\"",[3158,7301,6761],{"class":3175},[3158,7303,7304,7307,7309,7311],{"class":3160,"line":3469},[3158,7305,7306],{"class":3179},"        Version",[3158,7308,4407],{"class":3175},[3158,7310,7276],{"class":4354},[3158,7312,6786],{"class":3175},[3158,7314,7315,7318,7320],{"class":3160,"line":3480},[3158,7316,7317],{"class":3179},"        Description",[3158,7319,4407],{"class":3175},[3158,7321,7322],{"class":4354},"\"API для управління товарами інтернет-магазину\"\n",[3158,7324,7325],{"class":3160,"line":3495},[3158,7326,7327],{"class":3175},"    });\n",[3158,7329,7330],{"class":3160,"line":3500},[3158,7331,3884],{"class":3175},[3158,7333,7334],{"class":3160,"line":3506},[3158,7335,7336],{"class":3164},"    // Підключення XML-коментарів для документації\n",[3158,7338,7339,7341,7344,7346,7349,7353,7356,7358,7361,7363,7366,7368,7371,7374,7377,7379,7381,7384,7387],{"class":3160,"line":3518},[3158,7340,4401],{"class":4363},[3158,7342,7343],{"class":3179}," xmlFile",[3158,7345,4407],{"class":3175},[3158,7347,7348],{"class":4354},"$\"",[3158,7350,7352],{"class":7351},"sD7JJ","{",[3158,7354,7355],{"class":3179},"System",[3158,7357,3029],{"class":7351},[3158,7359,7360],{"class":3179},"Reflection",[3158,7362,3029],{"class":7351},[3158,7364,7365],{"class":3179},"Assembly",[3158,7367,3029],{"class":7351},[3158,7369,7370],{"class":3171},"GetExecutingAssembly",[3158,7372,7373],{"class":7351},"().",[3158,7375,7376],{"class":3171},"GetName",[3158,7378,7373],{"class":7351},[3158,7380,5966],{"class":3179},[3158,7382,7383],{"class":7351},"}",[3158,7385,7386],{"class":4354},".xml\"",[3158,7388,5264],{"class":3175},[3158,7390,7391,7393,7396,7398,7401,7403,7406,7408,7411,7413,7416,7418,7421],{"class":3160,"line":3959},[3158,7392,4401],{"class":4363},[3158,7394,7395],{"class":3179}," xmlPath",[3158,7397,4407],{"class":3175},[3158,7399,7400],{"class":3179},"Path",[3158,7402,3029],{"class":3175},[3158,7404,7405],{"class":3171},"Combine",[3158,7407,3176],{"class":3175},[3158,7409,7410],{"class":3179},"AppContext",[3158,7412,3029],{"class":3175},[3158,7414,7415],{"class":3179},"BaseDirectory",[3158,7417,3132],{"class":3175},[3158,7419,7420],{"class":3179},"xmlFile",[3158,7422,4431],{"class":3175},[3158,7424,7425,7427,7429,7431,7433,7436,7438,7441],{"class":3160,"line":3965},[3158,7426,4441],{"class":4440},[3158,7428,4444],{"class":3175},[3158,7430,3628],{"class":3179},[3158,7432,3029],{"class":3175},[3158,7434,7435],{"class":3171},"Exists",[3158,7437,3176],{"class":3175},[3158,7439,7440],{"class":3179},"xmlPath",[3158,7442,7443],{"class":3175},"))\n",[3158,7445,7446],{"class":3160,"line":3971},[3158,7447,6477],{"class":3175},[3158,7449,7450,7453,7455,7458,7460,7462],{"class":3160,"line":3976},[3158,7451,7452],{"class":3179},"        options",[3158,7454,3029],{"class":3175},[3158,7456,7457],{"class":3171},"IncludeXmlComments",[3158,7459,3176],{"class":3175},[3158,7461,7440],{"class":3179},[3158,7463,4431],{"class":3175},[3158,7465,7466],{"class":3160,"line":3981},[3158,7467,3879],{"class":3175},[3158,7469,7470],{"class":3160,"line":3987},[3158,7471,7472],{"class":3175},"});\n",[3158,7474,7475],{"class":3160,"line":3993},[3158,7476,3193],{"emptyLinePlaceholder":3192},[3158,7478,7479,7481,7484,7486,7488,7490,7493],{"class":3160,"line":3998},[3158,7480,7133],{"class":4363},[3158,7482,7483],{"class":3179}," app",[3158,7485,4407],{"class":3175},[3158,7487,7167],{"class":3179},[3158,7489,3029],{"class":3175},[3158,7491,7492],{"class":3171},"Build",[3158,7494,4968],{"class":3175},[3158,7496,7497],{"class":3160,"line":4003},[3158,7498,3193],{"emptyLinePlaceholder":3192},[3158,7500,7501],{"class":3160,"line":4009},[3158,7502,7503],{"class":3164},"// Ініціалізація бази даних\n",[3158,7505,7506,7508,7510,7512,7515,7517,7520,7522,7524,7526,7529],{"class":3160,"line":4015},[3158,7507,5248],{"class":4440},[3158,7509,4444],{"class":3175},[3158,7511,7133],{"class":4363},[3158,7513,7514],{"class":3179}," scope",[3158,7516,4407],{"class":3175},[3158,7518,7519],{"class":3179},"app",[3158,7521,3029],{"class":3175},[3158,7523,7172],{"class":3179},[3158,7525,3029],{"class":3175},[3158,7527,7528],{"class":3171},"CreateScope",[3158,7530,7531],{"class":3175},"())\n",[3158,7533,7534],{"class":3160,"line":4021},[3158,7535,4396],{"class":3175},[3158,7537,7538,7540,7543,7545,7548,7550,7553,7555,7558,7560,7562],{"class":3160,"line":4026},[3158,7539,4401],{"class":4363},[3158,7541,7542],{"class":3179}," db",[3158,7544,4407],{"class":3175},[3158,7546,7547],{"class":3179},"scope",[3158,7549,3029],{"class":3175},[3158,7551,7552],{"class":3179},"ServiceProvider",[3158,7554,3029],{"class":3175},[3158,7556,7557],{"class":3171},"GetRequiredService",[3158,7559,4373],{"class":3175},[3158,7561,6450],{"class":4348},[3158,7563,6513],{"class":3175},[3158,7565,7566,7569,7571,7574,7576,7579],{"class":3160,"line":4031},[3158,7567,7568],{"class":3179},"    db",[3158,7570,3029],{"class":3175},[3158,7572,7573],{"class":3179},"Database",[3158,7575,3029],{"class":3175},[3158,7577,7578],{"class":3171},"EnsureCreated",[3158,7580,4968],{"class":3175},[3158,7582,7583],{"class":3160,"line":4037},[3158,7584,4496],{"class":3175},[3158,7586,7587],{"class":3160,"line":4043},[3158,7588,3193],{"emptyLinePlaceholder":3192},[3158,7590,7591,7594,7596,7598,7600,7603,7605,7608],{"class":3160,"line":4048},[3158,7592,7593],{"class":4440},"if",[3158,7595,4444],{"class":3175},[3158,7597,7519],{"class":3179},[3158,7599,3029],{"class":3175},[3158,7601,7602],{"class":3179},"Environment",[3158,7604,3029],{"class":3175},[3158,7606,7607],{"class":3171},"IsDevelopment",[3158,7609,7531],{"class":3175},[3158,7611,7612],{"class":3160,"line":4053},[3158,7613,4396],{"class":3175},[3158,7615,7616,7619,7621,7624],{"class":3160,"line":4059},[3158,7617,7618],{"class":3179},"    app",[3158,7620,3029],{"class":3175},[3158,7622,7623],{"class":3171},"UseSwagger",[3158,7625,4968],{"class":3175},[3158,7627,7628,7630,7632,7635],{"class":3160,"line":4065},[3158,7629,7618],{"class":3179},[3158,7631,3029],{"class":3175},[3158,7633,7634],{"class":3171},"UseSwaggerUI",[3158,7636,4968],{"class":3175},[3158,7638,7639],{"class":3160,"line":4070},[3158,7640,4496],{"class":3175},[3158,7642,7643],{"class":3160,"line":4075},[3158,7644,3193],{"emptyLinePlaceholder":3192},[3158,7646,7647,7649,7651,7654],{"class":3160,"line":4081},[3158,7648,7519],{"class":3179},[3158,7650,3029],{"class":3175},[3158,7652,7653],{"class":3171},"UseHttpsRedirection",[3158,7655,4968],{"class":3175},[3158,7657,7658,7660,7662,7665],{"class":3160,"line":4087},[3158,7659,7519],{"class":3179},[3158,7661,3029],{"class":3175},[3158,7663,7664],{"class":3171},"UseAuthorization",[3158,7666,4968],{"class":3175},[3158,7668,7669,7671,7673,7676],{"class":3160,"line":4092},[3158,7670,7519],{"class":3179},[3158,7672,3029],{"class":3175},[3158,7674,7675],{"class":3171},"MapControllers",[3158,7677,4968],{"class":3175},[3158,7679,7680],{"class":3160,"line":4097},[3158,7681,3193],{"emptyLinePlaceholder":3192},[3158,7683,7684,7686,7688,7691],{"class":3160,"line":4103},[3158,7685,7519],{"class":3179},[3158,7687,3029],{"class":3175},[3158,7689,7690],{"class":3171},"Run",[3158,7692,4968],{"class":3175},[3031,7694,7695,7698,7699,7701],{},[2968,7696,7697],{},"Про InMemory Database:"," Ми використовуємо ",[3088,7700,7197],{}," для простоти демонстрації. У production-середовищі замініть на реальну базу даних (SQL Server, PostgreSQL, тощо).",[3109,7703],{},[3038,7705,7707],{"id":7706},"крок-2-створення-productscontroller-з-різними-типами-відповідей","Крок 2: Створення ProductsController з різними типами відповідей",[2964,7709,5235,7710,7713,7714,4328,7717,3029],{},[3088,7711,7712],{},"Controllers/ProductsController.cs",". Ми реалізуємо кожен endpoint з ",[2968,7715,7716],{},"правильним типом повернення",[2968,7718,7719],{},"HTTP-кодом",[3149,7721,7723],{"className":3151,"code":7722,"language":3153,"meta":3154,"style":3154},"using Microsoft.AspNetCore.Mvc;\nusing Microsoft.EntityFrameworkCore;\nusing ProductsApi.Data;\nusing ProductsApi.DTOs;\nusing ProductsApi.Models;\n\nnamespace ProductsApi.Controllers;\n\n[ApiController]\n[Route(\"api/[controller]\")]\n[Produces(\"application/json\")]\npublic class ProductsController : ControllerBase\n{\n    private readonly ProductDbContext _db;\n    private readonly ILogger\u003CProductsController> _logger;\n\n    public ProductsController(ProductDbContext db, ILogger\u003CProductsController> logger)\n    {\n        _db = db;\n        _logger = logger;\n    }\n\n    /// \u003Csummary>\n    /// Отримати всі активні товари\n    /// \u003C/summary>\n    /// \u003Creturns>Список товарів\u003C/returns>\n    /// \u003Cresponse code=\"200\">Успішно отримано список товарів\u003C/response>\n    [HttpGet]\n    [ProducesResponseType(typeof(IEnumerable\u003CProductResponseDto>), StatusCodes.Status200OK)]\n    public async Task\u003CActionResult\u003CIEnumerable\u003CProductResponseDto>>> GetAll()\n    {\n        _logger.LogInformation(\"Fetching all active products\");\n        \n        var products = await _db.Products\n            .Where(p => p.IsActive)\n            .OrderByDescending(p => p.CreatedAt)\n            .ToListAsync();\n        \n        var response = products.Select(MapToDto);\n        \n        return Ok(response);\n    }\n\n    /// \u003Csummary>\n    /// Отримати товар за ID\n    /// \u003C/summary>\n    /// \u003Cparam name=\"id\">Ідентифікатор товару\u003C/param>\n    /// \u003Creturns>Товар або 404\u003C/returns>\n    /// \u003Cresponse code=\"200\">Товар знайдено\u003C/response>\n    /// \u003Cresponse code=\"404\">Товар не знайдено\u003C/response>\n    [HttpGet(\"{id:int}\")]\n    [ProducesResponseType(typeof(ProductResponseDto), StatusCodes.Status200OK)]\n    [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]\n    public async Task\u003CActionResult\u003CProductResponseDto>> GetById(int id)\n    {\n        _logger.LogInformation(\"Fetching product with ID {ProductId}\", id);\n        \n        var product = await _db.Products.FindAsync(id);\n        \n        if (product is null)\n        {\n            _logger.LogWarning(\"Product with ID {ProductId} not found\", id);\n            return NotFound(new ProblemDetails\n            {\n                Title = \"Product not found\",\n                Detail = $\"Product with ID {id} does not exist\",\n                Status = StatusCodes.Status404NotFound,\n                Instance = HttpContext.Request.Path\n            });\n        }\n        \n        // Неявна конвертація ProductResponseDto → ActionResult\u003CProductResponseDto>\n        return MapToDto(product);\n    }\n\n    /// \u003Csummary>\n    /// Створити новий товар\n    /// \u003C/summary>\n    /// \u003Cparam name=\"dto\">Дані для створення товару\u003C/param>\n    /// \u003Creturns>Створений товар\u003C/returns>\n    /// \u003Cresponse code=\"201\">Товар успішно створено\u003C/response>\n    /// \u003Cresponse code=\"400\">Невалідні дані\u003C/response>\n    /// \u003Cresponse code=\"409\">Товар з такою назвою вже існує\u003C/response>\n    [HttpPost]\n    [ProducesResponseType(typeof(ProductResponseDto), StatusCodes.Status201Created)]\n    [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]\n    [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status409Conflict)]\n    public async Task\u003CActionResult\u003CProductResponseDto>> Create(CreateProductDto dto)\n    {\n        _logger.LogInformation(\"Creating new product: {ProductName}\", dto.Name);\n        \n        // Перевірка на дублікат назви\n        var existingProduct = await _db.Products\n            .FirstOrDefaultAsync(p => p.Name == dto.Name);\n        \n        if (existingProduct is not null)\n        {\n            _logger.LogWarning(\"Product with name '{ProductName}' already exists\", dto.Name);\n            return Conflict(new ProblemDetails\n            {\n                Title = \"Product already exists\",\n                Detail = $\"A product with the name '{dto.Name}' already exists\",\n                Status = StatusCodes.Status409Conflict,\n                Instance = HttpContext.Request.Path\n            });\n        }\n        \n        var product = new Product\n        {\n            Name = dto.Name,\n            Description = dto.Description,\n            Price = dto.Price,\n            Stock = dto.Stock,\n            Category = dto.Category,\n            CreatedAt = DateTime.UtcNow\n        };\n        \n        _db.Products.Add(product);\n        await _db.SaveChangesAsync();\n        \n        var response = MapToDto(product);\n        \n        // CreatedAtAction автоматично генерує Location header\n        return CreatedAtAction(\n            nameof(GetById),\n            new { id = product.Id },\n            response\n        );\n    }\n\n    /// \u003Csummary>\n    /// Оновити існуючий товар\n    /// \u003C/summary>\n    /// \u003Cparam name=\"id\">Ідентифікатор товару\u003C/param>\n    /// \u003Cparam name=\"dto\">Дані для оновлення\u003C/param>\n    /// \u003Creturns>Оновлений товар\u003C/returns>\n    /// \u003Cresponse code=\"200\">Товар успішно оновлено\u003C/response>\n    /// \u003Cresponse code=\"404\">Товар не знайдено\u003C/response>\n    [HttpPut(\"{id:int}\")]\n    [ProducesResponseType(typeof(ProductResponseDto), StatusCodes.Status200OK)]\n    [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]\n    public async Task\u003CActionResult\u003CProductResponseDto>> Update(int id, UpdateProductDto dto)\n    {\n        _logger.LogInformation(\"Updating product with ID {ProductId}\", id);\n        \n        var product = await _db.Products.FindAsync(id);\n        \n        if (product is null)\n        {\n            return NotFound(new ProblemDetails\n            {\n                Title = \"Product not found\",\n                Detail = $\"Product with ID {id} does not exist\",\n                Status = StatusCodes.Status404NotFound\n            });\n        }\n        \n        // Оновлюємо тільки передані поля\n        if (dto.Name is not null) product.Name = dto.Name;\n        if (dto.Description is not null) product.Description = dto.Description;\n        if (dto.Price.HasValue) product.Price = dto.Price.Value;\n        if (dto.Stock.HasValue) product.Stock = dto.Stock.Value;\n        if (dto.Category is not null) product.Category = dto.Category;\n        if (dto.IsActive.HasValue) product.IsActive = dto.IsActive.Value;\n        \n        product.UpdatedAt = DateTime.UtcNow;\n        \n        await _db.SaveChangesAsync();\n        \n        return MapToDto(product);\n    }\n\n    /// \u003Csummary>\n    /// Видалити товар (soft delete - деактивація)\n    /// \u003C/summary>\n    /// \u003Cparam name=\"id\">Ідентифікатор товару\u003C/param>\n    /// \u003Creturns>204 No Content\u003C/returns>\n    /// \u003Cresponse code=\"204\">Товар успішно деактивовано\u003C/response>\n    /// \u003Cresponse code=\"404\">Товар не знайдено\u003C/response>\n    [HttpDelete(\"{id:int}\")]\n    [ProducesResponseType(StatusCodes.Status204NoContent)]\n    [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]\n    public async Task\u003CIActionResult> Delete(int id)\n    {\n        _logger.LogInformation(\"Deactivating product with ID {ProductId}\", id);\n        \n        var product = await _db.Products.FindAsync(id);\n        \n        if (product is null)\n        {\n            return NotFound(new ProblemDetails\n            {\n                Title = \"Product not found\",\n                Detail = $\"Product with ID {id} does not exist\",\n                Status = StatusCodes.Status404NotFound\n            });\n        }\n        \n        // Soft delete - просто деактивуємо\n        product.IsActive = false;\n        product.UpdatedAt = DateTime.UtcNow;\n        \n        await _db.SaveChangesAsync();\n        \n        // NoContent() - успішно, але без даних у відповіді\n        return NoContent();\n    }\n\n    /// \u003Csummary>\n    /// Видалити товар назавжди (hard delete)\n    /// \u003C/summary>\n    /// \u003Cparam name=\"id\">Ідентифікатор товару\u003C/param>\n    /// \u003Creturns>204 No Content\u003C/returns>\n    /// \u003Cresponse code=\"204\">Товар успішно видалено\u003C/response>\n    /// \u003Cresponse code=\"404\">Товар не знайдено\u003C/response>\n    /// \u003Cresponse code=\"409\">Неможливо видалити товар з ненульовим залишком\u003C/response>\n    [HttpDelete(\"{id:int}/permanent\")]\n    [ProducesResponseType(StatusCodes.Status204NoContent)]\n    [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]\n    [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status409Conflict)]\n    public async Task\u003CIActionResult> DeletePermanent(int id)\n    {\n        _logger.LogInformation(\"Permanently deleting product with ID {ProductId}\", id);\n        \n        var product = await _db.Products.FindAsync(id);\n        \n        if (product is null)\n        {\n            return NotFound(new ProblemDetails\n            {\n                Title = \"Product not found\",\n                Detail = $\"Product with ID {id} does not exist\",\n                Status = StatusCodes.Status404NotFound\n            });\n        }\n        \n        // Бізнес-правило: не можна видаляти товар з залишком\n        if (product.Stock > 0)\n        {\n            return Conflict(new ProblemDetails\n            {\n                Title = \"Cannot delete product\",\n                Detail = $\"Product has {product.Stock} items in stock. Reduce stock to zero before deletion.\",\n                Status = StatusCodes.Status409Conflict\n            });\n        }\n        \n        _db.Products.Remove(product);\n        await _db.SaveChangesAsync();\n        \n        return NoContent();\n    }\n\n    /// \u003Csummary>\n    /// Оновити залишок товару\n    /// \u003C/summary>\n    /// \u003Cparam name=\"id\">Ідентифікатор товару\u003C/param>\n    /// \u003Cparam name=\"quantity\">Нова кількість\u003C/param>\n    /// \u003Creturns>204 No Content\u003C/returns>\n    /// \u003Cresponse code=\"204\">Залишок оновлено\u003C/response>\n    /// \u003Cresponse code=\"400\">Невалідна кількість\u003C/response>\n    /// \u003Cresponse code=\"404\">Товар не знайдено\u003C/response>\n    [HttpPatch(\"{id:int}/stock\")]\n    [ProducesResponseType(StatusCodes.Status204NoContent)]\n    [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]\n    [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]\n    public async Task\u003CIActionResult> UpdateStock(int id, [FromQuery] int quantity)\n    {\n        if (quantity \u003C 0)\n        {\n            return BadRequest(new ProblemDetails\n            {\n                Title = \"Invalid quantity\",\n                Detail = \"Stock quantity cannot be negative\",\n                Status = StatusCodes.Status400BadRequest\n            });\n        }\n        \n        var product = await _db.Products.FindAsync(id);\n        \n        if (product is null)\n        {\n            return NotFound(new ProblemDetails\n            {\n                Title = \"Product not found\",\n                Detail = $\"Product with ID {id} does not exist\",\n                Status = StatusCodes.Status404NotFound\n            });\n        }\n        \n        product.Stock = quantity;\n        product.UpdatedAt = DateTime.UtcNow;\n        \n        await _db.SaveChangesAsync();\n        \n        return NoContent();\n    }\n\n    // Приватний допоміжний метод для маппінгу\n    private static ProductResponseDto MapToDto(Product product) => new()\n    {\n        Id = product.Id,\n        Name = product.Name,\n        Description = product.Description,\n        Price = product.Price,\n        Stock = product.Stock,\n        Category = product.Category,\n        IsActive = product.IsActive,\n        CreatedAt = product.CreatedAt,\n        UpdatedAt = product.UpdatedAt\n    };\n}\n",[3088,7724,7725,7743,7755,7767,7779,7791,7795,7808,7812,7821,7835,7849,7863,7867,7881,7902,7906,7934,7938,7950,7961,7965,7969,7984,7989,8000,8021,8051,8059,8094,8123,8127,8143,8148,8167,8189,8211,8220,8224,8248,8252,8264,8268,8272,8282,8287,8297,8325,8344,8369,8395,8408,8433,8459,8487,8491,8510,8514,8540,8544,8559,8563,8584,8598,8603,8615,8636,8651,8671,8676,8681,8685,8690,8703,8707,8711,8721,8726,8737,8764,8784,8811,8838,8865,8875,8901,8928,8954,8986,8991,9016,9021,9027,9045,9076,9081,9100,9105,9129,9143,9148,9160,9185,9200,9217,9222,9227,9232,9245,9250,9266,9282,9298,9314,9330,9345,9351,9356,9376,9391,9396,9413,9418,9424,9434,9447,9468,9474,9480,9485,9490,9501,9507,9518,9543,9569,9589,9615,9640,9654,9679,9704,9741,9746,9766,9771,9798,9803,9818,9823,9836,9841,9852,9871,9885,9890,9895,9900,9906,9943,9980,10021,10060,10097,10136,10141,10161,10166,10179,10184,10197,10202,10207,10218,10224,10235,10260,10279,10306,10331,10345,10363,10388,10414,10419,10439,10444,10471,10476,10491,10496,10509,10514,10525,10544,10557,10562,10567,10572,10578,10593,10612,10617,10630,10635,10641,10651,10656,10661,10672,10678,10689,10714,10733,10759,10784,10810,10824,10841,10866,10891,10917,10922,10942,10947,10974,10979,10994,10999,11012,11017,11028,11047,11060,11065,11070,11075,11081,11101,11106,11119,11124,11136,11161,11175,11180,11185,11190,11210,11223,11228,11237,11242,11247,11258,11264,11275,11300,11327,11346,11372,11398,11423,11438,11455,11480,11505,11545,11550,11567,11572,11586,11591,11603,11615,11629,11634,11639,11644,11671,11676,11691,11696,11709,11714,11725,11744,11757,11762,11767,11772,11787,11806,11811,11824,11829,11838,11843,11848,11854,11880,11885,11901,11917,11932,11948,11964,11980,11996,12012,12027,12033],{"__ignoreMap":3154},[3158,7726,7727,7729,7731,7733,7736,7738,7741],{"class":3160,"line":3161},[3158,7728,5248],{"class":4440},[3158,7730,6375],{"class":4348},[3158,7732,3029],{"class":3175},[3158,7734,7735],{"class":4348},"AspNetCore",[3158,7737,3029],{"class":3175},[3158,7739,7740],{"class":4348},"Mvc",[3158,7742,5264],{"class":3175},[3158,7744,7745,7747,7749,7751,7753],{"class":3160,"line":3168},[3158,7746,5248],{"class":4440},[3158,7748,6375],{"class":4348},[3158,7750,3029],{"class":3175},[3158,7752,6380],{"class":4348},[3158,7754,5264],{"class":3175},[3158,7756,7757,7759,7761,7763,7765],{"class":3160,"line":3189},[3158,7758,5248],{"class":4440},[3158,7760,5276],{"class":4348},[3158,7762,3029],{"class":3175},[3158,7764,6409],{"class":4348},[3158,7766,5264],{"class":3175},[3158,7768,7769,7771,7773,7775,7777],{"class":3160,"line":3196},[3158,7770,5248],{"class":4440},[3158,7772,5276],{"class":4348},[3158,7774,3029],{"class":3175},[3158,7776,5681],{"class":4348},[3158,7778,5264],{"class":3175},[3158,7780,7781,7783,7785,7787,7789],{"class":3160,"line":3202},[3158,7782,5248],{"class":4440},[3158,7784,5276],{"class":4348},[3158,7786,3029],{"class":3175},[3158,7788,5281],{"class":4348},[3158,7790,5264],{"class":3175},[3158,7792,7793],{"class":3160,"line":3223},[3158,7794,3193],{"emptyLinePlaceholder":3192},[3158,7796,7797,7799,7801,7803,7806],{"class":3160,"line":3249},[3158,7798,5273],{"class":4363},[3158,7800,5276],{"class":4348},[3158,7802,3029],{"class":3175},[3158,7804,7805],{"class":4348},"Controllers",[3158,7807,5264],{"class":3175},[3158,7809,7810],{"class":3160,"line":3274},[3158,7811,3193],{"emptyLinePlaceholder":3192},[3158,7813,7814,7816,7819],{"class":3160,"line":3279},[3158,7815,4345],{"class":3175},[3158,7817,7818],{"class":4348},"ApiController",[3158,7820,5341],{"class":3175},[3158,7822,7823,7825,7828,7830,7833],{"class":3160,"line":3285},[3158,7824,4345],{"class":3175},[3158,7826,7827],{"class":4348},"Route",[3158,7829,3176],{"class":3175},[3158,7831,7832],{"class":4354},"\"api/[controller]\"",[3158,7834,4358],{"class":3175},[3158,7836,7837,7839,7842,7844,7847],{"class":3160,"line":3305},[3158,7838,4345],{"class":3175},[3158,7840,7841],{"class":4348},"Produces",[3158,7843,3176],{"class":3175},[3158,7845,7846],{"class":4354},"\"application/json\"",[3158,7848,4358],{"class":3175},[3158,7850,7851,7853,7855,7858,7860],{"class":3160,"line":3310},[3158,7852,4364],{"class":4363},[3158,7854,5294],{"class":4363},[3158,7856,7857],{"class":4348}," ProductsController",[3158,7859,6427],{"class":3175},[3158,7861,7862],{"class":4348},"ControllerBase\n",[3158,7864,7865],{"class":3160,"line":3316},[3158,7866,4396],{"class":3175},[3158,7868,7869,7872,7875,7877,7879],{"class":3160,"line":3443},[3158,7870,7871],{"class":4363},"    private",[3158,7873,7874],{"class":4363}," readonly",[3158,7876,6424],{"class":4348},[3158,7878,4413],{"class":3179},[3158,7880,5264],{"class":3175},[3158,7882,7883,7885,7887,7890,7892,7895,7897,7900],{"class":3160,"line":3458},[3158,7884,7871],{"class":4363},[3158,7886,7874],{"class":4363},[3158,7888,7889],{"class":4348}," ILogger",[3158,7891,4373],{"class":3175},[3158,7893,7894],{"class":4348},"ProductsController",[3158,7896,4378],{"class":3175},[3158,7898,7899],{"class":3179},"_logger",[3158,7901,5264],{"class":3175},[3158,7903,7904],{"class":3160,"line":3463},[3158,7905,3193],{"emptyLinePlaceholder":3192},[3158,7907,7908,7910,7912,7914,7916,7918,7920,7923,7925,7927,7929,7932],{"class":3160,"line":3469},[3158,7909,5306],{"class":4363},[3158,7911,7857],{"class":3171},[3158,7913,3176],{"class":3175},[3158,7915,6450],{"class":4348},[3158,7917,7542],{"class":3179},[3158,7919,3132],{"class":3175},[3158,7921,7922],{"class":4348},"ILogger",[3158,7924,4373],{"class":3175},[3158,7926,7894],{"class":4348},[3158,7928,4378],{"class":3175},[3158,7930,7931],{"class":3179},"logger",[3158,7933,3527],{"class":3175},[3158,7935,7936],{"class":3160,"line":3480},[3158,7937,6477],{"class":3175},[3158,7939,7940,7943,7945,7948],{"class":3160,"line":3495},[3158,7941,7942],{"class":3179},"        _db",[3158,7944,4407],{"class":3175},[3158,7946,7947],{"class":3179},"db",[3158,7949,5264],{"class":3175},[3158,7951,7952,7955,7957,7959],{"class":3160,"line":3500},[3158,7953,7954],{"class":3179},"        _logger",[3158,7956,4407],{"class":3175},[3158,7958,7931],{"class":3179},[3158,7960,5264],{"class":3175},[3158,7962,7963],{"class":3160,"line":3506},[3158,7964,3879],{"class":3175},[3158,7966,7967],{"class":3160,"line":3518},[3158,7968,3193],{"emptyLinePlaceholder":3192},[3158,7970,7971,7974,7977,7981],{"class":3160,"line":3959},[3158,7972,7973],{"class":3164},"    /// ",[3158,7975,4373],{"class":7976},"s0P7L",[3158,7978,7980],{"class":7979},"sKtos","summary",[3158,7982,7983],{"class":7976},">\n",[3158,7985,7986],{"class":3160,"line":3965},[3158,7987,7988],{"class":3164},"    /// Отримати всі активні товари\n",[3158,7990,7991,7993,7996,7998],{"class":3160,"line":3971},[3158,7992,7973],{"class":3164},[3158,7994,7995],{"class":7976},"\u003C/",[3158,7997,7980],{"class":7979},[3158,7999,7983],{"class":7976},[3158,8001,8002,8004,8006,8009,8012,8015,8017,8019],{"class":3160,"line":3976},[3158,8003,7973],{"class":3164},[3158,8005,4373],{"class":7976},[3158,8007,8008],{"class":7979},"returns",[3158,8010,8011],{"class":7976},">",[3158,8013,8014],{"class":3164},"Список товарів",[3158,8016,7995],{"class":7976},[3158,8018,8008],{"class":7979},[3158,8020,7983],{"class":7976},[3158,8022,8023,8025,8027,8030,8034,8037,8040,8042,8045,8047,8049],{"class":3160,"line":3981},[3158,8024,7973],{"class":3164},[3158,8026,4373],{"class":7976},[3158,8028,8029],{"class":7979},"response",[3158,8031,8033],{"class":8032},"sa4r_"," code",[3158,8035,8036],{"class":3164},"=",[3158,8038,8039],{"class":4354},"\"200\"",[3158,8041,8011],{"class":7976},[3158,8043,8044],{"class":3164},"Успішно отримано список товарів",[3158,8046,7995],{"class":7976},[3158,8048,8029],{"class":7979},[3158,8050,7983],{"class":7976},[3158,8052,8053,8055,8057],{"class":3160,"line":3987},[3158,8054,5335],{"class":3175},[3158,8056,4349],{"class":4348},[3158,8058,5341],{"class":3175},[3158,8060,8061,8063,8066,8068,8071,8073,8076,8078,8081,8084,8087,8089,8092],{"class":3160,"line":3993},[3158,8062,5335],{"class":3175},[3158,8064,8065],{"class":4348},"ProducesResponseType",[3158,8067,3176],{"class":3175},[3158,8069,8070],{"class":4363},"typeof",[3158,8072,3176],{"class":3175},[3158,8074,8075],{"class":4348},"IEnumerable",[3158,8077,4373],{"class":3175},[3158,8079,8080],{"class":4348},"ProductResponseDto",[3158,8082,8083],{"class":3175},">), ",[3158,8085,8086],{"class":3179},"StatusCodes",[3158,8088,3029],{"class":3175},[3158,8090,8091],{"class":3179},"Status200OK",[3158,8093,4358],{"class":3175},[3158,8095,8096,8098,8100,8102,8104,8106,8108,8110,8112,8114,8117,8120],{"class":3160,"line":3998},[3158,8097,5306],{"class":4363},[3158,8099,4367],{"class":4363},[3158,8101,4370],{"class":4348},[3158,8103,4373],{"class":3175},[3158,8105,4292],{"class":4348},[3158,8107,4373],{"class":3175},[3158,8109,8075],{"class":4348},[3158,8111,4373],{"class":3175},[3158,8113,8080],{"class":4348},[3158,8115,8116],{"class":3175},">>> ",[3158,8118,8119],{"class":3171},"GetAll",[3158,8121,8122],{"class":3175},"()\n",[3158,8124,8125],{"class":3160,"line":4003},[3158,8126,6477],{"class":3175},[3158,8128,8129,8131,8133,8136,8138,8141],{"class":3160,"line":4009},[3158,8130,7954],{"class":3179},[3158,8132,3029],{"class":3175},[3158,8134,8135],{"class":3171},"LogInformation",[3158,8137,3176],{"class":3175},[3158,8139,8140],{"class":4354},"\"Fetching all active products\"",[3158,8142,4431],{"class":3175},[3158,8144,8145],{"class":3160,"line":4015},[3158,8146,8147],{"class":3175},"        \n",[3158,8149,8150,8153,8156,8158,8160,8162,8164],{"class":3160,"line":4021},[3158,8151,8152],{"class":4363},"        var",[3158,8154,8155],{"class":3179}," products",[3158,8157,4407],{"class":3175},[3158,8159,4410],{"class":4363},[3158,8161,4413],{"class":3179},[3158,8163,3029],{"class":3175},[3158,8165,8166],{"class":3179},"Products\n",[3158,8168,8169,8172,8175,8177,8179,8181,8183,8185,8187],{"class":3160,"line":4026},[3158,8170,8171],{"class":3175},"            .",[3158,8173,8174],{"class":3171},"Where",[3158,8176,3176],{"class":3175},[3158,8178,2964],{"class":3179},[3158,8180,6503],{"class":3175},[3158,8182,2964],{"class":3179},[3158,8184,3029],{"class":3175},[3158,8186,6149],{"class":3179},[3158,8188,3527],{"class":3175},[3158,8190,8191,8193,8196,8198,8200,8202,8204,8206,8209],{"class":3160,"line":4031},[3158,8192,8171],{"class":3175},[3158,8194,8195],{"class":3171},"OrderByDescending",[3158,8197,3176],{"class":3175},[3158,8199,2964],{"class":3179},[3158,8201,6503],{"class":3175},[3158,8203,2964],{"class":3179},[3158,8205,3029],{"class":3175},[3158,8207,8208],{"class":3179},"CreatedAt",[3158,8210,3527],{"class":3175},[3158,8212,8213,8215,8218],{"class":3160,"line":4037},[3158,8214,8171],{"class":3175},[3158,8216,8217],{"class":3171},"ToListAsync",[3158,8219,4968],{"class":3175},[3158,8221,8222],{"class":3160,"line":4043},[3158,8223,8147],{"class":3175},[3158,8225,8226,8228,8231,8233,8236,8238,8241,8243,8246],{"class":3160,"line":4048},[3158,8227,8152],{"class":4363},[3158,8229,8230],{"class":3179}," response",[3158,8232,4407],{"class":3175},[3158,8234,8235],{"class":3179},"products",[3158,8237,3029],{"class":3175},[3158,8239,8240],{"class":3171},"Select",[3158,8242,3176],{"class":3175},[3158,8244,8245],{"class":3179},"MapToDto",[3158,8247,4431],{"class":3175},[3158,8249,8250],{"class":3160,"line":4053},[3158,8251,8147],{"class":3175},[3158,8253,8254,8256,8258,8260,8262],{"class":3160,"line":4059},[3158,8255,4460],{"class":4440},[3158,8257,4481],{"class":3171},[3158,8259,3176],{"class":3175},[3158,8261,8029],{"class":3179},[3158,8263,4431],{"class":3175},[3158,8265,8266],{"class":3160,"line":4065},[3158,8267,3879],{"class":3175},[3158,8269,8270],{"class":3160,"line":4070},[3158,8271,3193],{"emptyLinePlaceholder":3192},[3158,8273,8274,8276,8278,8280],{"class":3160,"line":4075},[3158,8275,7973],{"class":3164},[3158,8277,4373],{"class":7976},[3158,8279,7980],{"class":7979},[3158,8281,7983],{"class":7976},[3158,8283,8284],{"class":3160,"line":4081},[3158,8285,8286],{"class":3164},"    /// Отримати товар за ID\n",[3158,8288,8289,8291,8293,8295],{"class":3160,"line":4087},[3158,8290,7973],{"class":3164},[3158,8292,7995],{"class":7976},[3158,8294,7980],{"class":7979},[3158,8296,7983],{"class":7976},[3158,8298,8299,8301,8303,8306,8309,8311,8314,8316,8319,8321,8323],{"class":3160,"line":4092},[3158,8300,7973],{"class":3164},[3158,8302,4373],{"class":7976},[3158,8304,8305],{"class":7979},"param",[3158,8307,8308],{"class":8032}," name",[3158,8310,8036],{"class":3164},[3158,8312,8313],{"class":4354},"\"id\"",[3158,8315,8011],{"class":7976},[3158,8317,8318],{"class":3164},"Ідентифікатор товару",[3158,8320,7995],{"class":7976},[3158,8322,8305],{"class":7979},[3158,8324,7983],{"class":7976},[3158,8326,8327,8329,8331,8333,8335,8338,8340,8342],{"class":3160,"line":4097},[3158,8328,7973],{"class":3164},[3158,8330,4373],{"class":7976},[3158,8332,8008],{"class":7979},[3158,8334,8011],{"class":7976},[3158,8336,8337],{"class":3164},"Товар або 404",[3158,8339,7995],{"class":7976},[3158,8341,8008],{"class":7979},[3158,8343,7983],{"class":7976},[3158,8345,8346,8348,8350,8352,8354,8356,8358,8360,8363,8365,8367],{"class":3160,"line":4103},[3158,8347,7973],{"class":3164},[3158,8349,4373],{"class":7976},[3158,8351,8029],{"class":7979},[3158,8353,8033],{"class":8032},[3158,8355,8036],{"class":3164},[3158,8357,8039],{"class":4354},[3158,8359,8011],{"class":7976},[3158,8361,8362],{"class":3164},"Товар знайдено",[3158,8364,7995],{"class":7976},[3158,8366,8029],{"class":7979},[3158,8368,7983],{"class":7976},[3158,8370,8371,8373,8375,8377,8379,8381,8384,8386,8389,8391,8393],{"class":3160,"line":4109},[3158,8372,7973],{"class":3164},[3158,8374,4373],{"class":7976},[3158,8376,8029],{"class":7979},[3158,8378,8033],{"class":8032},[3158,8380,8036],{"class":3164},[3158,8382,8383],{"class":4354},"\"404\"",[3158,8385,8011],{"class":7976},[3158,8387,8388],{"class":3164},"Товар не знайдено",[3158,8390,7995],{"class":7976},[3158,8392,8029],{"class":7979},[3158,8394,7983],{"class":7976},[3158,8396,8397,8399,8401,8403,8406],{"class":3160,"line":4114},[3158,8398,5335],{"class":3175},[3158,8400,4349],{"class":4348},[3158,8402,3176],{"class":3175},[3158,8404,8405],{"class":4354},"\"{id:int}\"",[3158,8407,4358],{"class":3175},[3158,8409,8410,8412,8414,8416,8418,8420,8422,8425,8427,8429,8431],{"class":3160,"line":4119},[3158,8411,5335],{"class":3175},[3158,8413,8065],{"class":4348},[3158,8415,3176],{"class":3175},[3158,8417,8070],{"class":4363},[3158,8419,3176],{"class":3175},[3158,8421,8080],{"class":4348},[3158,8423,8424],{"class":3175},"), ",[3158,8426,8086],{"class":3179},[3158,8428,3029],{"class":3175},[3158,8430,8091],{"class":3179},[3158,8432,4358],{"class":3175},[3158,8434,8435,8437,8439,8441,8443,8445,8448,8450,8452,8454,8457],{"class":3160,"line":4125},[3158,8436,5335],{"class":3175},[3158,8438,8065],{"class":4348},[3158,8440,3176],{"class":3175},[3158,8442,8070],{"class":4363},[3158,8444,3176],{"class":3175},[3158,8446,8447],{"class":4348},"ProblemDetails",[3158,8449,8424],{"class":3175},[3158,8451,8086],{"class":3179},[3158,8453,3029],{"class":3175},[3158,8455,8456],{"class":3179},"Status404NotFound",[3158,8458,4358],{"class":3175},[3158,8460,8461,8463,8465,8467,8469,8471,8473,8475,8477,8479,8481,8483,8485],{"class":3160,"line":4131},[3158,8462,5306],{"class":4363},[3158,8464,4367],{"class":4363},[3158,8466,4370],{"class":4348},[3158,8468,4373],{"class":3175},[3158,8470,4292],{"class":4348},[3158,8472,4373],{"class":3175},[3158,8474,8080],{"class":4348},[3158,8476,4581],{"class":3175},[3158,8478,4381],{"class":3171},[3158,8480,3176],{"class":3175},[3158,8482,4386],{"class":4363},[3158,8484,4389],{"class":3179},[3158,8486,3527],{"class":3175},[3158,8488,8489],{"class":3160,"line":4136},[3158,8490,6477],{"class":3175},[3158,8492,8493,8495,8497,8499,8501,8504,8506,8508],{"class":3160,"line":4141},[3158,8494,7954],{"class":3179},[3158,8496,3029],{"class":3175},[3158,8498,8135],{"class":3171},[3158,8500,3176],{"class":3175},[3158,8502,8503],{"class":4354},"\"Fetching product with ID {ProductId}\"",[3158,8505,3132],{"class":3175},[3158,8507,4428],{"class":3179},[3158,8509,4431],{"class":3175},[3158,8511,8512],{"class":3160,"line":4147},[3158,8513,8147],{"class":3175},[3158,8515,8516,8518,8520,8522,8524,8526,8528,8530,8532,8534,8536,8538],{"class":3160,"line":4153},[3158,8517,8152],{"class":4363},[3158,8519,4404],{"class":3179},[3158,8521,4407],{"class":3175},[3158,8523,4410],{"class":4363},[3158,8525,4413],{"class":3179},[3158,8527,3029],{"class":3175},[3158,8529,4418],{"class":3179},[3158,8531,3029],{"class":3175},[3158,8533,4423],{"class":3171},[3158,8535,3176],{"class":3175},[3158,8537,4428],{"class":3179},[3158,8539,4431],{"class":3175},[3158,8541,8542],{"class":3160,"line":4159},[3158,8543,8147],{"class":3175},[3158,8545,8546,8549,8551,8553,8555,8557],{"class":3160,"line":4165},[3158,8547,8548],{"class":4440},"        if",[3158,8550,4444],{"class":3175},[3158,8552,4447],{"class":3179},[3158,8554,4450],{"class":4363},[3158,8556,4453],{"class":4363},[3158,8558,3527],{"class":3175},[3158,8560,8561],{"class":3160,"line":4170},[3158,8562,6573],{"class":3175},[3158,8564,8565,8568,8570,8573,8575,8578,8580,8582],{"class":3160,"line":4176},[3158,8566,8567],{"class":3179},"            _logger",[3158,8569,3029],{"class":3175},[3158,8571,8572],{"class":3171},"LogWarning",[3158,8574,3176],{"class":3175},[3158,8576,8577],{"class":4354},"\"Product with ID {ProductId} not found\"",[3158,8579,3132],{"class":3175},[3158,8581,4428],{"class":3179},[3158,8583,4431],{"class":3175},[3158,8585,8586,8589,8591,8593,8595],{"class":3160,"line":4182},[3158,8587,8588],{"class":4440},"            return",[3158,8590,4463],{"class":3171},[3158,8592,3176],{"class":3175},[3158,8594,7281],{"class":4363},[3158,8596,8597],{"class":4348}," ProblemDetails\n",[3158,8599,8600],{"class":3160,"line":4188},[3158,8601,8602],{"class":3175},"            {\n",[3158,8604,8605,8608,8610,8613],{"class":3160,"line":4194},[3158,8606,8607],{"class":3179},"                Title",[3158,8609,4407],{"class":3175},[3158,8611,8612],{"class":4354},"\"Product not found\"",[3158,8614,6786],{"class":3175},[3158,8616,8617,8620,8622,8625,8627,8629,8631,8634],{"class":3160,"line":4199},[3158,8618,8619],{"class":3179},"                Detail",[3158,8621,4407],{"class":3175},[3158,8623,8624],{"class":4354},"$\"Product with ID ",[3158,8626,7352],{"class":7351},[3158,8628,4428],{"class":3179},[3158,8630,7383],{"class":7351},[3158,8632,8633],{"class":4354}," does not exist\"",[3158,8635,6786],{"class":3175},[3158,8637,8638,8641,8643,8645,8647,8649],{"class":3160,"line":4205},[3158,8639,8640],{"class":3179},"                Status",[3158,8642,4407],{"class":3175},[3158,8644,8086],{"class":3179},[3158,8646,3029],{"class":3175},[3158,8648,8456],{"class":3179},[3158,8650,6786],{"class":3175},[3158,8652,8653,8656,8658,8661,8663,8666,8668],{"class":3160,"line":4210},[3158,8654,8655],{"class":3179},"                Instance",[3158,8657,4407],{"class":3175},[3158,8659,8660],{"class":3179},"HttpContext",[3158,8662,3029],{"class":3175},[3158,8664,8665],{"class":3179},"Request",[3158,8667,3029],{"class":3175},[3158,8669,8670],{"class":3179},"Path\n",[3158,8672,8673],{"class":3160,"line":4216},[3158,8674,8675],{"class":3175},"            });\n",[3158,8677,8678],{"class":3160,"line":4222},[3158,8679,8680],{"class":3175},"        }\n",[3158,8682,8683],{"class":3160,"line":4227},[3158,8684,8147],{"class":3175},[3158,8686,8687],{"class":3160,"line":4233},[3158,8688,8689],{"class":3164},"        // Неявна конвертація ProductResponseDto → ActionResult\u003CProductResponseDto>\n",[3158,8691,8692,8694,8697,8699,8701],{"class":3160,"line":4239},[3158,8693,4460],{"class":4440},[3158,8695,8696],{"class":3171}," MapToDto",[3158,8698,3176],{"class":3175},[3158,8700,4447],{"class":3179},[3158,8702,4431],{"class":3175},[3158,8704,8705],{"class":3160,"line":4245},[3158,8706,3879],{"class":3175},[3158,8708,8709],{"class":3160,"line":4251},[3158,8710,3193],{"emptyLinePlaceholder":3192},[3158,8712,8713,8715,8717,8719],{"class":3160,"line":4257},[3158,8714,7973],{"class":3164},[3158,8716,4373],{"class":7976},[3158,8718,7980],{"class":7979},[3158,8720,7983],{"class":7976},[3158,8722,8723],{"class":3160,"line":4263},[3158,8724,8725],{"class":3164},"    /// Створити новий товар\n",[3158,8727,8729,8731,8733,8735],{"class":3160,"line":8728},78,[3158,8730,7973],{"class":3164},[3158,8732,7995],{"class":7976},[3158,8734,7980],{"class":7979},[3158,8736,7983],{"class":7976},[3158,8738,8740,8742,8744,8746,8748,8750,8753,8755,8758,8760,8762],{"class":3160,"line":8739},79,[3158,8741,7973],{"class":3164},[3158,8743,4373],{"class":7976},[3158,8745,8305],{"class":7979},[3158,8747,8308],{"class":8032},[3158,8749,8036],{"class":3164},[3158,8751,8752],{"class":4354},"\"dto\"",[3158,8754,8011],{"class":7976},[3158,8756,8757],{"class":3164},"Дані для створення товару",[3158,8759,7995],{"class":7976},[3158,8761,8305],{"class":7979},[3158,8763,7983],{"class":7976},[3158,8765,8767,8769,8771,8773,8775,8778,8780,8782],{"class":3160,"line":8766},80,[3158,8768,7973],{"class":3164},[3158,8770,4373],{"class":7976},[3158,8772,8008],{"class":7979},[3158,8774,8011],{"class":7976},[3158,8776,8777],{"class":3164},"Створений товар",[3158,8779,7995],{"class":7976},[3158,8781,8008],{"class":7979},[3158,8783,7983],{"class":7976},[3158,8785,8787,8789,8791,8793,8795,8797,8800,8802,8805,8807,8809],{"class":3160,"line":8786},81,[3158,8788,7973],{"class":3164},[3158,8790,4373],{"class":7976},[3158,8792,8029],{"class":7979},[3158,8794,8033],{"class":8032},[3158,8796,8036],{"class":3164},[3158,8798,8799],{"class":4354},"\"201\"",[3158,8801,8011],{"class":7976},[3158,8803,8804],{"class":3164},"Товар успішно створено",[3158,8806,7995],{"class":7976},[3158,8808,8029],{"class":7979},[3158,8810,7983],{"class":7976},[3158,8812,8814,8816,8818,8820,8822,8824,8827,8829,8832,8834,8836],{"class":3160,"line":8813},82,[3158,8815,7973],{"class":3164},[3158,8817,4373],{"class":7976},[3158,8819,8029],{"class":7979},[3158,8821,8033],{"class":8032},[3158,8823,8036],{"class":3164},[3158,8825,8826],{"class":4354},"\"400\"",[3158,8828,8011],{"class":7976},[3158,8830,8831],{"class":3164},"Невалідні дані",[3158,8833,7995],{"class":7976},[3158,8835,8029],{"class":7979},[3158,8837,7983],{"class":7976},[3158,8839,8841,8843,8845,8847,8849,8851,8854,8856,8859,8861,8863],{"class":3160,"line":8840},83,[3158,8842,7973],{"class":3164},[3158,8844,4373],{"class":7976},[3158,8846,8029],{"class":7979},[3158,8848,8033],{"class":8032},[3158,8850,8036],{"class":3164},[3158,8852,8853],{"class":4354},"\"409\"",[3158,8855,8011],{"class":7976},[3158,8857,8858],{"class":3164},"Товар з такою назвою вже існує",[3158,8860,7995],{"class":7976},[3158,8862,8029],{"class":7979},[3158,8864,7983],{"class":7976},[3158,8866,8868,8870,8873],{"class":3160,"line":8867},84,[3158,8869,5335],{"class":3175},[3158,8871,8872],{"class":4348},"HttpPost",[3158,8874,5341],{"class":3175},[3158,8876,8878,8880,8882,8884,8886,8888,8890,8892,8894,8896,8899],{"class":3160,"line":8877},85,[3158,8879,5335],{"class":3175},[3158,8881,8065],{"class":4348},[3158,8883,3176],{"class":3175},[3158,8885,8070],{"class":4363},[3158,8887,3176],{"class":3175},[3158,8889,8080],{"class":4348},[3158,8891,8424],{"class":3175},[3158,8893,8086],{"class":3179},[3158,8895,3029],{"class":3175},[3158,8897,8898],{"class":3179},"Status201Created",[3158,8900,4358],{"class":3175},[3158,8902,8904,8906,8908,8910,8912,8914,8917,8919,8921,8923,8926],{"class":3160,"line":8903},86,[3158,8905,5335],{"class":3175},[3158,8907,8065],{"class":4348},[3158,8909,3176],{"class":3175},[3158,8911,8070],{"class":4363},[3158,8913,3176],{"class":3175},[3158,8915,8916],{"class":4348},"ValidationProblemDetails",[3158,8918,8424],{"class":3175},[3158,8920,8086],{"class":3179},[3158,8922,3029],{"class":3175},[3158,8924,8925],{"class":3179},"Status400BadRequest",[3158,8927,4358],{"class":3175},[3158,8929,8931,8933,8935,8937,8939,8941,8943,8945,8947,8949,8952],{"class":3160,"line":8930},87,[3158,8932,5335],{"class":3175},[3158,8934,8065],{"class":4348},[3158,8936,3176],{"class":3175},[3158,8938,8070],{"class":4363},[3158,8940,3176],{"class":3175},[3158,8942,8447],{"class":4348},[3158,8944,8424],{"class":3175},[3158,8946,8086],{"class":3179},[3158,8948,3029],{"class":3175},[3158,8950,8951],{"class":3179},"Status409Conflict",[3158,8953,4358],{"class":3175},[3158,8955,8957,8959,8961,8963,8965,8967,8969,8971,8973,8976,8978,8981,8984],{"class":3160,"line":8956},88,[3158,8958,5306],{"class":4363},[3158,8960,4367],{"class":4363},[3158,8962,4370],{"class":4348},[3158,8964,4373],{"class":3175},[3158,8966,4292],{"class":4348},[3158,8968,4373],{"class":3175},[3158,8970,8080],{"class":4348},[3158,8972,4581],{"class":3175},[3158,8974,8975],{"class":3171},"Create",[3158,8977,3176],{"class":3175},[3158,8979,8980],{"class":4348},"CreateProductDto",[3158,8982,8983],{"class":3179}," dto",[3158,8985,3527],{"class":3175},[3158,8987,8989],{"class":3160,"line":8988},89,[3158,8990,6477],{"class":3175},[3158,8992,8994,8996,8998,9000,9002,9005,9007,9010,9012,9014],{"class":3160,"line":8993},90,[3158,8995,7954],{"class":3179},[3158,8997,3029],{"class":3175},[3158,8999,8135],{"class":3171},[3158,9001,3176],{"class":3175},[3158,9003,9004],{"class":4354},"\"Creating new product: {ProductName}\"",[3158,9006,3132],{"class":3175},[3158,9008,9009],{"class":3179},"dto",[3158,9011,3029],{"class":3175},[3158,9013,5966],{"class":3179},[3158,9015,4431],{"class":3175},[3158,9017,9019],{"class":3160,"line":9018},91,[3158,9020,8147],{"class":3175},[3158,9022,9024],{"class":3160,"line":9023},92,[3158,9025,9026],{"class":3164},"        // Перевірка на дублікат назви\n",[3158,9028,9030,9032,9035,9037,9039,9041,9043],{"class":3160,"line":9029},93,[3158,9031,8152],{"class":4363},[3158,9033,9034],{"class":3179}," existingProduct",[3158,9036,4407],{"class":3175},[3158,9038,4410],{"class":4363},[3158,9040,4413],{"class":3179},[3158,9042,3029],{"class":3175},[3158,9044,8166],{"class":3179},[3158,9046,9048,9050,9053,9055,9057,9059,9061,9063,9065,9068,9070,9072,9074],{"class":3160,"line":9047},94,[3158,9049,8171],{"class":3175},[3158,9051,9052],{"class":3171},"FirstOrDefaultAsync",[3158,9054,3176],{"class":3175},[3158,9056,2964],{"class":3179},[3158,9058,6503],{"class":3175},[3158,9060,2964],{"class":3179},[3158,9062,3029],{"class":3175},[3158,9064,5966],{"class":3179},[3158,9066,9067],{"class":3175}," == ",[3158,9069,9009],{"class":3179},[3158,9071,3029],{"class":3175},[3158,9073,5966],{"class":3179},[3158,9075,4431],{"class":3175},[3158,9077,9079],{"class":3160,"line":9078},95,[3158,9080,8147],{"class":3175},[3158,9082,9084,9086,9088,9091,9093,9096,9098],{"class":3160,"line":9083},96,[3158,9085,8548],{"class":4440},[3158,9087,4444],{"class":3175},[3158,9089,9090],{"class":3179},"existingProduct",[3158,9092,4450],{"class":4363},[3158,9094,9095],{"class":4363}," not",[3158,9097,4453],{"class":4363},[3158,9099,3527],{"class":3175},[3158,9101,9103],{"class":3160,"line":9102},97,[3158,9104,6573],{"class":3175},[3158,9106,9108,9110,9112,9114,9116,9119,9121,9123,9125,9127],{"class":3160,"line":9107},98,[3158,9109,8567],{"class":3179},[3158,9111,3029],{"class":3175},[3158,9113,8572],{"class":3171},[3158,9115,3176],{"class":3175},[3158,9117,9118],{"class":4354},"\"Product with name '{ProductName}' already exists\"",[3158,9120,3132],{"class":3175},[3158,9122,9009],{"class":3179},[3158,9124,3029],{"class":3175},[3158,9126,5966],{"class":3179},[3158,9128,4431],{"class":3175},[3158,9130,9132,9134,9137,9139,9141],{"class":3160,"line":9131},99,[3158,9133,8588],{"class":4440},[3158,9135,9136],{"class":3171}," Conflict",[3158,9138,3176],{"class":3175},[3158,9140,7281],{"class":4363},[3158,9142,8597],{"class":4348},[3158,9144,9146],{"class":3160,"line":9145},100,[3158,9147,8602],{"class":3175},[3158,9149,9151,9153,9155,9158],{"class":3160,"line":9150},101,[3158,9152,8607],{"class":3179},[3158,9154,4407],{"class":3175},[3158,9156,9157],{"class":4354},"\"Product already exists\"",[3158,9159,6786],{"class":3175},[3158,9161,9163,9165,9167,9170,9172,9174,9176,9178,9180,9183],{"class":3160,"line":9162},102,[3158,9164,8619],{"class":3179},[3158,9166,4407],{"class":3175},[3158,9168,9169],{"class":4354},"$\"A product with the name '",[3158,9171,7352],{"class":7351},[3158,9173,9009],{"class":3179},[3158,9175,3029],{"class":7351},[3158,9177,5966],{"class":3179},[3158,9179,7383],{"class":7351},[3158,9181,9182],{"class":4354},"' already exists\"",[3158,9184,6786],{"class":3175},[3158,9186,9188,9190,9192,9194,9196,9198],{"class":3160,"line":9187},103,[3158,9189,8640],{"class":3179},[3158,9191,4407],{"class":3175},[3158,9193,8086],{"class":3179},[3158,9195,3029],{"class":3175},[3158,9197,8951],{"class":3179},[3158,9199,6786],{"class":3175},[3158,9201,9203,9205,9207,9209,9211,9213,9215],{"class":3160,"line":9202},104,[3158,9204,8655],{"class":3179},[3158,9206,4407],{"class":3175},[3158,9208,8660],{"class":3179},[3158,9210,3029],{"class":3175},[3158,9212,8665],{"class":3179},[3158,9214,3029],{"class":3175},[3158,9216,8670],{"class":3179},[3158,9218,9220],{"class":3160,"line":9219},105,[3158,9221,8675],{"class":3175},[3158,9223,9225],{"class":3160,"line":9224},106,[3158,9226,8680],{"class":3175},[3158,9228,9230],{"class":3160,"line":9229},107,[3158,9231,8147],{"class":3175},[3158,9233,9235,9237,9239,9241,9243],{"class":3160,"line":9234},108,[3158,9236,8152],{"class":4363},[3158,9238,4404],{"class":3179},[3158,9240,4407],{"class":3175},[3158,9242,7281],{"class":4363},[3158,9244,5297],{"class":4348},[3158,9246,9248],{"class":3160,"line":9247},109,[3158,9249,6573],{"class":3175},[3158,9251,9253,9256,9258,9260,9262,9264],{"class":3160,"line":9252},110,[3158,9254,9255],{"class":3179},"            Name",[3158,9257,4407],{"class":3175},[3158,9259,9009],{"class":3179},[3158,9261,3029],{"class":3175},[3158,9263,5966],{"class":3179},[3158,9265,6786],{"class":3175},[3158,9267,9269,9272,9274,9276,9278,9280],{"class":3160,"line":9268},111,[3158,9270,9271],{"class":3179},"            Description",[3158,9273,4407],{"class":3175},[3158,9275,9009],{"class":3179},[3158,9277,3029],{"class":3175},[3158,9279,5407],{"class":3179},[3158,9281,6786],{"class":3175},[3158,9283,9285,9288,9290,9292,9294,9296],{"class":3160,"line":9284},112,[3158,9286,9287],{"class":3179},"            Price",[3158,9289,4407],{"class":3175},[3158,9291,9009],{"class":3179},[3158,9293,3029],{"class":3175},[3158,9295,6043],{"class":3179},[3158,9297,6786],{"class":3175},[3158,9299,9301,9304,9306,9308,9310,9312],{"class":3160,"line":9300},113,[3158,9302,9303],{"class":3179},"            Stock",[3158,9305,4407],{"class":3175},[3158,9307,9009],{"class":3179},[3158,9309,3029],{"class":3175},[3158,9311,6088],{"class":3179},[3158,9313,6786],{"class":3175},[3158,9315,9317,9320,9322,9324,9326,9328],{"class":3160,"line":9316},114,[3158,9318,9319],{"class":3179},"            Category",[3158,9321,4407],{"class":3175},[3158,9323,9009],{"class":3179},[3158,9325,3029],{"class":3175},[3158,9327,5533],{"class":3179},[3158,9329,6786],{"class":3175},[3158,9331,9333,9336,9338,9340,9342],{"class":3160,"line":9332},115,[3158,9334,9335],{"class":3179},"            CreatedAt",[3158,9337,4407],{"class":3175},[3158,9339,5600],{"class":3179},[3158,9341,3029],{"class":3175},[3158,9343,9344],{"class":3179},"UtcNow\n",[3158,9346,9348],{"class":3160,"line":9347},116,[3158,9349,9350],{"class":3175},"        };\n",[3158,9352,9354],{"class":3160,"line":9353},117,[3158,9355,8147],{"class":3175},[3158,9357,9359,9361,9363,9365,9367,9370,9372,9374],{"class":3160,"line":9358},118,[3158,9360,7942],{"class":3179},[3158,9362,3029],{"class":3175},[3158,9364,4418],{"class":3179},[3158,9366,3029],{"class":3175},[3158,9368,9369],{"class":3171},"Add",[3158,9371,3176],{"class":3175},[3158,9373,4447],{"class":3179},[3158,9375,4431],{"class":3175},[3158,9377,9379,9382,9384,9386,9389],{"class":3160,"line":9378},119,[3158,9380,9381],{"class":4363},"        await",[3158,9383,4413],{"class":3179},[3158,9385,3029],{"class":3175},[3158,9387,9388],{"class":3171},"SaveChangesAsync",[3158,9390,4968],{"class":3175},[3158,9392,9394],{"class":3160,"line":9393},120,[3158,9395,8147],{"class":3175},[3158,9397,9399,9401,9403,9405,9407,9409,9411],{"class":3160,"line":9398},121,[3158,9400,8152],{"class":4363},[3158,9402,8230],{"class":3179},[3158,9404,4407],{"class":3175},[3158,9406,8245],{"class":3171},[3158,9408,3176],{"class":3175},[3158,9410,4447],{"class":3179},[3158,9412,4431],{"class":3175},[3158,9414,9416],{"class":3160,"line":9415},122,[3158,9417,8147],{"class":3175},[3158,9419,9421],{"class":3160,"line":9420},123,[3158,9422,9423],{"class":3164},"        // CreatedAtAction автоматично генерує Location header\n",[3158,9425,9427,9429,9432],{"class":3160,"line":9426},124,[3158,9428,4460],{"class":4440},[3158,9430,9431],{"class":3171}," CreatedAtAction",[3158,9433,6732],{"class":3175},[3158,9435,9437,9440,9442,9444],{"class":3160,"line":9436},125,[3158,9438,9439],{"class":4363},"            nameof",[3158,9441,3176],{"class":3175},[3158,9443,4381],{"class":3179},[3158,9445,9446],{"class":3175},"),\n",[3158,9448,9450,9453,9455,9457,9459,9461,9463,9465],{"class":3160,"line":9449},126,[3158,9451,9452],{"class":4363},"            new",[3158,9454,5315],{"class":3175},[3158,9456,4428],{"class":3179},[3158,9458,4407],{"class":3175},[3158,9460,4447],{"class":3179},[3158,9462,3029],{"class":3175},[3158,9464,6597],{"class":3179},[3158,9466,9467],{"class":3175}," },\n",[3158,9469,9471],{"class":3160,"line":9470},127,[3158,9472,9473],{"class":3179},"            response\n",[3158,9475,9477],{"class":3160,"line":9476},128,[3158,9478,9479],{"class":3175},"        );\n",[3158,9481,9483],{"class":3160,"line":9482},129,[3158,9484,3879],{"class":3175},[3158,9486,9488],{"class":3160,"line":9487},130,[3158,9489,3193],{"emptyLinePlaceholder":3192},[3158,9491,9493,9495,9497,9499],{"class":3160,"line":9492},131,[3158,9494,7973],{"class":3164},[3158,9496,4373],{"class":7976},[3158,9498,7980],{"class":7979},[3158,9500,7983],{"class":7976},[3158,9502,9504],{"class":3160,"line":9503},132,[3158,9505,9506],{"class":3164},"    /// Оновити існуючий товар\n",[3158,9508,9510,9512,9514,9516],{"class":3160,"line":9509},133,[3158,9511,7973],{"class":3164},[3158,9513,7995],{"class":7976},[3158,9515,7980],{"class":7979},[3158,9517,7983],{"class":7976},[3158,9519,9521,9523,9525,9527,9529,9531,9533,9535,9537,9539,9541],{"class":3160,"line":9520},134,[3158,9522,7973],{"class":3164},[3158,9524,4373],{"class":7976},[3158,9526,8305],{"class":7979},[3158,9528,8308],{"class":8032},[3158,9530,8036],{"class":3164},[3158,9532,8313],{"class":4354},[3158,9534,8011],{"class":7976},[3158,9536,8318],{"class":3164},[3158,9538,7995],{"class":7976},[3158,9540,8305],{"class":7979},[3158,9542,7983],{"class":7976},[3158,9544,9546,9548,9550,9552,9554,9556,9558,9560,9563,9565,9567],{"class":3160,"line":9545},135,[3158,9547,7973],{"class":3164},[3158,9549,4373],{"class":7976},[3158,9551,8305],{"class":7979},[3158,9553,8308],{"class":8032},[3158,9555,8036],{"class":3164},[3158,9557,8752],{"class":4354},[3158,9559,8011],{"class":7976},[3158,9561,9562],{"class":3164},"Дані для оновлення",[3158,9564,7995],{"class":7976},[3158,9566,8305],{"class":7979},[3158,9568,7983],{"class":7976},[3158,9570,9572,9574,9576,9578,9580,9583,9585,9587],{"class":3160,"line":9571},136,[3158,9573,7973],{"class":3164},[3158,9575,4373],{"class":7976},[3158,9577,8008],{"class":7979},[3158,9579,8011],{"class":7976},[3158,9581,9582],{"class":3164},"Оновлений товар",[3158,9584,7995],{"class":7976},[3158,9586,8008],{"class":7979},[3158,9588,7983],{"class":7976},[3158,9590,9592,9594,9596,9598,9600,9602,9604,9606,9609,9611,9613],{"class":3160,"line":9591},137,[3158,9593,7973],{"class":3164},[3158,9595,4373],{"class":7976},[3158,9597,8029],{"class":7979},[3158,9599,8033],{"class":8032},[3158,9601,8036],{"class":3164},[3158,9603,8039],{"class":4354},[3158,9605,8011],{"class":7976},[3158,9607,9608],{"class":3164},"Товар успішно оновлено",[3158,9610,7995],{"class":7976},[3158,9612,8029],{"class":7979},[3158,9614,7983],{"class":7976},[3158,9616,9618,9620,9622,9624,9626,9628,9630,9632,9634,9636,9638],{"class":3160,"line":9617},138,[3158,9619,7973],{"class":3164},[3158,9621,4373],{"class":7976},[3158,9623,8029],{"class":7979},[3158,9625,8033],{"class":8032},[3158,9627,8036],{"class":3164},[3158,9629,8383],{"class":4354},[3158,9631,8011],{"class":7976},[3158,9633,8388],{"class":3164},[3158,9635,7995],{"class":7976},[3158,9637,8029],{"class":7979},[3158,9639,7983],{"class":7976},[3158,9641,9643,9645,9648,9650,9652],{"class":3160,"line":9642},139,[3158,9644,5335],{"class":3175},[3158,9646,9647],{"class":4348},"HttpPut",[3158,9649,3176],{"class":3175},[3158,9651,8405],{"class":4354},[3158,9653,4358],{"class":3175},[3158,9655,9657,9659,9661,9663,9665,9667,9669,9671,9673,9675,9677],{"class":3160,"line":9656},140,[3158,9658,5335],{"class":3175},[3158,9660,8065],{"class":4348},[3158,9662,3176],{"class":3175},[3158,9664,8070],{"class":4363},[3158,9666,3176],{"class":3175},[3158,9668,8080],{"class":4348},[3158,9670,8424],{"class":3175},[3158,9672,8086],{"class":3179},[3158,9674,3029],{"class":3175},[3158,9676,8091],{"class":3179},[3158,9678,4358],{"class":3175},[3158,9680,9682,9684,9686,9688,9690,9692,9694,9696,9698,9700,9702],{"class":3160,"line":9681},141,[3158,9683,5335],{"class":3175},[3158,9685,8065],{"class":4348},[3158,9687,3176],{"class":3175},[3158,9689,8070],{"class":4363},[3158,9691,3176],{"class":3175},[3158,9693,8447],{"class":4348},[3158,9695,8424],{"class":3175},[3158,9697,8086],{"class":3179},[3158,9699,3029],{"class":3175},[3158,9701,8456],{"class":3179},[3158,9703,4358],{"class":3175},[3158,9705,9707,9709,9711,9713,9715,9717,9719,9721,9723,9726,9728,9730,9732,9734,9737,9739],{"class":3160,"line":9706},142,[3158,9708,5306],{"class":4363},[3158,9710,4367],{"class":4363},[3158,9712,4370],{"class":4348},[3158,9714,4373],{"class":3175},[3158,9716,4292],{"class":4348},[3158,9718,4373],{"class":3175},[3158,9720,8080],{"class":4348},[3158,9722,4581],{"class":3175},[3158,9724,9725],{"class":3171},"Update",[3158,9727,3176],{"class":3175},[3158,9729,4386],{"class":4363},[3158,9731,4389],{"class":3179},[3158,9733,3132],{"class":3175},[3158,9735,9736],{"class":4348},"UpdateProductDto",[3158,9738,8983],{"class":3179},[3158,9740,3527],{"class":3175},[3158,9742,9744],{"class":3160,"line":9743},143,[3158,9745,6477],{"class":3175},[3158,9747,9749,9751,9753,9755,9757,9760,9762,9764],{"class":3160,"line":9748},144,[3158,9750,7954],{"class":3179},[3158,9752,3029],{"class":3175},[3158,9754,8135],{"class":3171},[3158,9756,3176],{"class":3175},[3158,9758,9759],{"class":4354},"\"Updating product with ID {ProductId}\"",[3158,9761,3132],{"class":3175},[3158,9763,4428],{"class":3179},[3158,9765,4431],{"class":3175},[3158,9767,9769],{"class":3160,"line":9768},145,[3158,9770,8147],{"class":3175},[3158,9772,9774,9776,9778,9780,9782,9784,9786,9788,9790,9792,9794,9796],{"class":3160,"line":9773},146,[3158,9775,8152],{"class":4363},[3158,9777,4404],{"class":3179},[3158,9779,4407],{"class":3175},[3158,9781,4410],{"class":4363},[3158,9783,4413],{"class":3179},[3158,9785,3029],{"class":3175},[3158,9787,4418],{"class":3179},[3158,9789,3029],{"class":3175},[3158,9791,4423],{"class":3171},[3158,9793,3176],{"class":3175},[3158,9795,4428],{"class":3179},[3158,9797,4431],{"class":3175},[3158,9799,9801],{"class":3160,"line":9800},147,[3158,9802,8147],{"class":3175},[3158,9804,9806,9808,9810,9812,9814,9816],{"class":3160,"line":9805},148,[3158,9807,8548],{"class":4440},[3158,9809,4444],{"class":3175},[3158,9811,4447],{"class":3179},[3158,9813,4450],{"class":4363},[3158,9815,4453],{"class":4363},[3158,9817,3527],{"class":3175},[3158,9819,9821],{"class":3160,"line":9820},149,[3158,9822,6573],{"class":3175},[3158,9824,9826,9828,9830,9832,9834],{"class":3160,"line":9825},150,[3158,9827,8588],{"class":4440},[3158,9829,4463],{"class":3171},[3158,9831,3176],{"class":3175},[3158,9833,7281],{"class":4363},[3158,9835,8597],{"class":4348},[3158,9837,9839],{"class":3160,"line":9838},151,[3158,9840,8602],{"class":3175},[3158,9842,9844,9846,9848,9850],{"class":3160,"line":9843},152,[3158,9845,8607],{"class":3179},[3158,9847,4407],{"class":3175},[3158,9849,8612],{"class":4354},[3158,9851,6786],{"class":3175},[3158,9853,9855,9857,9859,9861,9863,9865,9867,9869],{"class":3160,"line":9854},153,[3158,9856,8619],{"class":3179},[3158,9858,4407],{"class":3175},[3158,9860,8624],{"class":4354},[3158,9862,7352],{"class":7351},[3158,9864,4428],{"class":3179},[3158,9866,7383],{"class":7351},[3158,9868,8633],{"class":4354},[3158,9870,6786],{"class":3175},[3158,9872,9874,9876,9878,9880,9882],{"class":3160,"line":9873},154,[3158,9875,8640],{"class":3179},[3158,9877,4407],{"class":3175},[3158,9879,8086],{"class":3179},[3158,9881,3029],{"class":3175},[3158,9883,9884],{"class":3179},"Status404NotFound\n",[3158,9886,9888],{"class":3160,"line":9887},155,[3158,9889,8675],{"class":3175},[3158,9891,9893],{"class":3160,"line":9892},156,[3158,9894,8680],{"class":3175},[3158,9896,9898],{"class":3160,"line":9897},157,[3158,9899,8147],{"class":3175},[3158,9901,9903],{"class":3160,"line":9902},158,[3158,9904,9905],{"class":3164},"        // Оновлюємо тільки передані поля\n",[3158,9907,9909,9911,9913,9915,9917,9919,9921,9923,9925,9927,9929,9931,9933,9935,9937,9939,9941],{"class":3160,"line":9908},159,[3158,9910,8548],{"class":4440},[3158,9912,4444],{"class":3175},[3158,9914,9009],{"class":3179},[3158,9916,3029],{"class":3175},[3158,9918,5966],{"class":3179},[3158,9920,4450],{"class":4363},[3158,9922,9095],{"class":4363},[3158,9924,4453],{"class":4363},[3158,9926,4960],{"class":3175},[3158,9928,4447],{"class":3179},[3158,9930,3029],{"class":3175},[3158,9932,5966],{"class":3179},[3158,9934,4407],{"class":3175},[3158,9936,9009],{"class":3179},[3158,9938,3029],{"class":3175},[3158,9940,5966],{"class":3179},[3158,9942,5264],{"class":3175},[3158,9944,9946,9948,9950,9952,9954,9956,9958,9960,9962,9964,9966,9968,9970,9972,9974,9976,9978],{"class":3160,"line":9945},160,[3158,9947,8548],{"class":4440},[3158,9949,4444],{"class":3175},[3158,9951,9009],{"class":3179},[3158,9953,3029],{"class":3175},[3158,9955,5407],{"class":3179},[3158,9957,4450],{"class":4363},[3158,9959,9095],{"class":4363},[3158,9961,4453],{"class":4363},[3158,9963,4960],{"class":3175},[3158,9965,4447],{"class":3179},[3158,9967,3029],{"class":3175},[3158,9969,5407],{"class":3179},[3158,9971,4407],{"class":3175},[3158,9973,9009],{"class":3179},[3158,9975,3029],{"class":3175},[3158,9977,5407],{"class":3179},[3158,9979,5264],{"class":3175},[3158,9981,9983,9985,9987,9989,9991,9993,9995,9998,10000,10002,10004,10006,10008,10010,10012,10014,10016,10019],{"class":3160,"line":9982},161,[3158,9984,8548],{"class":4440},[3158,9986,4444],{"class":3175},[3158,9988,9009],{"class":3179},[3158,9990,3029],{"class":3175},[3158,9992,6043],{"class":3179},[3158,9994,3029],{"class":3175},[3158,9996,9997],{"class":3179},"HasValue",[3158,9999,4960],{"class":3175},[3158,10001,4447],{"class":3179},[3158,10003,3029],{"class":3175},[3158,10005,6043],{"class":3179},[3158,10007,4407],{"class":3175},[3158,10009,9009],{"class":3179},[3158,10011,3029],{"class":3175},[3158,10013,6043],{"class":3179},[3158,10015,3029],{"class":3175},[3158,10017,10018],{"class":3179},"Value",[3158,10020,5264],{"class":3175},[3158,10022,10024,10026,10028,10030,10032,10034,10036,10038,10040,10042,10044,10046,10048,10050,10052,10054,10056,10058],{"class":3160,"line":10023},162,[3158,10025,8548],{"class":4440},[3158,10027,4444],{"class":3175},[3158,10029,9009],{"class":3179},[3158,10031,3029],{"class":3175},[3158,10033,6088],{"class":3179},[3158,10035,3029],{"class":3175},[3158,10037,9997],{"class":3179},[3158,10039,4960],{"class":3175},[3158,10041,4447],{"class":3179},[3158,10043,3029],{"class":3175},[3158,10045,6088],{"class":3179},[3158,10047,4407],{"class":3175},[3158,10049,9009],{"class":3179},[3158,10051,3029],{"class":3175},[3158,10053,6088],{"class":3179},[3158,10055,3029],{"class":3175},[3158,10057,10018],{"class":3179},[3158,10059,5264],{"class":3175},[3158,10061,10063,10065,10067,10069,10071,10073,10075,10077,10079,10081,10083,10085,10087,10089,10091,10093,10095],{"class":3160,"line":10062},163,[3158,10064,8548],{"class":4440},[3158,10066,4444],{"class":3175},[3158,10068,9009],{"class":3179},[3158,10070,3029],{"class":3175},[3158,10072,5533],{"class":3179},[3158,10074,4450],{"class":4363},[3158,10076,9095],{"class":4363},[3158,10078,4453],{"class":4363},[3158,10080,4960],{"class":3175},[3158,10082,4447],{"class":3179},[3158,10084,3029],{"class":3175},[3158,10086,5533],{"class":3179},[3158,10088,4407],{"class":3175},[3158,10090,9009],{"class":3179},[3158,10092,3029],{"class":3175},[3158,10094,5533],{"class":3179},[3158,10096,5264],{"class":3175},[3158,10098,10100,10102,10104,10106,10108,10110,10112,10114,10116,10118,10120,10122,10124,10126,10128,10130,10132,10134],{"class":3160,"line":10099},164,[3158,10101,8548],{"class":4440},[3158,10103,4444],{"class":3175},[3158,10105,9009],{"class":3179},[3158,10107,3029],{"class":3175},[3158,10109,6149],{"class":3179},[3158,10111,3029],{"class":3175},[3158,10113,9997],{"class":3179},[3158,10115,4960],{"class":3175},[3158,10117,4447],{"class":3179},[3158,10119,3029],{"class":3175},[3158,10121,6149],{"class":3179},[3158,10123,4407],{"class":3175},[3158,10125,9009],{"class":3179},[3158,10127,3029],{"class":3175},[3158,10129,6149],{"class":3179},[3158,10131,3029],{"class":3175},[3158,10133,10018],{"class":3179},[3158,10135,5264],{"class":3175},[3158,10137,10139],{"class":3160,"line":10138},165,[3158,10140,8147],{"class":3175},[3158,10142,10144,10147,10149,10151,10153,10155,10157,10159],{"class":3160,"line":10143},166,[3158,10145,10146],{"class":3179},"        product",[3158,10148,3029],{"class":3175},[3158,10150,5622],{"class":3179},[3158,10152,4407],{"class":3175},[3158,10154,5600],{"class":3179},[3158,10156,3029],{"class":3175},[3158,10158,5605],{"class":3179},[3158,10160,5264],{"class":3175},[3158,10162,10164],{"class":3160,"line":10163},167,[3158,10165,8147],{"class":3175},[3158,10167,10169,10171,10173,10175,10177],{"class":3160,"line":10168},168,[3158,10170,9381],{"class":4363},[3158,10172,4413],{"class":3179},[3158,10174,3029],{"class":3175},[3158,10176,9388],{"class":3171},[3158,10178,4968],{"class":3175},[3158,10180,10182],{"class":3160,"line":10181},169,[3158,10183,8147],{"class":3175},[3158,10185,10187,10189,10191,10193,10195],{"class":3160,"line":10186},170,[3158,10188,4460],{"class":4440},[3158,10190,8696],{"class":3171},[3158,10192,3176],{"class":3175},[3158,10194,4447],{"class":3179},[3158,10196,4431],{"class":3175},[3158,10198,10200],{"class":3160,"line":10199},171,[3158,10201,3879],{"class":3175},[3158,10203,10205],{"class":3160,"line":10204},172,[3158,10206,3193],{"emptyLinePlaceholder":3192},[3158,10208,10210,10212,10214,10216],{"class":3160,"line":10209},173,[3158,10211,7973],{"class":3164},[3158,10213,4373],{"class":7976},[3158,10215,7980],{"class":7979},[3158,10217,7983],{"class":7976},[3158,10219,10221],{"class":3160,"line":10220},174,[3158,10222,10223],{"class":3164},"    /// Видалити товар (soft delete - деактивація)\n",[3158,10225,10227,10229,10231,10233],{"class":3160,"line":10226},175,[3158,10228,7973],{"class":3164},[3158,10230,7995],{"class":7976},[3158,10232,7980],{"class":7979},[3158,10234,7983],{"class":7976},[3158,10236,10238,10240,10242,10244,10246,10248,10250,10252,10254,10256,10258],{"class":3160,"line":10237},176,[3158,10239,7973],{"class":3164},[3158,10241,4373],{"class":7976},[3158,10243,8305],{"class":7979},[3158,10245,8308],{"class":8032},[3158,10247,8036],{"class":3164},[3158,10249,8313],{"class":4354},[3158,10251,8011],{"class":7976},[3158,10253,8318],{"class":3164},[3158,10255,7995],{"class":7976},[3158,10257,8305],{"class":7979},[3158,10259,7983],{"class":7976},[3158,10261,10263,10265,10267,10269,10271,10273,10275,10277],{"class":3160,"line":10262},177,[3158,10264,7973],{"class":3164},[3158,10266,4373],{"class":7976},[3158,10268,8008],{"class":7979},[3158,10270,8011],{"class":7976},[3158,10272,2999],{"class":3164},[3158,10274,7995],{"class":7976},[3158,10276,8008],{"class":7979},[3158,10278,7983],{"class":7976},[3158,10280,10282,10284,10286,10288,10290,10292,10295,10297,10300,10302,10304],{"class":3160,"line":10281},178,[3158,10283,7973],{"class":3164},[3158,10285,4373],{"class":7976},[3158,10287,8029],{"class":7979},[3158,10289,8033],{"class":8032},[3158,10291,8036],{"class":3164},[3158,10293,10294],{"class":4354},"\"204\"",[3158,10296,8011],{"class":7976},[3158,10298,10299],{"class":3164},"Товар успішно деактивовано",[3158,10301,7995],{"class":7976},[3158,10303,8029],{"class":7979},[3158,10305,7983],{"class":7976},[3158,10307,10309,10311,10313,10315,10317,10319,10321,10323,10325,10327,10329],{"class":3160,"line":10308},179,[3158,10310,7973],{"class":3164},[3158,10312,4373],{"class":7976},[3158,10314,8029],{"class":7979},[3158,10316,8033],{"class":8032},[3158,10318,8036],{"class":3164},[3158,10320,8383],{"class":4354},[3158,10322,8011],{"class":7976},[3158,10324,8388],{"class":3164},[3158,10326,7995],{"class":7976},[3158,10328,8029],{"class":7979},[3158,10330,7983],{"class":7976},[3158,10332,10334,10336,10339,10341,10343],{"class":3160,"line":10333},180,[3158,10335,5335],{"class":3175},[3158,10337,10338],{"class":4348},"HttpDelete",[3158,10340,3176],{"class":3175},[3158,10342,8405],{"class":4354},[3158,10344,4358],{"class":3175},[3158,10346,10348,10350,10352,10354,10356,10358,10361],{"class":3160,"line":10347},181,[3158,10349,5335],{"class":3175},[3158,10351,8065],{"class":4348},[3158,10353,3176],{"class":3175},[3158,10355,8086],{"class":3179},[3158,10357,3029],{"class":3175},[3158,10359,10360],{"class":3179},"Status204NoContent",[3158,10362,4358],{"class":3175},[3158,10364,10366,10368,10370,10372,10374,10376,10378,10380,10382,10384,10386],{"class":3160,"line":10365},182,[3158,10367,5335],{"class":3175},[3158,10369,8065],{"class":4348},[3158,10371,3176],{"class":3175},[3158,10373,8070],{"class":4363},[3158,10375,3176],{"class":3175},[3158,10377,8447],{"class":4348},[3158,10379,8424],{"class":3175},[3158,10381,8086],{"class":3179},[3158,10383,3029],{"class":3175},[3158,10385,8456],{"class":3179},[3158,10387,4358],{"class":3175},[3158,10389,10391,10393,10395,10397,10399,10401,10403,10406,10408,10410,10412],{"class":3160,"line":10390},183,[3158,10392,5306],{"class":4363},[3158,10394,4367],{"class":4363},[3158,10396,4370],{"class":4348},[3158,10398,4373],{"class":3175},[3158,10400,3094],{"class":4348},[3158,10402,4378],{"class":3175},[3158,10404,10405],{"class":3171},"Delete",[3158,10407,3176],{"class":3175},[3158,10409,4386],{"class":4363},[3158,10411,4389],{"class":3179},[3158,10413,3527],{"class":3175},[3158,10415,10417],{"class":3160,"line":10416},184,[3158,10418,6477],{"class":3175},[3158,10420,10422,10424,10426,10428,10430,10433,10435,10437],{"class":3160,"line":10421},185,[3158,10423,7954],{"class":3179},[3158,10425,3029],{"class":3175},[3158,10427,8135],{"class":3171},[3158,10429,3176],{"class":3175},[3158,10431,10432],{"class":4354},"\"Deactivating product with ID {ProductId}\"",[3158,10434,3132],{"class":3175},[3158,10436,4428],{"class":3179},[3158,10438,4431],{"class":3175},[3158,10440,10442],{"class":3160,"line":10441},186,[3158,10443,8147],{"class":3175},[3158,10445,10447,10449,10451,10453,10455,10457,10459,10461,10463,10465,10467,10469],{"class":3160,"line":10446},187,[3158,10448,8152],{"class":4363},[3158,10450,4404],{"class":3179},[3158,10452,4407],{"class":3175},[3158,10454,4410],{"class":4363},[3158,10456,4413],{"class":3179},[3158,10458,3029],{"class":3175},[3158,10460,4418],{"class":3179},[3158,10462,3029],{"class":3175},[3158,10464,4423],{"class":3171},[3158,10466,3176],{"class":3175},[3158,10468,4428],{"class":3179},[3158,10470,4431],{"class":3175},[3158,10472,10474],{"class":3160,"line":10473},188,[3158,10475,8147],{"class":3175},[3158,10477,10479,10481,10483,10485,10487,10489],{"class":3160,"line":10478},189,[3158,10480,8548],{"class":4440},[3158,10482,4444],{"class":3175},[3158,10484,4447],{"class":3179},[3158,10486,4450],{"class":4363},[3158,10488,4453],{"class":4363},[3158,10490,3527],{"class":3175},[3158,10492,10494],{"class":3160,"line":10493},190,[3158,10495,6573],{"class":3175},[3158,10497,10499,10501,10503,10505,10507],{"class":3160,"line":10498},191,[3158,10500,8588],{"class":4440},[3158,10502,4463],{"class":3171},[3158,10504,3176],{"class":3175},[3158,10506,7281],{"class":4363},[3158,10508,8597],{"class":4348},[3158,10510,10512],{"class":3160,"line":10511},192,[3158,10513,8602],{"class":3175},[3158,10515,10517,10519,10521,10523],{"class":3160,"line":10516},193,[3158,10518,8607],{"class":3179},[3158,10520,4407],{"class":3175},[3158,10522,8612],{"class":4354},[3158,10524,6786],{"class":3175},[3158,10526,10528,10530,10532,10534,10536,10538,10540,10542],{"class":3160,"line":10527},194,[3158,10529,8619],{"class":3179},[3158,10531,4407],{"class":3175},[3158,10533,8624],{"class":4354},[3158,10535,7352],{"class":7351},[3158,10537,4428],{"class":3179},[3158,10539,7383],{"class":7351},[3158,10541,8633],{"class":4354},[3158,10543,6786],{"class":3175},[3158,10545,10547,10549,10551,10553,10555],{"class":3160,"line":10546},195,[3158,10548,8640],{"class":3179},[3158,10550,4407],{"class":3175},[3158,10552,8086],{"class":3179},[3158,10554,3029],{"class":3175},[3158,10556,9884],{"class":3179},[3158,10558,10560],{"class":3160,"line":10559},196,[3158,10561,8675],{"class":3175},[3158,10563,10565],{"class":3160,"line":10564},197,[3158,10566,8680],{"class":3175},[3158,10568,10570],{"class":3160,"line":10569},198,[3158,10571,8147],{"class":3175},[3158,10573,10575],{"class":3160,"line":10574},199,[3158,10576,10577],{"class":3164},"        // Soft delete - просто деактивуємо\n",[3158,10579,10581,10583,10585,10587,10589,10591],{"class":3160,"line":10580},200,[3158,10582,10146],{"class":3179},[3158,10584,3029],{"class":3175},[3158,10586,6149],{"class":3179},[3158,10588,4407],{"class":3175},[3158,10590,7043],{"class":4363},[3158,10592,5264],{"class":3175},[3158,10594,10596,10598,10600,10602,10604,10606,10608,10610],{"class":3160,"line":10595},201,[3158,10597,10146],{"class":3179},[3158,10599,3029],{"class":3175},[3158,10601,5622],{"class":3179},[3158,10603,4407],{"class":3175},[3158,10605,5600],{"class":3179},[3158,10607,3029],{"class":3175},[3158,10609,5605],{"class":3179},[3158,10611,5264],{"class":3175},[3158,10613,10615],{"class":3160,"line":10614},202,[3158,10616,8147],{"class":3175},[3158,10618,10620,10622,10624,10626,10628],{"class":3160,"line":10619},203,[3158,10621,9381],{"class":4363},[3158,10623,4413],{"class":3179},[3158,10625,3029],{"class":3175},[3158,10627,9388],{"class":3171},[3158,10629,4968],{"class":3175},[3158,10631,10633],{"class":3160,"line":10632},204,[3158,10634,8147],{"class":3175},[3158,10636,10638],{"class":3160,"line":10637},205,[3158,10639,10640],{"class":3164},"        // NoContent() - успішно, але без даних у відповіді\n",[3158,10642,10644,10646,10649],{"class":3160,"line":10643},206,[3158,10645,4460],{"class":4440},[3158,10647,10648],{"class":3171}," NoContent",[3158,10650,4968],{"class":3175},[3158,10652,10654],{"class":3160,"line":10653},207,[3158,10655,3879],{"class":3175},[3158,10657,10659],{"class":3160,"line":10658},208,[3158,10660,3193],{"emptyLinePlaceholder":3192},[3158,10662,10664,10666,10668,10670],{"class":3160,"line":10663},209,[3158,10665,7973],{"class":3164},[3158,10667,4373],{"class":7976},[3158,10669,7980],{"class":7979},[3158,10671,7983],{"class":7976},[3158,10673,10675],{"class":3160,"line":10674},210,[3158,10676,10677],{"class":3164},"    /// Видалити товар назавжди (hard delete)\n",[3158,10679,10681,10683,10685,10687],{"class":3160,"line":10680},211,[3158,10682,7973],{"class":3164},[3158,10684,7995],{"class":7976},[3158,10686,7980],{"class":7979},[3158,10688,7983],{"class":7976},[3158,10690,10692,10694,10696,10698,10700,10702,10704,10706,10708,10710,10712],{"class":3160,"line":10691},212,[3158,10693,7973],{"class":3164},[3158,10695,4373],{"class":7976},[3158,10697,8305],{"class":7979},[3158,10699,8308],{"class":8032},[3158,10701,8036],{"class":3164},[3158,10703,8313],{"class":4354},[3158,10705,8011],{"class":7976},[3158,10707,8318],{"class":3164},[3158,10709,7995],{"class":7976},[3158,10711,8305],{"class":7979},[3158,10713,7983],{"class":7976},[3158,10715,10717,10719,10721,10723,10725,10727,10729,10731],{"class":3160,"line":10716},213,[3158,10718,7973],{"class":3164},[3158,10720,4373],{"class":7976},[3158,10722,8008],{"class":7979},[3158,10724,8011],{"class":7976},[3158,10726,2999],{"class":3164},[3158,10728,7995],{"class":7976},[3158,10730,8008],{"class":7979},[3158,10732,7983],{"class":7976},[3158,10734,10736,10738,10740,10742,10744,10746,10748,10750,10753,10755,10757],{"class":3160,"line":10735},214,[3158,10737,7973],{"class":3164},[3158,10739,4373],{"class":7976},[3158,10741,8029],{"class":7979},[3158,10743,8033],{"class":8032},[3158,10745,8036],{"class":3164},[3158,10747,10294],{"class":4354},[3158,10749,8011],{"class":7976},[3158,10751,10752],{"class":3164},"Товар успішно видалено",[3158,10754,7995],{"class":7976},[3158,10756,8029],{"class":7979},[3158,10758,7983],{"class":7976},[3158,10760,10762,10764,10766,10768,10770,10772,10774,10776,10778,10780,10782],{"class":3160,"line":10761},215,[3158,10763,7973],{"class":3164},[3158,10765,4373],{"class":7976},[3158,10767,8029],{"class":7979},[3158,10769,8033],{"class":8032},[3158,10771,8036],{"class":3164},[3158,10773,8383],{"class":4354},[3158,10775,8011],{"class":7976},[3158,10777,8388],{"class":3164},[3158,10779,7995],{"class":7976},[3158,10781,8029],{"class":7979},[3158,10783,7983],{"class":7976},[3158,10785,10787,10789,10791,10793,10795,10797,10799,10801,10804,10806,10808],{"class":3160,"line":10786},216,[3158,10788,7973],{"class":3164},[3158,10790,4373],{"class":7976},[3158,10792,8029],{"class":7979},[3158,10794,8033],{"class":8032},[3158,10796,8036],{"class":3164},[3158,10798,8853],{"class":4354},[3158,10800,8011],{"class":7976},[3158,10802,10803],{"class":3164},"Неможливо видалити товар з ненульовим залишком",[3158,10805,7995],{"class":7976},[3158,10807,8029],{"class":7979},[3158,10809,7983],{"class":7976},[3158,10811,10813,10815,10817,10819,10822],{"class":3160,"line":10812},217,[3158,10814,5335],{"class":3175},[3158,10816,10338],{"class":4348},[3158,10818,3176],{"class":3175},[3158,10820,10821],{"class":4354},"\"{id:int}/permanent\"",[3158,10823,4358],{"class":3175},[3158,10825,10827,10829,10831,10833,10835,10837,10839],{"class":3160,"line":10826},218,[3158,10828,5335],{"class":3175},[3158,10830,8065],{"class":4348},[3158,10832,3176],{"class":3175},[3158,10834,8086],{"class":3179},[3158,10836,3029],{"class":3175},[3158,10838,10360],{"class":3179},[3158,10840,4358],{"class":3175},[3158,10842,10844,10846,10848,10850,10852,10854,10856,10858,10860,10862,10864],{"class":3160,"line":10843},219,[3158,10845,5335],{"class":3175},[3158,10847,8065],{"class":4348},[3158,10849,3176],{"class":3175},[3158,10851,8070],{"class":4363},[3158,10853,3176],{"class":3175},[3158,10855,8447],{"class":4348},[3158,10857,8424],{"class":3175},[3158,10859,8086],{"class":3179},[3158,10861,3029],{"class":3175},[3158,10863,8456],{"class":3179},[3158,10865,4358],{"class":3175},[3158,10867,10869,10871,10873,10875,10877,10879,10881,10883,10885,10887,10889],{"class":3160,"line":10868},220,[3158,10870,5335],{"class":3175},[3158,10872,8065],{"class":4348},[3158,10874,3176],{"class":3175},[3158,10876,8070],{"class":4363},[3158,10878,3176],{"class":3175},[3158,10880,8447],{"class":4348},[3158,10882,8424],{"class":3175},[3158,10884,8086],{"class":3179},[3158,10886,3029],{"class":3175},[3158,10888,8951],{"class":3179},[3158,10890,4358],{"class":3175},[3158,10892,10894,10896,10898,10900,10902,10904,10906,10909,10911,10913,10915],{"class":3160,"line":10893},221,[3158,10895,5306],{"class":4363},[3158,10897,4367],{"class":4363},[3158,10899,4370],{"class":4348},[3158,10901,4373],{"class":3175},[3158,10903,3094],{"class":4348},[3158,10905,4378],{"class":3175},[3158,10907,10908],{"class":3171},"DeletePermanent",[3158,10910,3176],{"class":3175},[3158,10912,4386],{"class":4363},[3158,10914,4389],{"class":3179},[3158,10916,3527],{"class":3175},[3158,10918,10920],{"class":3160,"line":10919},222,[3158,10921,6477],{"class":3175},[3158,10923,10925,10927,10929,10931,10933,10936,10938,10940],{"class":3160,"line":10924},223,[3158,10926,7954],{"class":3179},[3158,10928,3029],{"class":3175},[3158,10930,8135],{"class":3171},[3158,10932,3176],{"class":3175},[3158,10934,10935],{"class":4354},"\"Permanently deleting product with ID {ProductId}\"",[3158,10937,3132],{"class":3175},[3158,10939,4428],{"class":3179},[3158,10941,4431],{"class":3175},[3158,10943,10945],{"class":3160,"line":10944},224,[3158,10946,8147],{"class":3175},[3158,10948,10950,10952,10954,10956,10958,10960,10962,10964,10966,10968,10970,10972],{"class":3160,"line":10949},225,[3158,10951,8152],{"class":4363},[3158,10953,4404],{"class":3179},[3158,10955,4407],{"class":3175},[3158,10957,4410],{"class":4363},[3158,10959,4413],{"class":3179},[3158,10961,3029],{"class":3175},[3158,10963,4418],{"class":3179},[3158,10965,3029],{"class":3175},[3158,10967,4423],{"class":3171},[3158,10969,3176],{"class":3175},[3158,10971,4428],{"class":3179},[3158,10973,4431],{"class":3175},[3158,10975,10977],{"class":3160,"line":10976},226,[3158,10978,8147],{"class":3175},[3158,10980,10982,10984,10986,10988,10990,10992],{"class":3160,"line":10981},227,[3158,10983,8548],{"class":4440},[3158,10985,4444],{"class":3175},[3158,10987,4447],{"class":3179},[3158,10989,4450],{"class":4363},[3158,10991,4453],{"class":4363},[3158,10993,3527],{"class":3175},[3158,10995,10997],{"class":3160,"line":10996},228,[3158,10998,6573],{"class":3175},[3158,11000,11002,11004,11006,11008,11010],{"class":3160,"line":11001},229,[3158,11003,8588],{"class":4440},[3158,11005,4463],{"class":3171},[3158,11007,3176],{"class":3175},[3158,11009,7281],{"class":4363},[3158,11011,8597],{"class":4348},[3158,11013,11015],{"class":3160,"line":11014},230,[3158,11016,8602],{"class":3175},[3158,11018,11020,11022,11024,11026],{"class":3160,"line":11019},231,[3158,11021,8607],{"class":3179},[3158,11023,4407],{"class":3175},[3158,11025,8612],{"class":4354},[3158,11027,6786],{"class":3175},[3158,11029,11031,11033,11035,11037,11039,11041,11043,11045],{"class":3160,"line":11030},232,[3158,11032,8619],{"class":3179},[3158,11034,4407],{"class":3175},[3158,11036,8624],{"class":4354},[3158,11038,7352],{"class":7351},[3158,11040,4428],{"class":3179},[3158,11042,7383],{"class":7351},[3158,11044,8633],{"class":4354},[3158,11046,6786],{"class":3175},[3158,11048,11050,11052,11054,11056,11058],{"class":3160,"line":11049},233,[3158,11051,8640],{"class":3179},[3158,11053,4407],{"class":3175},[3158,11055,8086],{"class":3179},[3158,11057,3029],{"class":3175},[3158,11059,9884],{"class":3179},[3158,11061,11063],{"class":3160,"line":11062},234,[3158,11064,8675],{"class":3175},[3158,11066,11068],{"class":3160,"line":11067},235,[3158,11069,8680],{"class":3175},[3158,11071,11073],{"class":3160,"line":11072},236,[3158,11074,8147],{"class":3175},[3158,11076,11078],{"class":3160,"line":11077},237,[3158,11079,11080],{"class":3164},"        // Бізнес-правило: не можна видаляти товар з залишком\n",[3158,11082,11084,11086,11088,11090,11092,11094,11097,11099],{"class":3160,"line":11083},238,[3158,11085,8548],{"class":4440},[3158,11087,4444],{"class":3175},[3158,11089,4447],{"class":3179},[3158,11091,3029],{"class":3175},[3158,11093,6088],{"class":3179},[3158,11095,11096],{"class":3175}," > ",[3158,11098,5475],{"class":3551},[3158,11100,3527],{"class":3175},[3158,11102,11104],{"class":3160,"line":11103},239,[3158,11105,6573],{"class":3175},[3158,11107,11109,11111,11113,11115,11117],{"class":3160,"line":11108},240,[3158,11110,8588],{"class":4440},[3158,11112,9136],{"class":3171},[3158,11114,3176],{"class":3175},[3158,11116,7281],{"class":4363},[3158,11118,8597],{"class":4348},[3158,11120,11122],{"class":3160,"line":11121},241,[3158,11123,8602],{"class":3175},[3158,11125,11127,11129,11131,11134],{"class":3160,"line":11126},242,[3158,11128,8607],{"class":3179},[3158,11130,4407],{"class":3175},[3158,11132,11133],{"class":4354},"\"Cannot delete product\"",[3158,11135,6786],{"class":3175},[3158,11137,11139,11141,11143,11146,11148,11150,11152,11154,11156,11159],{"class":3160,"line":11138},243,[3158,11140,8619],{"class":3179},[3158,11142,4407],{"class":3175},[3158,11144,11145],{"class":4354},"$\"Product has ",[3158,11147,7352],{"class":7351},[3158,11149,4447],{"class":3179},[3158,11151,3029],{"class":7351},[3158,11153,6088],{"class":3179},[3158,11155,7383],{"class":7351},[3158,11157,11158],{"class":4354}," items in stock. Reduce stock to zero before deletion.\"",[3158,11160,6786],{"class":3175},[3158,11162,11164,11166,11168,11170,11172],{"class":3160,"line":11163},244,[3158,11165,8640],{"class":3179},[3158,11167,4407],{"class":3175},[3158,11169,8086],{"class":3179},[3158,11171,3029],{"class":3175},[3158,11173,11174],{"class":3179},"Status409Conflict\n",[3158,11176,11178],{"class":3160,"line":11177},245,[3158,11179,8675],{"class":3175},[3158,11181,11183],{"class":3160,"line":11182},246,[3158,11184,8680],{"class":3175},[3158,11186,11188],{"class":3160,"line":11187},247,[3158,11189,8147],{"class":3175},[3158,11191,11193,11195,11197,11199,11201,11204,11206,11208],{"class":3160,"line":11192},248,[3158,11194,7942],{"class":3179},[3158,11196,3029],{"class":3175},[3158,11198,4418],{"class":3179},[3158,11200,3029],{"class":3175},[3158,11202,11203],{"class":3171},"Remove",[3158,11205,3176],{"class":3175},[3158,11207,4447],{"class":3179},[3158,11209,4431],{"class":3175},[3158,11211,11213,11215,11217,11219,11221],{"class":3160,"line":11212},249,[3158,11214,9381],{"class":4363},[3158,11216,4413],{"class":3179},[3158,11218,3029],{"class":3175},[3158,11220,9388],{"class":3171},[3158,11222,4968],{"class":3175},[3158,11224,11226],{"class":3160,"line":11225},250,[3158,11227,8147],{"class":3175},[3158,11229,11231,11233,11235],{"class":3160,"line":11230},251,[3158,11232,4460],{"class":4440},[3158,11234,10648],{"class":3171},[3158,11236,4968],{"class":3175},[3158,11238,11240],{"class":3160,"line":11239},252,[3158,11241,3879],{"class":3175},[3158,11243,11245],{"class":3160,"line":11244},253,[3158,11246,3193],{"emptyLinePlaceholder":3192},[3158,11248,11250,11252,11254,11256],{"class":3160,"line":11249},254,[3158,11251,7973],{"class":3164},[3158,11253,4373],{"class":7976},[3158,11255,7980],{"class":7979},[3158,11257,7983],{"class":7976},[3158,11259,11261],{"class":3160,"line":11260},255,[3158,11262,11263],{"class":3164},"    /// Оновити залишок товару\n",[3158,11265,11267,11269,11271,11273],{"class":3160,"line":11266},256,[3158,11268,7973],{"class":3164},[3158,11270,7995],{"class":7976},[3158,11272,7980],{"class":7979},[3158,11274,7983],{"class":7976},[3158,11276,11278,11280,11282,11284,11286,11288,11290,11292,11294,11296,11298],{"class":3160,"line":11277},257,[3158,11279,7973],{"class":3164},[3158,11281,4373],{"class":7976},[3158,11283,8305],{"class":7979},[3158,11285,8308],{"class":8032},[3158,11287,8036],{"class":3164},[3158,11289,8313],{"class":4354},[3158,11291,8011],{"class":7976},[3158,11293,8318],{"class":3164},[3158,11295,7995],{"class":7976},[3158,11297,8305],{"class":7979},[3158,11299,7983],{"class":7976},[3158,11301,11303,11305,11307,11309,11311,11313,11316,11318,11321,11323,11325],{"class":3160,"line":11302},258,[3158,11304,7973],{"class":3164},[3158,11306,4373],{"class":7976},[3158,11308,8305],{"class":7979},[3158,11310,8308],{"class":8032},[3158,11312,8036],{"class":3164},[3158,11314,11315],{"class":4354},"\"quantity\"",[3158,11317,8011],{"class":7976},[3158,11319,11320],{"class":3164},"Нова кількість",[3158,11322,7995],{"class":7976},[3158,11324,8305],{"class":7979},[3158,11326,7983],{"class":7976},[3158,11328,11330,11332,11334,11336,11338,11340,11342,11344],{"class":3160,"line":11329},259,[3158,11331,7973],{"class":3164},[3158,11333,4373],{"class":7976},[3158,11335,8008],{"class":7979},[3158,11337,8011],{"class":7976},[3158,11339,2999],{"class":3164},[3158,11341,7995],{"class":7976},[3158,11343,8008],{"class":7979},[3158,11345,7983],{"class":7976},[3158,11347,11349,11351,11353,11355,11357,11359,11361,11363,11366,11368,11370],{"class":3160,"line":11348},260,[3158,11350,7973],{"class":3164},[3158,11352,4373],{"class":7976},[3158,11354,8029],{"class":7979},[3158,11356,8033],{"class":8032},[3158,11358,8036],{"class":3164},[3158,11360,10294],{"class":4354},[3158,11362,8011],{"class":7976},[3158,11364,11365],{"class":3164},"Залишок оновлено",[3158,11367,7995],{"class":7976},[3158,11369,8029],{"class":7979},[3158,11371,7983],{"class":7976},[3158,11373,11375,11377,11379,11381,11383,11385,11387,11389,11392,11394,11396],{"class":3160,"line":11374},261,[3158,11376,7973],{"class":3164},[3158,11378,4373],{"class":7976},[3158,11380,8029],{"class":7979},[3158,11382,8033],{"class":8032},[3158,11384,8036],{"class":3164},[3158,11386,8826],{"class":4354},[3158,11388,8011],{"class":7976},[3158,11390,11391],{"class":3164},"Невалідна кількість",[3158,11393,7995],{"class":7976},[3158,11395,8029],{"class":7979},[3158,11397,7983],{"class":7976},[3158,11399,11401,11403,11405,11407,11409,11411,11413,11415,11417,11419,11421],{"class":3160,"line":11400},262,[3158,11402,7973],{"class":3164},[3158,11404,4373],{"class":7976},[3158,11406,8029],{"class":7979},[3158,11408,8033],{"class":8032},[3158,11410,8036],{"class":3164},[3158,11412,8383],{"class":4354},[3158,11414,8011],{"class":7976},[3158,11416,8388],{"class":3164},[3158,11418,7995],{"class":7976},[3158,11420,8029],{"class":7979},[3158,11422,7983],{"class":7976},[3158,11424,11426,11428,11431,11433,11436],{"class":3160,"line":11425},263,[3158,11427,5335],{"class":3175},[3158,11429,11430],{"class":4348},"HttpPatch",[3158,11432,3176],{"class":3175},[3158,11434,11435],{"class":4354},"\"{id:int}/stock\"",[3158,11437,4358],{"class":3175},[3158,11439,11441,11443,11445,11447,11449,11451,11453],{"class":3160,"line":11440},264,[3158,11442,5335],{"class":3175},[3158,11444,8065],{"class":4348},[3158,11446,3176],{"class":3175},[3158,11448,8086],{"class":3179},[3158,11450,3029],{"class":3175},[3158,11452,10360],{"class":3179},[3158,11454,4358],{"class":3175},[3158,11456,11458,11460,11462,11464,11466,11468,11470,11472,11474,11476,11478],{"class":3160,"line":11457},265,[3158,11459,5335],{"class":3175},[3158,11461,8065],{"class":4348},[3158,11463,3176],{"class":3175},[3158,11465,8070],{"class":4363},[3158,11467,3176],{"class":3175},[3158,11469,8447],{"class":4348},[3158,11471,8424],{"class":3175},[3158,11473,8086],{"class":3179},[3158,11475,3029],{"class":3175},[3158,11477,8925],{"class":3179},[3158,11479,4358],{"class":3175},[3158,11481,11483,11485,11487,11489,11491,11493,11495,11497,11499,11501,11503],{"class":3160,"line":11482},266,[3158,11484,5335],{"class":3175},[3158,11486,8065],{"class":4348},[3158,11488,3176],{"class":3175},[3158,11490,8070],{"class":4363},[3158,11492,3176],{"class":3175},[3158,11494,8447],{"class":4348},[3158,11496,8424],{"class":3175},[3158,11498,8086],{"class":3179},[3158,11500,3029],{"class":3175},[3158,11502,8456],{"class":3179},[3158,11504,4358],{"class":3175},[3158,11506,11508,11510,11512,11514,11516,11518,11520,11523,11525,11527,11529,11532,11535,11538,11540,11543],{"class":3160,"line":11507},267,[3158,11509,5306],{"class":4363},[3158,11511,4367],{"class":4363},[3158,11513,4370],{"class":4348},[3158,11515,4373],{"class":3175},[3158,11517,3094],{"class":4348},[3158,11519,4378],{"class":3175},[3158,11521,11522],{"class":3171},"UpdateStock",[3158,11524,3176],{"class":3175},[3158,11526,4386],{"class":4363},[3158,11528,4389],{"class":3179},[3158,11530,11531],{"class":3175},", [",[3158,11533,11534],{"class":4348},"FromQuery",[3158,11536,11537],{"class":3175},"] ",[3158,11539,4386],{"class":4363},[3158,11541,11542],{"class":3179}," quantity",[3158,11544,3527],{"class":3175},[3158,11546,11548],{"class":3160,"line":11547},268,[3158,11549,6477],{"class":3175},[3158,11551,11553,11555,11557,11560,11563,11565],{"class":3160,"line":11552},269,[3158,11554,8548],{"class":4440},[3158,11556,4444],{"class":3175},[3158,11558,11559],{"class":3179},"quantity",[3158,11561,11562],{"class":3175}," \u003C ",[3158,11564,5475],{"class":3551},[3158,11566,3527],{"class":3175},[3158,11568,11570],{"class":3160,"line":11569},270,[3158,11571,6573],{"class":3175},[3158,11573,11575,11577,11580,11582,11584],{"class":3160,"line":11574},271,[3158,11576,8588],{"class":4440},[3158,11578,11579],{"class":3171}," BadRequest",[3158,11581,3176],{"class":3175},[3158,11583,7281],{"class":4363},[3158,11585,8597],{"class":4348},[3158,11587,11589],{"class":3160,"line":11588},272,[3158,11590,8602],{"class":3175},[3158,11592,11594,11596,11598,11601],{"class":3160,"line":11593},273,[3158,11595,8607],{"class":3179},[3158,11597,4407],{"class":3175},[3158,11599,11600],{"class":4354},"\"Invalid quantity\"",[3158,11602,6786],{"class":3175},[3158,11604,11606,11608,11610,11613],{"class":3160,"line":11605},274,[3158,11607,8619],{"class":3179},[3158,11609,4407],{"class":3175},[3158,11611,11612],{"class":4354},"\"Stock quantity cannot be negative\"",[3158,11614,6786],{"class":3175},[3158,11616,11618,11620,11622,11624,11626],{"class":3160,"line":11617},275,[3158,11619,8640],{"class":3179},[3158,11621,4407],{"class":3175},[3158,11623,8086],{"class":3179},[3158,11625,3029],{"class":3175},[3158,11627,11628],{"class":3179},"Status400BadRequest\n",[3158,11630,11632],{"class":3160,"line":11631},276,[3158,11633,8675],{"class":3175},[3158,11635,11637],{"class":3160,"line":11636},277,[3158,11638,8680],{"class":3175},[3158,11640,11642],{"class":3160,"line":11641},278,[3158,11643,8147],{"class":3175},[3158,11645,11647,11649,11651,11653,11655,11657,11659,11661,11663,11665,11667,11669],{"class":3160,"line":11646},279,[3158,11648,8152],{"class":4363},[3158,11650,4404],{"class":3179},[3158,11652,4407],{"class":3175},[3158,11654,4410],{"class":4363},[3158,11656,4413],{"class":3179},[3158,11658,3029],{"class":3175},[3158,11660,4418],{"class":3179},[3158,11662,3029],{"class":3175},[3158,11664,4423],{"class":3171},[3158,11666,3176],{"class":3175},[3158,11668,4428],{"class":3179},[3158,11670,4431],{"class":3175},[3158,11672,11674],{"class":3160,"line":11673},280,[3158,11675,8147],{"class":3175},[3158,11677,11679,11681,11683,11685,11687,11689],{"class":3160,"line":11678},281,[3158,11680,8548],{"class":4440},[3158,11682,4444],{"class":3175},[3158,11684,4447],{"class":3179},[3158,11686,4450],{"class":4363},[3158,11688,4453],{"class":4363},[3158,11690,3527],{"class":3175},[3158,11692,11694],{"class":3160,"line":11693},282,[3158,11695,6573],{"class":3175},[3158,11697,11699,11701,11703,11705,11707],{"class":3160,"line":11698},283,[3158,11700,8588],{"class":4440},[3158,11702,4463],{"class":3171},[3158,11704,3176],{"class":3175},[3158,11706,7281],{"class":4363},[3158,11708,8597],{"class":4348},[3158,11710,11712],{"class":3160,"line":11711},284,[3158,11713,8602],{"class":3175},[3158,11715,11717,11719,11721,11723],{"class":3160,"line":11716},285,[3158,11718,8607],{"class":3179},[3158,11720,4407],{"class":3175},[3158,11722,8612],{"class":4354},[3158,11724,6786],{"class":3175},[3158,11726,11728,11730,11732,11734,11736,11738,11740,11742],{"class":3160,"line":11727},286,[3158,11729,8619],{"class":3179},[3158,11731,4407],{"class":3175},[3158,11733,8624],{"class":4354},[3158,11735,7352],{"class":7351},[3158,11737,4428],{"class":3179},[3158,11739,7383],{"class":7351},[3158,11741,8633],{"class":4354},[3158,11743,6786],{"class":3175},[3158,11745,11747,11749,11751,11753,11755],{"class":3160,"line":11746},287,[3158,11748,8640],{"class":3179},[3158,11750,4407],{"class":3175},[3158,11752,8086],{"class":3179},[3158,11754,3029],{"class":3175},[3158,11756,9884],{"class":3179},[3158,11758,11760],{"class":3160,"line":11759},288,[3158,11761,8675],{"class":3175},[3158,11763,11765],{"class":3160,"line":11764},289,[3158,11766,8680],{"class":3175},[3158,11768,11770],{"class":3160,"line":11769},290,[3158,11771,8147],{"class":3175},[3158,11773,11775,11777,11779,11781,11783,11785],{"class":3160,"line":11774},291,[3158,11776,10146],{"class":3179},[3158,11778,3029],{"class":3175},[3158,11780,6088],{"class":3179},[3158,11782,4407],{"class":3175},[3158,11784,11559],{"class":3179},[3158,11786,5264],{"class":3175},[3158,11788,11790,11792,11794,11796,11798,11800,11802,11804],{"class":3160,"line":11789},292,[3158,11791,10146],{"class":3179},[3158,11793,3029],{"class":3175},[3158,11795,5622],{"class":3179},[3158,11797,4407],{"class":3175},[3158,11799,5600],{"class":3179},[3158,11801,3029],{"class":3175},[3158,11803,5605],{"class":3179},[3158,11805,5264],{"class":3175},[3158,11807,11809],{"class":3160,"line":11808},293,[3158,11810,8147],{"class":3175},[3158,11812,11814,11816,11818,11820,11822],{"class":3160,"line":11813},294,[3158,11815,9381],{"class":4363},[3158,11817,4413],{"class":3179},[3158,11819,3029],{"class":3175},[3158,11821,9388],{"class":3171},[3158,11823,4968],{"class":3175},[3158,11825,11827],{"class":3160,"line":11826},295,[3158,11828,8147],{"class":3175},[3158,11830,11832,11834,11836],{"class":3160,"line":11831},296,[3158,11833,4460],{"class":4440},[3158,11835,10648],{"class":3171},[3158,11837,4968],{"class":3175},[3158,11839,11841],{"class":3160,"line":11840},297,[3158,11842,3879],{"class":3175},[3158,11844,11846],{"class":3160,"line":11845},298,[3158,11847,3193],{"emptyLinePlaceholder":3192},[3158,11849,11851],{"class":3160,"line":11850},299,[3158,11852,11853],{"class":3164},"    // Приватний допоміжний метод для маппінгу\n",[3158,11855,11857,11859,11862,11865,11867,11869,11871,11873,11876,11878],{"class":3160,"line":11856},300,[3158,11858,7871],{"class":4363},[3158,11860,11861],{"class":4363}," static",[3158,11863,11864],{"class":4348}," ProductResponseDto",[3158,11866,8696],{"class":3171},[3158,11868,3176],{"class":3175},[3158,11870,4526],{"class":4348},[3158,11872,4404],{"class":3179},[3158,11874,11875],{"class":3175},") => ",[3158,11877,7281],{"class":4363},[3158,11879,8122],{"class":3175},[3158,11881,11883],{"class":3160,"line":11882},301,[3158,11884,6477],{"class":3175},[3158,11886,11888,11891,11893,11895,11897,11899],{"class":3160,"line":11887},302,[3158,11889,11890],{"class":3179},"        Id",[3158,11892,4407],{"class":3175},[3158,11894,4447],{"class":3179},[3158,11896,3029],{"class":3175},[3158,11898,6597],{"class":3179},[3158,11900,6786],{"class":3175},[3158,11902,11904,11907,11909,11911,11913,11915],{"class":3160,"line":11903},303,[3158,11905,11906],{"class":3179},"        Name",[3158,11908,4407],{"class":3175},[3158,11910,4447],{"class":3179},[3158,11912,3029],{"class":3175},[3158,11914,5966],{"class":3179},[3158,11916,6786],{"class":3175},[3158,11918,11920,11922,11924,11926,11928,11930],{"class":3160,"line":11919},304,[3158,11921,7317],{"class":3179},[3158,11923,4407],{"class":3175},[3158,11925,4447],{"class":3179},[3158,11927,3029],{"class":3175},[3158,11929,5407],{"class":3179},[3158,11931,6786],{"class":3175},[3158,11933,11935,11938,11940,11942,11944,11946],{"class":3160,"line":11934},305,[3158,11936,11937],{"class":3179},"        Price",[3158,11939,4407],{"class":3175},[3158,11941,4447],{"class":3179},[3158,11943,3029],{"class":3175},[3158,11945,6043],{"class":3179},[3158,11947,6786],{"class":3175},[3158,11949,11951,11954,11956,11958,11960,11962],{"class":3160,"line":11950},306,[3158,11952,11953],{"class":3179},"        Stock",[3158,11955,4407],{"class":3175},[3158,11957,4447],{"class":3179},[3158,11959,3029],{"class":3175},[3158,11961,6088],{"class":3179},[3158,11963,6786],{"class":3175},[3158,11965,11967,11970,11972,11974,11976,11978],{"class":3160,"line":11966},307,[3158,11968,11969],{"class":3179},"        Category",[3158,11971,4407],{"class":3175},[3158,11973,4447],{"class":3179},[3158,11975,3029],{"class":3175},[3158,11977,5533],{"class":3179},[3158,11979,6786],{"class":3175},[3158,11981,11983,11986,11988,11990,11992,11994],{"class":3160,"line":11982},308,[3158,11984,11985],{"class":3179},"        IsActive",[3158,11987,4407],{"class":3175},[3158,11989,4447],{"class":3179},[3158,11991,3029],{"class":3175},[3158,11993,6149],{"class":3179},[3158,11995,6786],{"class":3175},[3158,11997,11999,12002,12004,12006,12008,12010],{"class":3160,"line":11998},309,[3158,12000,12001],{"class":3179},"        CreatedAt",[3158,12003,4407],{"class":3175},[3158,12005,4447],{"class":3179},[3158,12007,3029],{"class":3175},[3158,12009,8208],{"class":3179},[3158,12011,6786],{"class":3175},[3158,12013,12015,12018,12020,12022,12024],{"class":3160,"line":12014},310,[3158,12016,12017],{"class":3179},"        UpdatedAt",[3158,12019,4407],{"class":3175},[3158,12021,4447],{"class":3179},[3158,12023,3029],{"class":3175},[3158,12025,12026],{"class":3179},"UpdatedAt\n",[3158,12028,12030],{"class":3160,"line":12029},311,[3158,12031,12032],{"class":3175},"    };\n",[3158,12034,12036],{"class":3160,"line":12035},312,[3158,12037,4496],{"class":3175},[2964,12039,12040],{},"Декомпозиція коду:",[4273,12042,12043,12050,12063,12070,12082,12093],{},[2983,12044,12045,12049],{},[2968,12046,12047],{},[3088,12048,3104],{}," — документує можливі типи відповідей для OpenAPI/Swagger",[2983,12051,12052,12055,12056,3132,12059,12062],{},[2968,12053,12054],{},"XML-коментарі"," — ",[3088,12057,12058],{},"\u003Csummary>",[3088,12060,12061],{},"\u003Cresponse>"," генерують документацію",[2983,12064,12065,12069],{},[2968,12066,12067],{},[3088,12068,8447],{}," — стандартизований формат помилок (RFC 9457)",[2983,12071,12072,12077,12078,12081],{},[2968,12073,12074],{},[3088,12075,12076],{},"CreatedAtAction()"," — автоматично генерує ",[3088,12079,12080],{},"Location: /api/products/4"," header",[2983,12083,12084,12055,12086,12089,12090],{},[2968,12085,4793],{},[3088,12087,12088],{},"return MapToDto(product)"," замість ",[3088,12091,12092],{},"return Ok(MapToDto(product))",[2983,12094,12095,12098],{},[2968,12096,12097],{},"Structured logging"," — параметризовані повідомлення для кращого аналізу",[3109,12100],{},[2959,12102,12104],{"id":12103},"повернення-файлів-з-api","Повернення файлів з API",[2964,12106,12107],{},"Окрім JSON-даних, API часто потребує повертати файли: звіти у PDF, експорт у CSV, зображення товарів. ASP.NET Core надає кілька способів роботи з файлами через спеціалізовані результати.",[3038,12109,12111],{"id":12110},"типи-fileresult","Типи FileResult",[3847,12113,12114],{},[3149,12115,12117],{"className":3851,"code":12116,"language":3847,"meta":3154,"style":3154},"graph TD\n    A[FileResult] --> B[FileContentResult]\n    A --> C[FileStreamResult]\n    A --> D[PhysicalFileResult]\n    A --> E[VirtualFileResult]\n    \n    B --> F[\"File(byte[], contentType)\"]\n    C --> G[\"File(Stream, contentType)\"]\n    D --> H[\"PhysicalFile(path, contentType)\"]\n    E --> I[\"File з wwwroot\"]\n    \n    style A fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n    style B fill:#10b981,stroke:#059669,color:#ffffff\n    style C fill:#10b981,stroke:#059669,color:#ffffff\n    style D fill:#10b981,stroke:#059669,color:#ffffff\n    style E fill:#10b981,stroke:#059669,color:#ffffff\n",[3088,12118,12119,12124,12129,12134,12139,12144,12148,12153,12158,12163,12168,12172,12177,12182,12187,12192],{"__ignoreMap":3154},[3158,12120,12121],{"class":3160,"line":3161},[3158,12122,12123],{},"graph TD\n",[3158,12125,12126],{"class":3160,"line":3168},[3158,12127,12128],{},"    A[FileResult] --> B[FileContentResult]\n",[3158,12130,12131],{"class":3160,"line":3189},[3158,12132,12133],{},"    A --> C[FileStreamResult]\n",[3158,12135,12136],{"class":3160,"line":3196},[3158,12137,12138],{},"    A --> D[PhysicalFileResult]\n",[3158,12140,12141],{"class":3160,"line":3202},[3158,12142,12143],{},"    A --> E[VirtualFileResult]\n",[3158,12145,12146],{"class":3160,"line":3223},[3158,12147,3884],{},[3158,12149,12150],{"class":3160,"line":3249},[3158,12151,12152],{},"    B --> F[\"File(byte[], contentType)\"]\n",[3158,12154,12155],{"class":3160,"line":3274},[3158,12156,12157],{},"    C --> G[\"File(Stream, contentType)\"]\n",[3158,12159,12160],{"class":3160,"line":3279},[3158,12161,12162],{},"    D --> H[\"PhysicalFile(path, contentType)\"]\n",[3158,12164,12165],{"class":3160,"line":3285},[3158,12166,12167],{},"    E --> I[\"File з wwwroot\"]\n",[3158,12169,12170],{"class":3160,"line":3305},[3158,12171,3884],{},[3158,12173,12174],{"class":3160,"line":3310},[3158,12175,12176],{},"    style A fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n",[3158,12178,12179],{"class":3160,"line":3316},[3158,12180,12181],{},"    style B fill:#10b981,stroke:#059669,color:#ffffff\n",[3158,12183,12184],{"class":3160,"line":3443},[3158,12185,12186],{},"    style C fill:#10b981,stroke:#059669,color:#ffffff\n",[3158,12188,12189],{"class":3160,"line":3458},[3158,12190,12191],{},"    style D fill:#10b981,stroke:#059669,color:#ffffff\n",[3158,12193,12194],{"class":3160,"line":3463},[3158,12195,12196],{},"    style E fill:#10b981,stroke:#059669,color:#ffffff\n",[4273,12198,12199,12207,12215,12223],{},[2983,12200,12201,12206],{},[2968,12202,12203],{},[3088,12204,12205],{},"FileContentResult"," — файл з масиву байтів (для невеликих файлів у пам'яті)",[2983,12208,12209,12214],{},[2968,12210,12211],{},[3088,12212,12213],{},"FileStreamResult"," — файл зі стріму (для великих файлів, що генеруються на льоту)",[2983,12216,12217,12222],{},[2968,12218,12219],{},[3088,12220,12221],{},"PhysicalFileResult"," — файл з файлової системи за абсолютним шляхом",[2983,12224,12225,12230,12231,12234],{},[2968,12226,12227],{},[3088,12228,12229],{},"VirtualFileResult"," — файл з ",[3088,12232,12233],{},"wwwroot"," або іншого віртуального шляху",[3038,12236,12238],{"id":12237},"приклад-1-експорт-товарів-у-csv","Приклад 1: Експорт товарів у CSV",[2964,12240,12241,12242,3142],{},"Додайте метод до ",[3088,12243,7894],{},[3149,12245,12247],{"className":3151,"code":12246,"language":3153,"meta":3154,"style":3154},"/// \u003Csummary>\n/// Експортувати всі товари у CSV-файл\n/// \u003C/summary>\n/// \u003Creturns>CSV-файл\u003C/returns>\n/// \u003Cresponse code=\"200\">CSV-файл успішно згенеровано\u003C/response>\n[HttpGet(\"export/csv\")]\n[Produces(\"text/csv\")]\n[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]\npublic async Task\u003CIActionResult> ExportToCsv()\n{\n    _logger.LogInformation(\"Exporting products to CSV\");\n    \n    var products = await _db.Products.ToListAsync();\n    \n    // Генерація CSV\n    var csv = new StringBuilder();\n    csv.AppendLine(\"Id,Name,Description,Price,Stock,Category,IsActive\");\n    \n    foreach (var product in products)\n    {\n        csv.AppendLine($\"{product.Id},\" +\n                      $\"\\\"{product.Name}\\\",\" +\n                      $\"\\\"{product.Description ?? \"\"}\\\",\" +\n                      $\"{product.Price},\" +\n                      $\"{product.Stock},\" +\n                      $\"\\\"{product.Category ?? \"\"}\\\",\" +\n                      $\"{product.IsActive}\");\n    }\n    \n    var bytes = Encoding.UTF8.GetBytes(csv.ToString());\n    \n    // File() з масиву байтів + ім'я файлу для завантаження\n    return File(\n        bytes, \n        \"text/csv\", \n        $\"products_{DateTime.UtcNow:yyyyMMdd_HHmmss}.csv\"\n    );\n}\n",[3088,12248,12249,12260,12265,12275,12294,12319,12332,12345,12369,12388,12392,12408,12412,12434,12438,12443,12459,12476,12480,12498,12502,12531,12556,12584,12602,12620,12646,12665,12669,12673,12708,12712,12717,12726,12733,12740,12763,12768],{"__ignoreMap":3154},[3158,12250,12251,12254,12256,12258],{"class":3160,"line":3161},[3158,12252,12253],{"class":3164},"/// ",[3158,12255,4373],{"class":7976},[3158,12257,7980],{"class":7979},[3158,12259,7983],{"class":7976},[3158,12261,12262],{"class":3160,"line":3168},[3158,12263,12264],{"class":3164},"/// Експортувати всі товари у CSV-файл\n",[3158,12266,12267,12269,12271,12273],{"class":3160,"line":3189},[3158,12268,12253],{"class":3164},[3158,12270,7995],{"class":7976},[3158,12272,7980],{"class":7979},[3158,12274,7983],{"class":7976},[3158,12276,12277,12279,12281,12283,12285,12288,12290,12292],{"class":3160,"line":3196},[3158,12278,12253],{"class":3164},[3158,12280,4373],{"class":7976},[3158,12282,8008],{"class":7979},[3158,12284,8011],{"class":7976},[3158,12286,12287],{"class":3164},"CSV-файл",[3158,12289,7995],{"class":7976},[3158,12291,8008],{"class":7979},[3158,12293,7983],{"class":7976},[3158,12295,12296,12298,12300,12302,12304,12306,12308,12310,12313,12315,12317],{"class":3160,"line":3202},[3158,12297,12253],{"class":3164},[3158,12299,4373],{"class":7976},[3158,12301,8029],{"class":7979},[3158,12303,8033],{"class":8032},[3158,12305,8036],{"class":3164},[3158,12307,8039],{"class":4354},[3158,12309,8011],{"class":7976},[3158,12311,12312],{"class":3164},"CSV-файл успішно згенеровано",[3158,12314,7995],{"class":7976},[3158,12316,8029],{"class":7979},[3158,12318,7983],{"class":7976},[3158,12320,12321,12323,12325,12327,12330],{"class":3160,"line":3223},[3158,12322,4345],{"class":3175},[3158,12324,4349],{"class":4348},[3158,12326,3176],{"class":3175},[3158,12328,12329],{"class":4354},"\"export/csv\"",[3158,12331,4358],{"class":3175},[3158,12333,12334,12336,12338,12340,12343],{"class":3160,"line":3249},[3158,12335,4345],{"class":3175},[3158,12337,7841],{"class":4348},[3158,12339,3176],{"class":3175},[3158,12341,12342],{"class":4354},"\"text/csv\"",[3158,12344,4358],{"class":3175},[3158,12346,12347,12349,12351,12353,12355,12357,12359,12361,12363,12365,12367],{"class":3160,"line":3274},[3158,12348,4345],{"class":3175},[3158,12350,8065],{"class":4348},[3158,12352,3176],{"class":3175},[3158,12354,8070],{"class":4363},[3158,12356,3176],{"class":3175},[3158,12358,12205],{"class":4348},[3158,12360,8424],{"class":3175},[3158,12362,8086],{"class":3179},[3158,12364,3029],{"class":3175},[3158,12366,8091],{"class":3179},[3158,12368,4358],{"class":3175},[3158,12370,12371,12373,12375,12377,12379,12381,12383,12386],{"class":3160,"line":3279},[3158,12372,4364],{"class":4363},[3158,12374,4367],{"class":4363},[3158,12376,4370],{"class":4348},[3158,12378,4373],{"class":3175},[3158,12380,3094],{"class":4348},[3158,12382,4378],{"class":3175},[3158,12384,12385],{"class":3171},"ExportToCsv",[3158,12387,8122],{"class":3175},[3158,12389,12390],{"class":3160,"line":3285},[3158,12391,4396],{"class":3175},[3158,12393,12394,12397,12399,12401,12403,12406],{"class":3160,"line":3305},[3158,12395,12396],{"class":3179},"    _logger",[3158,12398,3029],{"class":3175},[3158,12400,8135],{"class":3171},[3158,12402,3176],{"class":3175},[3158,12404,12405],{"class":4354},"\"Exporting products to CSV\"",[3158,12407,4431],{"class":3175},[3158,12409,12410],{"class":3160,"line":3310},[3158,12411,3884],{"class":3175},[3158,12413,12414,12416,12418,12420,12422,12424,12426,12428,12430,12432],{"class":3160,"line":3316},[3158,12415,4401],{"class":4363},[3158,12417,8155],{"class":3179},[3158,12419,4407],{"class":3175},[3158,12421,4410],{"class":4363},[3158,12423,4413],{"class":3179},[3158,12425,3029],{"class":3175},[3158,12427,4418],{"class":3179},[3158,12429,3029],{"class":3175},[3158,12431,8217],{"class":3171},[3158,12433,4968],{"class":3175},[3158,12435,12436],{"class":3160,"line":3443},[3158,12437,3884],{"class":3175},[3158,12439,12440],{"class":3160,"line":3458},[3158,12441,12442],{"class":3164},"    // Генерація CSV\n",[3158,12444,12445,12447,12450,12452,12454,12457],{"class":3160,"line":3463},[3158,12446,4401],{"class":4363},[3158,12448,12449],{"class":3179}," csv",[3158,12451,4407],{"class":3175},[3158,12453,7281],{"class":4363},[3158,12455,12456],{"class":4348}," StringBuilder",[3158,12458,4968],{"class":3175},[3158,12460,12461,12464,12466,12469,12471,12474],{"class":3160,"line":3469},[3158,12462,12463],{"class":3179},"    csv",[3158,12465,3029],{"class":3175},[3158,12467,12468],{"class":3171},"AppendLine",[3158,12470,3176],{"class":3175},[3158,12472,12473],{"class":4354},"\"Id,Name,Description,Price,Stock,Category,IsActive\"",[3158,12475,4431],{"class":3175},[3158,12477,12478],{"class":3160,"line":3480},[3158,12479,3884],{"class":3175},[3158,12481,12482,12485,12487,12489,12491,12494,12496],{"class":3160,"line":3495},[3158,12483,12484],{"class":4440},"    foreach",[3158,12486,4444],{"class":3175},[3158,12488,7133],{"class":4363},[3158,12490,4404],{"class":3179},[3158,12492,12493],{"class":4440}," in",[3158,12495,8155],{"class":3179},[3158,12497,3527],{"class":3175},[3158,12499,12500],{"class":3160,"line":3500},[3158,12501,6477],{"class":3175},[3158,12503,12504,12507,12509,12511,12513,12515,12517,12519,12521,12523,12525,12528],{"class":3160,"line":3506},[3158,12505,12506],{"class":3179},"        csv",[3158,12508,3029],{"class":3175},[3158,12510,12468],{"class":3171},[3158,12512,3176],{"class":3175},[3158,12514,7348],{"class":4354},[3158,12516,7352],{"class":7351},[3158,12518,4447],{"class":3179},[3158,12520,3029],{"class":7351},[3158,12522,6597],{"class":3179},[3158,12524,7383],{"class":7351},[3158,12526,12527],{"class":4354},",\"",[3158,12529,12530],{"class":3175}," +\n",[3158,12532,12533,12536,12540,12542,12544,12546,12548,12550,12552,12554],{"class":3160,"line":3518},[3158,12534,12535],{"class":4354},"                      $\"",[3158,12537,12539],{"class":12538},"sjcCO","\\\"",[3158,12541,7352],{"class":7351},[3158,12543,4447],{"class":3179},[3158,12545,3029],{"class":7351},[3158,12547,5966],{"class":3179},[3158,12549,7383],{"class":7351},[3158,12551,12539],{"class":12538},[3158,12553,12527],{"class":4354},[3158,12555,12530],{"class":3175},[3158,12557,12558,12560,12562,12564,12566,12568,12570,12573,12576,12578,12580,12582],{"class":3160,"line":3959},[3158,12559,12535],{"class":4354},[3158,12561,12539],{"class":12538},[3158,12563,7352],{"class":7351},[3158,12565,4447],{"class":3179},[3158,12567,3029],{"class":7351},[3158,12569,5407],{"class":3179},[3158,12571,12572],{"class":3175}," ??",[3158,12574,12575],{"class":4354}," \"\"",[3158,12577,7383],{"class":7351},[3158,12579,12539],{"class":12538},[3158,12581,12527],{"class":4354},[3158,12583,12530],{"class":3175},[3158,12585,12586,12588,12590,12592,12594,12596,12598,12600],{"class":3160,"line":3965},[3158,12587,12535],{"class":4354},[3158,12589,7352],{"class":7351},[3158,12591,4447],{"class":3179},[3158,12593,3029],{"class":7351},[3158,12595,6043],{"class":3179},[3158,12597,7383],{"class":7351},[3158,12599,12527],{"class":4354},[3158,12601,12530],{"class":3175},[3158,12603,12604,12606,12608,12610,12612,12614,12616,12618],{"class":3160,"line":3971},[3158,12605,12535],{"class":4354},[3158,12607,7352],{"class":7351},[3158,12609,4447],{"class":3179},[3158,12611,3029],{"class":7351},[3158,12613,6088],{"class":3179},[3158,12615,7383],{"class":7351},[3158,12617,12527],{"class":4354},[3158,12619,12530],{"class":3175},[3158,12621,12622,12624,12626,12628,12630,12632,12634,12636,12638,12640,12642,12644],{"class":3160,"line":3976},[3158,12623,12535],{"class":4354},[3158,12625,12539],{"class":12538},[3158,12627,7352],{"class":7351},[3158,12629,4447],{"class":3179},[3158,12631,3029],{"class":7351},[3158,12633,5533],{"class":3179},[3158,12635,12572],{"class":3175},[3158,12637,12575],{"class":4354},[3158,12639,7383],{"class":7351},[3158,12641,12539],{"class":12538},[3158,12643,12527],{"class":4354},[3158,12645,12530],{"class":3175},[3158,12647,12648,12650,12652,12654,12656,12658,12660,12663],{"class":3160,"line":3981},[3158,12649,12535],{"class":4354},[3158,12651,7352],{"class":7351},[3158,12653,4447],{"class":3179},[3158,12655,3029],{"class":7351},[3158,12657,6149],{"class":3179},[3158,12659,7383],{"class":7351},[3158,12661,12662],{"class":4354},"\"",[3158,12664,4431],{"class":3175},[3158,12666,12667],{"class":3160,"line":3987},[3158,12668,3879],{"class":3175},[3158,12670,12671],{"class":3160,"line":3993},[3158,12672,3884],{"class":3175},[3158,12674,12675,12677,12680,12682,12685,12687,12690,12692,12695,12697,12700,12702,12705],{"class":3160,"line":3998},[3158,12676,4401],{"class":4363},[3158,12678,12679],{"class":3179}," bytes",[3158,12681,4407],{"class":3175},[3158,12683,12684],{"class":3179},"Encoding",[3158,12686,3029],{"class":3175},[3158,12688,12689],{"class":3179},"UTF8",[3158,12691,3029],{"class":3175},[3158,12693,12694],{"class":3171},"GetBytes",[3158,12696,3176],{"class":3175},[3158,12698,12699],{"class":3179},"csv",[3158,12701,3029],{"class":3175},[3158,12703,12704],{"class":3171},"ToString",[3158,12706,12707],{"class":3175},"());\n",[3158,12709,12710],{"class":3160,"line":4003},[3158,12711,3884],{"class":3175},[3158,12713,12714],{"class":3160,"line":4009},[3158,12715,12716],{"class":3164},"    // File() з масиву байтів + ім'я файлу для завантаження\n",[3158,12718,12719,12721,12724],{"class":3160,"line":4015},[3158,12720,4478],{"class":4440},[3158,12722,12723],{"class":3171}," File",[3158,12725,6732],{"class":3175},[3158,12727,12728,12731],{"class":3160,"line":4021},[3158,12729,12730],{"class":3179},"        bytes",[3158,12732,6761],{"class":3175},[3158,12734,12735,12738],{"class":3160,"line":4026},[3158,12736,12737],{"class":4354},"        \"text/csv\"",[3158,12739,6761],{"class":3175},[3158,12741,12742,12745,12747,12749,12751,12753,12755,12758,12760],{"class":3160,"line":4031},[3158,12743,12744],{"class":4354},"        $\"products_",[3158,12746,7352],{"class":7351},[3158,12748,5600],{"class":3179},[3158,12750,3029],{"class":7351},[3158,12752,5605],{"class":3179},[3158,12754,3142],{"class":3175},[3158,12756,12757],{"class":3179},"yyyyMMdd_HHmmss",[3158,12759,7383],{"class":7351},[3158,12761,12762],{"class":4354},".csv\"\n",[3158,12764,12765],{"class":3160,"line":4037},[3158,12766,12767],{"class":3175},"    );\n",[3158,12769,12770],{"class":3160,"line":4043},[3158,12771,4496],{"class":3175},[2964,12773,12774],{},[2968,12775,12776],{},"Що відбувається:",[2980,12778,12779,12782,12788,12798],{},[2983,12780,12781],{},"Генеруємо CSV-рядок у пам'яті",[2983,12783,12784,12785],{},"Конвертуємо у байти через ",[3088,12786,12787],{},"Encoding.UTF8",[2983,12789,12790,12791,12794,12795],{},"Повертаємо через ",[3088,12792,12793],{},"File()"," з MIME-типом ",[3088,12796,12797],{},"text/csv",[2983,12799,12800],{},"Третій параметр — ім'я файлу для завантаження (браузер покаже діалог \"Save As\")",[3038,12802,12804],{"id":12803},"приклад-2-генерація-pdf-звіту","Приклад 2: Генерація PDF-звіту",[2964,12806,12807,12808,12811],{},"Для генерації PDF використаємо бібліотеку ",[3088,12809,12810],{},"QuestPDF"," (встановіть через NuGet):",[3149,12813,12816],{"className":12814,"code":12815,"language":5173,"meta":3154,"style":3154},"language-bash shiki shiki-themes light-plus dark-plus dark-plus","dotnet add package QuestPDF\n",[3088,12817,12818],{"__ignoreMap":3154},[3158,12819,12820,12823,12826,12829],{"class":3160,"line":3161},[3158,12821,12822],{"class":3171},"dotnet",[3158,12824,12825],{"class":4354}," add",[3158,12827,12828],{"class":4354}," package",[3158,12830,12831],{"class":4354}," QuestPDF\n",[2964,12833,12834],{},"Додайте метод:",[3149,12836,12838],{"className":3151,"code":12837,"language":3153,"meta":3154,"style":3154},"/// \u003Csummary>\n/// Згенерувати PDF-звіт по товарах\n/// \u003C/summary>\n/// \u003Creturns>PDF-файл\u003C/returns>\n/// \u003Cresponse code=\"200\">PDF-звіт успішно згенеровано\u003C/response>\n[HttpGet(\"export/pdf\")]\n[Produces(\"application/pdf\")]\n[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]\npublic async Task\u003CIActionResult> ExportToPdf()\n{\n    _logger.LogInformation(\"Generating PDF report\");\n    \n    var products = await _db.Products\n        .Where(p => p.IsActive)\n        .OrderBy(p => p.Category)\n        .ThenBy(p => p.Name)\n        .ToListAsync();\n    \n    // Генерація PDF через QuestPDF\n    var pdfBytes = GenerateProductsPdf(products);\n    \n    return File(\n        pdfBytes, \n        \"application/pdf\", \n        $\"products_report_{DateTime.UtcNow:yyyyMMdd}.pdf\"\n    );\n}\n\nprivate byte[] GenerateProductsPdf(List\u003CProduct> products)\n{\n    // Спрощена версія - у реальному проєкті використовуйте QuestPDF\n    // Тут просто повертаємо placeholder\n    var content = $\"Products Report\\n\\nTotal: {products.Count} items\";\n    return Encoding.UTF8.GetBytes(content);\n}\n",[3088,12839,12840,12850,12855,12865,12884,12909,12922,12935,12959,12978,12982,12997,13001,13017,13038,13059,13080,13088,13092,13097,13115,13119,13127,13134,13141,13164,13168,13172,13176,13204,13208,13213,13218,13252,13274],{"__ignoreMap":3154},[3158,12841,12842,12844,12846,12848],{"class":3160,"line":3161},[3158,12843,12253],{"class":3164},[3158,12845,4373],{"class":7976},[3158,12847,7980],{"class":7979},[3158,12849,7983],{"class":7976},[3158,12851,12852],{"class":3160,"line":3168},[3158,12853,12854],{"class":3164},"/// Згенерувати PDF-звіт по товарах\n",[3158,12856,12857,12859,12861,12863],{"class":3160,"line":3189},[3158,12858,12253],{"class":3164},[3158,12860,7995],{"class":7976},[3158,12862,7980],{"class":7979},[3158,12864,7983],{"class":7976},[3158,12866,12867,12869,12871,12873,12875,12878,12880,12882],{"class":3160,"line":3196},[3158,12868,12253],{"class":3164},[3158,12870,4373],{"class":7976},[3158,12872,8008],{"class":7979},[3158,12874,8011],{"class":7976},[3158,12876,12877],{"class":3164},"PDF-файл",[3158,12879,7995],{"class":7976},[3158,12881,8008],{"class":7979},[3158,12883,7983],{"class":7976},[3158,12885,12886,12888,12890,12892,12894,12896,12898,12900,12903,12905,12907],{"class":3160,"line":3202},[3158,12887,12253],{"class":3164},[3158,12889,4373],{"class":7976},[3158,12891,8029],{"class":7979},[3158,12893,8033],{"class":8032},[3158,12895,8036],{"class":3164},[3158,12897,8039],{"class":4354},[3158,12899,8011],{"class":7976},[3158,12901,12902],{"class":3164},"PDF-звіт успішно згенеровано",[3158,12904,7995],{"class":7976},[3158,12906,8029],{"class":7979},[3158,12908,7983],{"class":7976},[3158,12910,12911,12913,12915,12917,12920],{"class":3160,"line":3223},[3158,12912,4345],{"class":3175},[3158,12914,4349],{"class":4348},[3158,12916,3176],{"class":3175},[3158,12918,12919],{"class":4354},"\"export/pdf\"",[3158,12921,4358],{"class":3175},[3158,12923,12924,12926,12928,12930,12933],{"class":3160,"line":3249},[3158,12925,4345],{"class":3175},[3158,12927,7841],{"class":4348},[3158,12929,3176],{"class":3175},[3158,12931,12932],{"class":4354},"\"application/pdf\"",[3158,12934,4358],{"class":3175},[3158,12936,12937,12939,12941,12943,12945,12947,12949,12951,12953,12955,12957],{"class":3160,"line":3274},[3158,12938,4345],{"class":3175},[3158,12940,8065],{"class":4348},[3158,12942,3176],{"class":3175},[3158,12944,8070],{"class":4363},[3158,12946,3176],{"class":3175},[3158,12948,12205],{"class":4348},[3158,12950,8424],{"class":3175},[3158,12952,8086],{"class":3179},[3158,12954,3029],{"class":3175},[3158,12956,8091],{"class":3179},[3158,12958,4358],{"class":3175},[3158,12960,12961,12963,12965,12967,12969,12971,12973,12976],{"class":3160,"line":3279},[3158,12962,4364],{"class":4363},[3158,12964,4367],{"class":4363},[3158,12966,4370],{"class":4348},[3158,12968,4373],{"class":3175},[3158,12970,3094],{"class":4348},[3158,12972,4378],{"class":3175},[3158,12974,12975],{"class":3171},"ExportToPdf",[3158,12977,8122],{"class":3175},[3158,12979,12980],{"class":3160,"line":3285},[3158,12981,4396],{"class":3175},[3158,12983,12984,12986,12988,12990,12992,12995],{"class":3160,"line":3305},[3158,12985,12396],{"class":3179},[3158,12987,3029],{"class":3175},[3158,12989,8135],{"class":3171},[3158,12991,3176],{"class":3175},[3158,12993,12994],{"class":4354},"\"Generating PDF report\"",[3158,12996,4431],{"class":3175},[3158,12998,12999],{"class":3160,"line":3310},[3158,13000,3884],{"class":3175},[3158,13002,13003,13005,13007,13009,13011,13013,13015],{"class":3160,"line":3316},[3158,13004,4401],{"class":4363},[3158,13006,8155],{"class":3179},[3158,13008,4407],{"class":3175},[3158,13010,4410],{"class":4363},[3158,13012,4413],{"class":3179},[3158,13014,3029],{"class":3175},[3158,13016,8166],{"class":3179},[3158,13018,13019,13022,13024,13026,13028,13030,13032,13034,13036],{"class":3160,"line":3443},[3158,13020,13021],{"class":3175},"        .",[3158,13023,8174],{"class":3171},[3158,13025,3176],{"class":3175},[3158,13027,2964],{"class":3179},[3158,13029,6503],{"class":3175},[3158,13031,2964],{"class":3179},[3158,13033,3029],{"class":3175},[3158,13035,6149],{"class":3179},[3158,13037,3527],{"class":3175},[3158,13039,13040,13042,13045,13047,13049,13051,13053,13055,13057],{"class":3160,"line":3458},[3158,13041,13021],{"class":3175},[3158,13043,13044],{"class":3171},"OrderBy",[3158,13046,3176],{"class":3175},[3158,13048,2964],{"class":3179},[3158,13050,6503],{"class":3175},[3158,13052,2964],{"class":3179},[3158,13054,3029],{"class":3175},[3158,13056,5533],{"class":3179},[3158,13058,3527],{"class":3175},[3158,13060,13061,13063,13066,13068,13070,13072,13074,13076,13078],{"class":3160,"line":3463},[3158,13062,13021],{"class":3175},[3158,13064,13065],{"class":3171},"ThenBy",[3158,13067,3176],{"class":3175},[3158,13069,2964],{"class":3179},[3158,13071,6503],{"class":3175},[3158,13073,2964],{"class":3179},[3158,13075,3029],{"class":3175},[3158,13077,5966],{"class":3179},[3158,13079,3527],{"class":3175},[3158,13081,13082,13084,13086],{"class":3160,"line":3469},[3158,13083,13021],{"class":3175},[3158,13085,8217],{"class":3171},[3158,13087,4968],{"class":3175},[3158,13089,13090],{"class":3160,"line":3480},[3158,13091,3884],{"class":3175},[3158,13093,13094],{"class":3160,"line":3495},[3158,13095,13096],{"class":3164},"    // Генерація PDF через QuestPDF\n",[3158,13098,13099,13101,13104,13106,13109,13111,13113],{"class":3160,"line":3500},[3158,13100,4401],{"class":4363},[3158,13102,13103],{"class":3179}," pdfBytes",[3158,13105,4407],{"class":3175},[3158,13107,13108],{"class":3171},"GenerateProductsPdf",[3158,13110,3176],{"class":3175},[3158,13112,8235],{"class":3179},[3158,13114,4431],{"class":3175},[3158,13116,13117],{"class":3160,"line":3506},[3158,13118,3884],{"class":3175},[3158,13120,13121,13123,13125],{"class":3160,"line":3518},[3158,13122,4478],{"class":4440},[3158,13124,12723],{"class":3171},[3158,13126,6732],{"class":3175},[3158,13128,13129,13132],{"class":3160,"line":3959},[3158,13130,13131],{"class":3179},"        pdfBytes",[3158,13133,6761],{"class":3175},[3158,13135,13136,13139],{"class":3160,"line":3965},[3158,13137,13138],{"class":4354},"        \"application/pdf\"",[3158,13140,6761],{"class":3175},[3158,13142,13143,13146,13148,13150,13152,13154,13156,13159,13161],{"class":3160,"line":3971},[3158,13144,13145],{"class":4354},"        $\"products_report_",[3158,13147,7352],{"class":7351},[3158,13149,5600],{"class":3179},[3158,13151,3029],{"class":7351},[3158,13153,5605],{"class":3179},[3158,13155,3142],{"class":3175},[3158,13157,13158],{"class":3179},"yyyyMMdd",[3158,13160,7383],{"class":7351},[3158,13162,13163],{"class":4354},".pdf\"\n",[3158,13165,13166],{"class":3160,"line":3976},[3158,13167,12767],{"class":3175},[3158,13169,13170],{"class":3160,"line":3981},[3158,13171,4496],{"class":3175},[3158,13173,13174],{"class":3160,"line":3987},[3158,13175,3193],{"emptyLinePlaceholder":3192},[3158,13177,13178,13181,13184,13187,13189,13191,13194,13196,13198,13200,13202],{"class":3160,"line":3993},[3158,13179,13180],{"class":4363},"private",[3158,13182,13183],{"class":4363}," byte",[3158,13185,13186],{"class":3175},"[] ",[3158,13188,13108],{"class":3171},[3158,13190,3176],{"class":3175},[3158,13192,13193],{"class":4348},"List",[3158,13195,4373],{"class":3175},[3158,13197,4526],{"class":4348},[3158,13199,4378],{"class":3175},[3158,13201,8235],{"class":3179},[3158,13203,3527],{"class":3175},[3158,13205,13206],{"class":3160,"line":3998},[3158,13207,4396],{"class":3175},[3158,13209,13210],{"class":3160,"line":4003},[3158,13211,13212],{"class":3164},"    // Спрощена версія - у реальному проєкті використовуйте QuestPDF\n",[3158,13214,13215],{"class":3160,"line":4009},[3158,13216,13217],{"class":3164},"    // Тут просто повертаємо placeholder\n",[3158,13219,13220,13222,13225,13227,13230,13233,13236,13238,13240,13242,13245,13247,13250],{"class":3160,"line":4015},[3158,13221,4401],{"class":4363},[3158,13223,13224],{"class":3179}," content",[3158,13226,4407],{"class":3175},[3158,13228,13229],{"class":4354},"$\"Products Report",[3158,13231,13232],{"class":12538},"\\n\\n",[3158,13234,13235],{"class":4354},"Total: ",[3158,13237,7352],{"class":7351},[3158,13239,8235],{"class":3179},[3158,13241,3029],{"class":7351},[3158,13243,13244],{"class":3179},"Count",[3158,13246,7383],{"class":7351},[3158,13248,13249],{"class":4354}," items\"",[3158,13251,5264],{"class":3175},[3158,13253,13254,13256,13259,13261,13263,13265,13267,13269,13272],{"class":3160,"line":4021},[3158,13255,4478],{"class":4440},[3158,13257,13258],{"class":3179}," Encoding",[3158,13260,3029],{"class":3175},[3158,13262,12689],{"class":3179},[3158,13264,3029],{"class":3175},[3158,13266,12694],{"class":3171},[3158,13268,3176],{"class":3175},[3158,13270,13271],{"class":3179},"content",[3158,13273,4431],{"class":3175},[3158,13275,13276],{"class":3160,"line":4026},[3158,13277,4496],{"class":3175},[3038,13279,13281],{"id":13280},"приклад-3-повернення-зображення-товару","Приклад 3: Повернення зображення товару",[2964,13283,13284],{},"Додайте метод для отримання зображення товару з файлової системи:",[3149,13286,13288],{"className":3151,"code":13287,"language":3153,"meta":3154,"style":3154},"/// \u003Csummary>\n/// Отримати зображення товару\n/// \u003C/summary>\n/// \u003Cparam name=\"id\">Ідентифікатор товару\u003C/param>\n/// \u003Creturns>Зображення або 404\u003C/returns>\n/// \u003Cresponse code=\"200\">Зображення знайдено\u003C/response>\n/// \u003Cresponse code=\"404\">Зображення не знайдено\u003C/response>\n[HttpGet(\"{id:int}/image\")]\n[Produces(\"image/jpeg\", \"image/png\")]\n[ProducesResponseType(typeof(FileResult), StatusCodes.Status200OK)]\n[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]\npublic async Task\u003CIActionResult> GetProductImage(int id)\n{\n    var product = await _db.Products.FindAsync(id);\n    \n    if (product is null)\n    {\n        return NotFound(new ProblemDetails\n        {\n            Title = \"Product not found\",\n            Detail = $\"Product with ID {id} does not exist\",\n            Status = StatusCodes.Status404NotFound\n        });\n    }\n    \n    // Шлях до зображення (у реальному проєкті зберігайте в БД)\n    var imagePath = Path.Combine(\n        Directory.GetCurrentDirectory(), \n        \"wwwroot\", \n        \"images\", \n        \"products\", \n        $\"{id}.jpg\"\n    );\n    \n    if (!System.IO.File.Exists(imagePath))\n    {\n        // Повертаємо placeholder зображення\n        imagePath = Path.Combine(\n            Directory.GetCurrentDirectory(), \n            \"wwwroot\", \n            \"images\", \n            \"placeholder.jpg\"\n        );\n    }\n    \n    // PhysicalFile() для файлів з файлової системи\n    return PhysicalFile(imagePath, \"image/jpeg\");\n}\n",[3088,13289,13290,13300,13305,13315,13339,13358,13383,13408,13421,13439,13463,13487,13512,13516,13542,13546,13560,13564,13576,13580,13591,13610,13623,13627,13631,13635,13640,13657,13670,13677,13684,13691,13705,13709,13713,13742,13746,13751,13766,13777,13784,13791,13796,13800,13804,13808,13813,13830],{"__ignoreMap":3154},[3158,13291,13292,13294,13296,13298],{"class":3160,"line":3161},[3158,13293,12253],{"class":3164},[3158,13295,4373],{"class":7976},[3158,13297,7980],{"class":7979},[3158,13299,7983],{"class":7976},[3158,13301,13302],{"class":3160,"line":3168},[3158,13303,13304],{"class":3164},"/// Отримати зображення товару\n",[3158,13306,13307,13309,13311,13313],{"class":3160,"line":3189},[3158,13308,12253],{"class":3164},[3158,13310,7995],{"class":7976},[3158,13312,7980],{"class":7979},[3158,13314,7983],{"class":7976},[3158,13316,13317,13319,13321,13323,13325,13327,13329,13331,13333,13335,13337],{"class":3160,"line":3196},[3158,13318,12253],{"class":3164},[3158,13320,4373],{"class":7976},[3158,13322,8305],{"class":7979},[3158,13324,8308],{"class":8032},[3158,13326,8036],{"class":3164},[3158,13328,8313],{"class":4354},[3158,13330,8011],{"class":7976},[3158,13332,8318],{"class":3164},[3158,13334,7995],{"class":7976},[3158,13336,8305],{"class":7979},[3158,13338,7983],{"class":7976},[3158,13340,13341,13343,13345,13347,13349,13352,13354,13356],{"class":3160,"line":3202},[3158,13342,12253],{"class":3164},[3158,13344,4373],{"class":7976},[3158,13346,8008],{"class":7979},[3158,13348,8011],{"class":7976},[3158,13350,13351],{"class":3164},"Зображення або 404",[3158,13353,7995],{"class":7976},[3158,13355,8008],{"class":7979},[3158,13357,7983],{"class":7976},[3158,13359,13360,13362,13364,13366,13368,13370,13372,13374,13377,13379,13381],{"class":3160,"line":3223},[3158,13361,12253],{"class":3164},[3158,13363,4373],{"class":7976},[3158,13365,8029],{"class":7979},[3158,13367,8033],{"class":8032},[3158,13369,8036],{"class":3164},[3158,13371,8039],{"class":4354},[3158,13373,8011],{"class":7976},[3158,13375,13376],{"class":3164},"Зображення знайдено",[3158,13378,7995],{"class":7976},[3158,13380,8029],{"class":7979},[3158,13382,7983],{"class":7976},[3158,13384,13385,13387,13389,13391,13393,13395,13397,13399,13402,13404,13406],{"class":3160,"line":3249},[3158,13386,12253],{"class":3164},[3158,13388,4373],{"class":7976},[3158,13390,8029],{"class":7979},[3158,13392,8033],{"class":8032},[3158,13394,8036],{"class":3164},[3158,13396,8383],{"class":4354},[3158,13398,8011],{"class":7976},[3158,13400,13401],{"class":3164},"Зображення не знайдено",[3158,13403,7995],{"class":7976},[3158,13405,8029],{"class":7979},[3158,13407,7983],{"class":7976},[3158,13409,13410,13412,13414,13416,13419],{"class":3160,"line":3274},[3158,13411,4345],{"class":3175},[3158,13413,4349],{"class":4348},[3158,13415,3176],{"class":3175},[3158,13417,13418],{"class":4354},"\"{id:int}/image\"",[3158,13420,4358],{"class":3175},[3158,13422,13423,13425,13427,13429,13432,13434,13437],{"class":3160,"line":3279},[3158,13424,4345],{"class":3175},[3158,13426,7841],{"class":4348},[3158,13428,3176],{"class":3175},[3158,13430,13431],{"class":4354},"\"image/jpeg\"",[3158,13433,3132],{"class":3175},[3158,13435,13436],{"class":4354},"\"image/png\"",[3158,13438,4358],{"class":3175},[3158,13440,13441,13443,13445,13447,13449,13451,13453,13455,13457,13459,13461],{"class":3160,"line":3285},[3158,13442,4345],{"class":3175},[3158,13444,8065],{"class":4348},[3158,13446,3176],{"class":3175},[3158,13448,8070],{"class":4363},[3158,13450,3176],{"class":3175},[3158,13452,4317],{"class":4348},[3158,13454,8424],{"class":3175},[3158,13456,8086],{"class":3179},[3158,13458,3029],{"class":3175},[3158,13460,8091],{"class":3179},[3158,13462,4358],{"class":3175},[3158,13464,13465,13467,13469,13471,13473,13475,13477,13479,13481,13483,13485],{"class":3160,"line":3305},[3158,13466,4345],{"class":3175},[3158,13468,8065],{"class":4348},[3158,13470,3176],{"class":3175},[3158,13472,8070],{"class":4363},[3158,13474,3176],{"class":3175},[3158,13476,8447],{"class":4348},[3158,13478,8424],{"class":3175},[3158,13480,8086],{"class":3179},[3158,13482,3029],{"class":3175},[3158,13484,8456],{"class":3179},[3158,13486,4358],{"class":3175},[3158,13488,13489,13491,13493,13495,13497,13499,13501,13504,13506,13508,13510],{"class":3160,"line":3310},[3158,13490,4364],{"class":4363},[3158,13492,4367],{"class":4363},[3158,13494,4370],{"class":4348},[3158,13496,4373],{"class":3175},[3158,13498,3094],{"class":4348},[3158,13500,4378],{"class":3175},[3158,13502,13503],{"class":3171},"GetProductImage",[3158,13505,3176],{"class":3175},[3158,13507,4386],{"class":4363},[3158,13509,4389],{"class":3179},[3158,13511,3527],{"class":3175},[3158,13513,13514],{"class":3160,"line":3316},[3158,13515,4396],{"class":3175},[3158,13517,13518,13520,13522,13524,13526,13528,13530,13532,13534,13536,13538,13540],{"class":3160,"line":3443},[3158,13519,4401],{"class":4363},[3158,13521,4404],{"class":3179},[3158,13523,4407],{"class":3175},[3158,13525,4410],{"class":4363},[3158,13527,4413],{"class":3179},[3158,13529,3029],{"class":3175},[3158,13531,4418],{"class":3179},[3158,13533,3029],{"class":3175},[3158,13535,4423],{"class":3171},[3158,13537,3176],{"class":3175},[3158,13539,4428],{"class":3179},[3158,13541,4431],{"class":3175},[3158,13543,13544],{"class":3160,"line":3458},[3158,13545,3884],{"class":3175},[3158,13547,13548,13550,13552,13554,13556,13558],{"class":3160,"line":3463},[3158,13549,4441],{"class":4440},[3158,13551,4444],{"class":3175},[3158,13553,4447],{"class":3179},[3158,13555,4450],{"class":4363},[3158,13557,4453],{"class":4363},[3158,13559,3527],{"class":3175},[3158,13561,13562],{"class":3160,"line":3469},[3158,13563,6477],{"class":3175},[3158,13565,13566,13568,13570,13572,13574],{"class":3160,"line":3480},[3158,13567,4460],{"class":4440},[3158,13569,4463],{"class":3171},[3158,13571,3176],{"class":3175},[3158,13573,7281],{"class":4363},[3158,13575,8597],{"class":4348},[3158,13577,13578],{"class":3160,"line":3495},[3158,13579,6573],{"class":3175},[3158,13581,13582,13585,13587,13589],{"class":3160,"line":3500},[3158,13583,13584],{"class":3179},"            Title",[3158,13586,4407],{"class":3175},[3158,13588,8612],{"class":4354},[3158,13590,6786],{"class":3175},[3158,13592,13593,13596,13598,13600,13602,13604,13606,13608],{"class":3160,"line":3506},[3158,13594,13595],{"class":3179},"            Detail",[3158,13597,4407],{"class":3175},[3158,13599,8624],{"class":4354},[3158,13601,7352],{"class":7351},[3158,13603,4428],{"class":3179},[3158,13605,7383],{"class":7351},[3158,13607,8633],{"class":4354},[3158,13609,6786],{"class":3175},[3158,13611,13612,13615,13617,13619,13621],{"class":3160,"line":3518},[3158,13613,13614],{"class":3179},"            Status",[3158,13616,4407],{"class":3175},[3158,13618,8086],{"class":3179},[3158,13620,3029],{"class":3175},[3158,13622,9884],{"class":3179},[3158,13624,13625],{"class":3160,"line":3959},[3158,13626,7083],{"class":3175},[3158,13628,13629],{"class":3160,"line":3965},[3158,13630,3879],{"class":3175},[3158,13632,13633],{"class":3160,"line":3971},[3158,13634,3884],{"class":3175},[3158,13636,13637],{"class":3160,"line":3976},[3158,13638,13639],{"class":3164},"    // Шлях до зображення (у реальному проєкті зберігайте в БД)\n",[3158,13641,13642,13644,13647,13649,13651,13653,13655],{"class":3160,"line":3981},[3158,13643,4401],{"class":4363},[3158,13645,13646],{"class":3179}," imagePath",[3158,13648,4407],{"class":3175},[3158,13650,7400],{"class":3179},[3158,13652,3029],{"class":3175},[3158,13654,7405],{"class":3171},[3158,13656,6732],{"class":3175},[3158,13658,13659,13662,13664,13667],{"class":3160,"line":3987},[3158,13660,13661],{"class":3179},"        Directory",[3158,13663,3029],{"class":3175},[3158,13665,13666],{"class":3171},"GetCurrentDirectory",[3158,13668,13669],{"class":3175},"(), \n",[3158,13671,13672,13675],{"class":3160,"line":3993},[3158,13673,13674],{"class":4354},"        \"wwwroot\"",[3158,13676,6761],{"class":3175},[3158,13678,13679,13682],{"class":3160,"line":3998},[3158,13680,13681],{"class":4354},"        \"images\"",[3158,13683,6761],{"class":3175},[3158,13685,13686,13689],{"class":3160,"line":4003},[3158,13687,13688],{"class":4354},"        \"products\"",[3158,13690,6761],{"class":3175},[3158,13692,13693,13696,13698,13700,13702],{"class":3160,"line":4009},[3158,13694,13695],{"class":4354},"        $\"",[3158,13697,7352],{"class":7351},[3158,13699,4428],{"class":3179},[3158,13701,7383],{"class":7351},[3158,13703,13704],{"class":4354},".jpg\"\n",[3158,13706,13707],{"class":3160,"line":4015},[3158,13708,12767],{"class":3175},[3158,13710,13711],{"class":3160,"line":4021},[3158,13712,3884],{"class":3175},[3158,13714,13715,13717,13720,13722,13724,13727,13729,13731,13733,13735,13737,13740],{"class":3160,"line":4026},[3158,13716,4441],{"class":4440},[3158,13718,13719],{"class":3175}," (!",[3158,13721,7355],{"class":3179},[3158,13723,3029],{"class":3175},[3158,13725,13726],{"class":3179},"IO",[3158,13728,3029],{"class":3175},[3158,13730,3628],{"class":3179},[3158,13732,3029],{"class":3175},[3158,13734,7435],{"class":3171},[3158,13736,3176],{"class":3175},[3158,13738,13739],{"class":3179},"imagePath",[3158,13741,7443],{"class":3175},[3158,13743,13744],{"class":3160,"line":4031},[3158,13745,6477],{"class":3175},[3158,13747,13748],{"class":3160,"line":4037},[3158,13749,13750],{"class":3164},"        // Повертаємо placeholder зображення\n",[3158,13752,13753,13756,13758,13760,13762,13764],{"class":3160,"line":4043},[3158,13754,13755],{"class":3179},"        imagePath",[3158,13757,4407],{"class":3175},[3158,13759,7400],{"class":3179},[3158,13761,3029],{"class":3175},[3158,13763,7405],{"class":3171},[3158,13765,6732],{"class":3175},[3158,13767,13768,13771,13773,13775],{"class":3160,"line":4048},[3158,13769,13770],{"class":3179},"            Directory",[3158,13772,3029],{"class":3175},[3158,13774,13666],{"class":3171},[3158,13776,13669],{"class":3175},[3158,13778,13779,13782],{"class":3160,"line":4053},[3158,13780,13781],{"class":4354},"            \"wwwroot\"",[3158,13783,6761],{"class":3175},[3158,13785,13786,13789],{"class":3160,"line":4059},[3158,13787,13788],{"class":4354},"            \"images\"",[3158,13790,6761],{"class":3175},[3158,13792,13793],{"class":3160,"line":4065},[3158,13794,13795],{"class":4354},"            \"placeholder.jpg\"\n",[3158,13797,13798],{"class":3160,"line":4070},[3158,13799,9479],{"class":3175},[3158,13801,13802],{"class":3160,"line":4075},[3158,13803,3879],{"class":3175},[3158,13805,13806],{"class":3160,"line":4081},[3158,13807,3884],{"class":3175},[3158,13809,13810],{"class":3160,"line":4087},[3158,13811,13812],{"class":3164},"    // PhysicalFile() для файлів з файлової системи\n",[3158,13814,13815,13817,13820,13822,13824,13826,13828],{"class":3160,"line":4092},[3158,13816,4478],{"class":4440},[3158,13818,13819],{"class":3171}," PhysicalFile",[3158,13821,3176],{"class":3175},[3158,13823,13739],{"class":3179},[3158,13825,3132],{"class":3175},[3158,13827,13431],{"class":4354},[3158,13829,4431],{"class":3175},[3158,13831,13832],{"class":3160,"line":4097},[3158,13833,4496],{"class":3175},[3038,13835,13837],{"id":13836},"приклад-4-стрімінг-великого-файлу","Приклад 4: Стрімінг великого файлу",[2964,13839,13840,13841,13843],{},"Для великих файлів (>100 MB) використовуйте ",[3088,13842,12213],{},", щоб не завантажувати весь файл у пам'ять:",[3149,13845,13847],{"className":3151,"code":13846,"language":3153,"meta":3154,"style":3154},"/// \u003Csummary>\n/// Завантажити великий файл (стрімінг)\n/// \u003C/summary>\n/// \u003Creturns>Файл\u003C/returns>\n[HttpGet(\"download/large-file\")]\n[Produces(\"application/octet-stream\")]\npublic IActionResult DownloadLargeFile()\n{\n    var filePath = Path.Combine(\n        Directory.GetCurrentDirectory(), \n        \"Data\", \n        \"large-export.zip\"\n    );\n    \n    // FileStream відкривається і читається по частинах\n    var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);\n    \n    return File(stream, \"application/octet-stream\", \"export.zip\");\n}\n",[3088,13848,13849,13859,13864,13874,13893,13906,13919,13931,13935,13952,13962,13969,13974,13978,13982,13987,14028,14032,14053],{"__ignoreMap":3154},[3158,13850,13851,13853,13855,13857],{"class":3160,"line":3161},[3158,13852,12253],{"class":3164},[3158,13854,4373],{"class":7976},[3158,13856,7980],{"class":7979},[3158,13858,7983],{"class":7976},[3158,13860,13861],{"class":3160,"line":3168},[3158,13862,13863],{"class":3164},"/// Завантажити великий файл (стрімінг)\n",[3158,13865,13866,13868,13870,13872],{"class":3160,"line":3189},[3158,13867,12253],{"class":3164},[3158,13869,7995],{"class":7976},[3158,13871,7980],{"class":7979},[3158,13873,7983],{"class":7976},[3158,13875,13876,13878,13880,13882,13884,13887,13889,13891],{"class":3160,"line":3196},[3158,13877,12253],{"class":3164},[3158,13879,4373],{"class":7976},[3158,13881,8008],{"class":7979},[3158,13883,8011],{"class":7976},[3158,13885,13886],{"class":3164},"Файл",[3158,13888,7995],{"class":7976},[3158,13890,8008],{"class":7979},[3158,13892,7983],{"class":7976},[3158,13894,13895,13897,13899,13901,13904],{"class":3160,"line":3202},[3158,13896,4345],{"class":3175},[3158,13898,4349],{"class":4348},[3158,13900,3176],{"class":3175},[3158,13902,13903],{"class":4354},"\"download/large-file\"",[3158,13905,4358],{"class":3175},[3158,13907,13908,13910,13912,13914,13917],{"class":3160,"line":3223},[3158,13909,4345],{"class":3175},[3158,13911,7841],{"class":4348},[3158,13913,3176],{"class":3175},[3158,13915,13916],{"class":4354},"\"application/octet-stream\"",[3158,13918,4358],{"class":3175},[3158,13920,13921,13923,13926,13929],{"class":3160,"line":3249},[3158,13922,4364],{"class":4363},[3158,13924,13925],{"class":4348}," IActionResult",[3158,13927,13928],{"class":3171}," DownloadLargeFile",[3158,13930,8122],{"class":3175},[3158,13932,13933],{"class":3160,"line":3274},[3158,13934,4396],{"class":3175},[3158,13936,13937,13939,13942,13944,13946,13948,13950],{"class":3160,"line":3279},[3158,13938,4401],{"class":4363},[3158,13940,13941],{"class":3179}," filePath",[3158,13943,4407],{"class":3175},[3158,13945,7400],{"class":3179},[3158,13947,3029],{"class":3175},[3158,13949,7405],{"class":3171},[3158,13951,6732],{"class":3175},[3158,13953,13954,13956,13958,13960],{"class":3160,"line":3285},[3158,13955,13661],{"class":3179},[3158,13957,3029],{"class":3175},[3158,13959,13666],{"class":3171},[3158,13961,13669],{"class":3175},[3158,13963,13964,13967],{"class":3160,"line":3305},[3158,13965,13966],{"class":4354},"        \"Data\"",[3158,13968,6761],{"class":3175},[3158,13970,13971],{"class":3160,"line":3310},[3158,13972,13973],{"class":4354},"        \"large-export.zip\"\n",[3158,13975,13976],{"class":3160,"line":3316},[3158,13977,12767],{"class":3175},[3158,13979,13980],{"class":3160,"line":3443},[3158,13981,3884],{"class":3175},[3158,13983,13984],{"class":3160,"line":3458},[3158,13985,13986],{"class":3164},"    // FileStream відкривається і читається по частинах\n",[3158,13988,13989,13991,13994,13996,13998,14001,14003,14006,14008,14011,14013,14016,14018,14021,14023,14026],{"class":3160,"line":3463},[3158,13990,4401],{"class":4363},[3158,13992,13993],{"class":3179}," stream",[3158,13995,4407],{"class":3175},[3158,13997,7281],{"class":4363},[3158,13999,14000],{"class":4348}," FileStream",[3158,14002,3176],{"class":3175},[3158,14004,14005],{"class":3179},"filePath",[3158,14007,3132],{"class":3175},[3158,14009,14010],{"class":3179},"FileMode",[3158,14012,3029],{"class":3175},[3158,14014,14015],{"class":3179},"Open",[3158,14017,3132],{"class":3175},[3158,14019,14020],{"class":3179},"FileAccess",[3158,14022,3029],{"class":3175},[3158,14024,14025],{"class":3179},"Read",[3158,14027,4431],{"class":3175},[3158,14029,14030],{"class":3160,"line":3469},[3158,14031,3884],{"class":3175},[3158,14033,14034,14036,14038,14040,14042,14044,14046,14048,14051],{"class":3160,"line":3480},[3158,14035,4478],{"class":4440},[3158,14037,12723],{"class":3171},[3158,14039,3176],{"class":3175},[3158,14041,3652],{"class":3179},[3158,14043,3132],{"class":3175},[3158,14045,13916],{"class":4354},[3158,14047,3132],{"class":3175},[3158,14049,14050],{"class":4354},"\"export.zip\"",[3158,14052,4431],{"class":3175},[3158,14054,14055],{"class":3160,"line":3495},[3158,14056,4496],{"class":3175},[3816,14058,14059,14064],{},[2964,14060,14061],{},[2968,14062,14063],{},"Вибір методу для файлів:",[2980,14065,14066,14075,14084,14093],{},[2983,14067,14068,5183,14071,14074],{},[2968,14069,14070],{},"Малі файли (\u003C1 MB):",[3088,14072,14073],{},"File(byte[], ...)"," — найпростіше",[2983,14076,14077,5183,14080,14083],{},[2968,14078,14079],{},"Середні файли (1-10 MB):",[3088,14081,14082],{},"PhysicalFile(path, ...)"," — ефективніше",[2983,14085,14086,5183,14089,14092],{},[2968,14087,14088],{},"Великі файли (>10 MB):",[3088,14090,14091],{},"File(Stream, ...)"," — стрімінг без завантаження в пам'ять",[2983,14094,14095,5183,14098,3842,14101],{},[2968,14096,14097],{},"Динамічна генерація:",[3088,14099,14100],{},"File(MemoryStream, ...)",[3088,14102,14073],{},[3109,14104],{},[2959,14106,14108],{"id":14107},"патерни-відповідей-best-practices","Патерни відповідей: Best Practices",[2964,14110,14111,14112,14115],{},"Тепер, коли ми розглянули всі типи результатів, зведемо ",[2968,14113,14114],{},"best practices"," для типових сценаріїв.",[3038,14117,14119],{"id":14118},"патерн-1-знайти-або-404","Патерн 1: \"Знайти або 404\"",[2964,14121,14122],{},"Найпоширеніший патерн — отримання ресурсу за ID:",[3149,14124,14126],{"className":3151,"code":14125,"language":3153,"meta":3154,"style":3154},"[HttpGet(\"{id}\")]\npublic async Task\u003CActionResult\u003CProductResponseDto>> GetById(int id)\n{\n    var product = await _db.Products.FindAsync(id);\n    \n    if (product is null)\n        return NotFound(); // або NotFound(ProblemDetails)\n    \n    return MapToDto(product); // Неявна конвертація\n}\n",[3088,14127,14128,14140,14168,14172,14198,14202,14216,14227,14231,14246],{"__ignoreMap":3154},[3158,14129,14130,14132,14134,14136,14138],{"class":3160,"line":3161},[3158,14131,4345],{"class":3175},[3158,14133,4349],{"class":4348},[3158,14135,3176],{"class":3175},[3158,14137,4355],{"class":4354},[3158,14139,4358],{"class":3175},[3158,14141,14142,14144,14146,14148,14150,14152,14154,14156,14158,14160,14162,14164,14166],{"class":3160,"line":3168},[3158,14143,4364],{"class":4363},[3158,14145,4367],{"class":4363},[3158,14147,4370],{"class":4348},[3158,14149,4373],{"class":3175},[3158,14151,4292],{"class":4348},[3158,14153,4373],{"class":3175},[3158,14155,8080],{"class":4348},[3158,14157,4581],{"class":3175},[3158,14159,4381],{"class":3171},[3158,14161,3176],{"class":3175},[3158,14163,4386],{"class":4363},[3158,14165,4389],{"class":3179},[3158,14167,3527],{"class":3175},[3158,14169,14170],{"class":3160,"line":3189},[3158,14171,4396],{"class":3175},[3158,14173,14174,14176,14178,14180,14182,14184,14186,14188,14190,14192,14194,14196],{"class":3160,"line":3196},[3158,14175,4401],{"class":4363},[3158,14177,4404],{"class":3179},[3158,14179,4407],{"class":3175},[3158,14181,4410],{"class":4363},[3158,14183,4413],{"class":3179},[3158,14185,3029],{"class":3175},[3158,14187,4418],{"class":3179},[3158,14189,3029],{"class":3175},[3158,14191,4423],{"class":3171},[3158,14193,3176],{"class":3175},[3158,14195,4428],{"class":3179},[3158,14197,4431],{"class":3175},[3158,14199,14200],{"class":3160,"line":3202},[3158,14201,3884],{"class":3175},[3158,14203,14204,14206,14208,14210,14212,14214],{"class":3160,"line":3223},[3158,14205,4441],{"class":4440},[3158,14207,4444],{"class":3175},[3158,14209,4447],{"class":3179},[3158,14211,4450],{"class":4363},[3158,14213,4453],{"class":4363},[3158,14215,3527],{"class":3175},[3158,14217,14218,14220,14222,14224],{"class":3160,"line":3249},[3158,14219,4460],{"class":4440},[3158,14221,4463],{"class":3171},[3158,14223,4466],{"class":3175},[3158,14225,14226],{"class":3164},"// або NotFound(ProblemDetails)\n",[3158,14228,14229],{"class":3160,"line":3274},[3158,14230,3884],{"class":3175},[3158,14232,14233,14235,14237,14239,14241,14243],{"class":3160,"line":3279},[3158,14234,4478],{"class":4440},[3158,14236,8696],{"class":3171},[3158,14238,3176],{"class":3175},[3158,14240,4447],{"class":3179},[3158,14242,4981],{"class":3175},[3158,14244,14245],{"class":3164},"// Неявна конвертація\n",[3158,14247,14248],{"class":3160,"line":3285},[3158,14249,4496],{"class":3175},[2964,14251,14252],{},[2968,14253,14254],{},"Ключові моменти:",[2980,14256,14257,14263,14269],{},[2983,14258,14259,14260,14262],{},"Використовуйте ",[3088,14261,3090],{}," для type safety",[2983,14264,14265,14268],{},[3088,14266,14267],{},"NotFound()"," для відсутніх ресурсів",[2983,14270,14271],{},"Неявна конвертація для успішної відповіді",[3038,14273,14275],{"id":14274},"патерн-2-створити-з-location-header","Патерн 2: \"Створити з Location header\"",[2964,14277,14278],{},"Створення нового ресурсу з поверненням URI:",[3149,14280,14282],{"className":3151,"code":14281,"language":3153,"meta":3154,"style":3154},"[HttpPost]\npublic async Task\u003CActionResult\u003CProductResponseDto>> Create(CreateProductDto dto)\n{\n    var product = new Product { /* ... */ };\n    _db.Products.Add(product);\n    await _db.SaveChangesAsync();\n    \n    return CreatedAtAction(\n        nameof(GetById),           // Назва action для генерації URI\n        new { id = product.Id },   // Route values\n        MapToDto(product)          // Тіло відповіді\n    );\n}\n",[3088,14283,14284,14292,14320,14324,14344,14363,14376,14380,14388,14403,14426,14440,14444],{"__ignoreMap":3154},[3158,14285,14286,14288,14290],{"class":3160,"line":3161},[3158,14287,4345],{"class":3175},[3158,14289,8872],{"class":4348},[3158,14291,5341],{"class":3175},[3158,14293,14294,14296,14298,14300,14302,14304,14306,14308,14310,14312,14314,14316,14318],{"class":3160,"line":3168},[3158,14295,4364],{"class":4363},[3158,14297,4367],{"class":4363},[3158,14299,4370],{"class":4348},[3158,14301,4373],{"class":3175},[3158,14303,4292],{"class":4348},[3158,14305,4373],{"class":3175},[3158,14307,8080],{"class":4348},[3158,14309,4581],{"class":3175},[3158,14311,8975],{"class":3171},[3158,14313,3176],{"class":3175},[3158,14315,8980],{"class":4348},[3158,14317,8983],{"class":3179},[3158,14319,3527],{"class":3175},[3158,14321,14322],{"class":3160,"line":3189},[3158,14323,4396],{"class":3175},[3158,14325,14326,14328,14330,14332,14334,14336,14338,14341],{"class":3160,"line":3196},[3158,14327,4401],{"class":4363},[3158,14329,4404],{"class":3179},[3158,14331,4407],{"class":3175},[3158,14333,7281],{"class":4363},[3158,14335,6740],{"class":4348},[3158,14337,5315],{"class":3175},[3158,14339,14340],{"class":3164},"/* ... */",[3158,14342,14343],{"class":3175}," };\n",[3158,14345,14346,14349,14351,14353,14355,14357,14359,14361],{"class":3160,"line":3202},[3158,14347,14348],{"class":3179},"    _db",[3158,14350,3029],{"class":3175},[3158,14352,4418],{"class":3179},[3158,14354,3029],{"class":3175},[3158,14356,9369],{"class":3171},[3158,14358,3176],{"class":3175},[3158,14360,4447],{"class":3179},[3158,14362,4431],{"class":3175},[3158,14364,14365,14368,14370,14372,14374],{"class":3160,"line":3223},[3158,14366,14367],{"class":4363},"    await",[3158,14369,4413],{"class":3179},[3158,14371,3029],{"class":3175},[3158,14373,9388],{"class":3171},[3158,14375,4968],{"class":3175},[3158,14377,14378],{"class":3160,"line":3249},[3158,14379,3884],{"class":3175},[3158,14381,14382,14384,14386],{"class":3160,"line":3274},[3158,14383,4478],{"class":4440},[3158,14385,9431],{"class":3171},[3158,14387,6732],{"class":3175},[3158,14389,14390,14393,14395,14397,14400],{"class":3160,"line":3279},[3158,14391,14392],{"class":4363},"        nameof",[3158,14394,3176],{"class":3175},[3158,14396,4381],{"class":3179},[3158,14398,14399],{"class":3175},"),           ",[3158,14401,14402],{"class":3164},"// Назва action для генерації URI\n",[3158,14404,14405,14408,14410,14412,14414,14416,14418,14420,14423],{"class":3160,"line":3285},[3158,14406,14407],{"class":4363},"        new",[3158,14409,5315],{"class":3175},[3158,14411,4428],{"class":3179},[3158,14413,4407],{"class":3175},[3158,14415,4447],{"class":3179},[3158,14417,3029],{"class":3175},[3158,14419,6597],{"class":3179},[3158,14421,14422],{"class":3175}," },   ",[3158,14424,14425],{"class":3164},"// Route values\n",[3158,14427,14428,14431,14433,14435,14437],{"class":3160,"line":3305},[3158,14429,14430],{"class":3171},"        MapToDto",[3158,14432,3176],{"class":3175},[3158,14434,4447],{"class":3179},[3158,14436,3217],{"class":3175},[3158,14438,14439],{"class":3164},"// Тіло відповіді\n",[3158,14441,14442],{"class":3160,"line":3310},[3158,14443,12767],{"class":3175},[3158,14445,14446],{"class":3160,"line":3316},[3158,14447,4496],{"class":3175},[2964,14449,14450],{},[2968,14451,14452],{},"Результат:",[3149,14454,14458],{"className":14455,"code":14456,"language":14457,"meta":3154,"style":3154},"language-http shiki shiki-themes light-plus dark-plus dark-plus","HTTP/1.1 201 Created\nLocation: https://api.example.com/api/products/42\nContent-Type: application/json\n\n{\n  \"id\": 42,\n  \"name\": \"New Product\",\n  ...\n}\n","http",[3088,14459,14460,14465,14470,14475,14479,14483,14488,14493,14498],{"__ignoreMap":3154},[3158,14461,14462],{"class":3160,"line":3161},[3158,14463,14464],{},"HTTP/1.1 201 Created\n",[3158,14466,14467],{"class":3160,"line":3168},[3158,14468,14469],{},"Location: https://api.example.com/api/products/42\n",[3158,14471,14472],{"class":3160,"line":3189},[3158,14473,14474],{},"Content-Type: application/json\n",[3158,14476,14477],{"class":3160,"line":3196},[3158,14478,3193],{"emptyLinePlaceholder":3192},[3158,14480,14481],{"class":3160,"line":3202},[3158,14482,4396],{},[3158,14484,14485],{"class":3160,"line":3223},[3158,14486,14487],{},"  \"id\": 42,\n",[3158,14489,14490],{"class":3160,"line":3249},[3158,14491,14492],{},"  \"name\": \"New Product\",\n",[3158,14494,14495],{"class":3160,"line":3274},[3158,14496,14497],{},"  ...\n",[3158,14499,14500],{"class":3160,"line":3279},[3158,14501,4496],{},[3038,14503,14505],{"id":14504},"патерн-3-оновити-без-повернення-даних","Патерн 3: \"Оновити без повернення даних\"",[2964,14507,14508],{},"Для операцій, де клієнту не потрібні оновлені дані:",[3149,14510,14512],{"className":3151,"code":14511,"language":3153,"meta":3154,"style":3154},"[HttpPatch(\"{id}/stock\")]\npublic async Task\u003CIActionResult> UpdateStock(int id, [FromQuery] int quantity)\n{\n    var product = await _db.Products.FindAsync(id);\n    if (product is null) return NotFound();\n    \n    product.Stock = quantity;\n    await _db.SaveChangesAsync();\n    \n    return NoContent(); // 204 - успішно, без тіла\n}\n",[3088,14513,14514,14527,14561,14565,14591,14611,14615,14630,14642,14646,14657],{"__ignoreMap":3154},[3158,14515,14516,14518,14520,14522,14525],{"class":3160,"line":3161},[3158,14517,4345],{"class":3175},[3158,14519,11430],{"class":4348},[3158,14521,3176],{"class":3175},[3158,14523,14524],{"class":4354},"\"{id}/stock\"",[3158,14526,4358],{"class":3175},[3158,14528,14529,14531,14533,14535,14537,14539,14541,14543,14545,14547,14549,14551,14553,14555,14557,14559],{"class":3160,"line":3168},[3158,14530,4364],{"class":4363},[3158,14532,4367],{"class":4363},[3158,14534,4370],{"class":4348},[3158,14536,4373],{"class":3175},[3158,14538,3094],{"class":4348},[3158,14540,4378],{"class":3175},[3158,14542,11522],{"class":3171},[3158,14544,3176],{"class":3175},[3158,14546,4386],{"class":4363},[3158,14548,4389],{"class":3179},[3158,14550,11531],{"class":3175},[3158,14552,11534],{"class":4348},[3158,14554,11537],{"class":3175},[3158,14556,4386],{"class":4363},[3158,14558,11542],{"class":3179},[3158,14560,3527],{"class":3175},[3158,14562,14563],{"class":3160,"line":3189},[3158,14564,4396],{"class":3175},[3158,14566,14567,14569,14571,14573,14575,14577,14579,14581,14583,14585,14587,14589],{"class":3160,"line":3196},[3158,14568,4401],{"class":4363},[3158,14570,4404],{"class":3179},[3158,14572,4407],{"class":3175},[3158,14574,4410],{"class":4363},[3158,14576,4413],{"class":3179},[3158,14578,3029],{"class":3175},[3158,14580,4418],{"class":3179},[3158,14582,3029],{"class":3175},[3158,14584,4423],{"class":3171},[3158,14586,3176],{"class":3175},[3158,14588,4428],{"class":3179},[3158,14590,4431],{"class":3175},[3158,14592,14593,14595,14597,14599,14601,14603,14605,14607,14609],{"class":3160,"line":3202},[3158,14594,4441],{"class":4440},[3158,14596,4444],{"class":3175},[3158,14598,4447],{"class":3179},[3158,14600,4450],{"class":4363},[3158,14602,4453],{"class":4363},[3158,14604,4960],{"class":3175},[3158,14606,4963],{"class":4440},[3158,14608,4463],{"class":3171},[3158,14610,4968],{"class":3175},[3158,14612,14613],{"class":3160,"line":3223},[3158,14614,3884],{"class":3175},[3158,14616,14617,14620,14622,14624,14626,14628],{"class":3160,"line":3249},[3158,14618,14619],{"class":3179},"    product",[3158,14621,3029],{"class":3175},[3158,14623,6088],{"class":3179},[3158,14625,4407],{"class":3175},[3158,14627,11559],{"class":3179},[3158,14629,5264],{"class":3175},[3158,14631,14632,14634,14636,14638,14640],{"class":3160,"line":3274},[3158,14633,14367],{"class":4363},[3158,14635,4413],{"class":3179},[3158,14637,3029],{"class":3175},[3158,14639,9388],{"class":3171},[3158,14641,4968],{"class":3175},[3158,14643,14644],{"class":3160,"line":3279},[3158,14645,3884],{"class":3175},[3158,14647,14648,14650,14652,14654],{"class":3160,"line":3285},[3158,14649,4478],{"class":4440},[3158,14651,10648],{"class":3171},[3158,14653,4466],{"class":3175},[3158,14655,14656],{"class":3164},"// 204 - успішно, без тіла\n",[3158,14658,14659],{"class":3160,"line":3305},[3158,14660,4496],{"class":3175},[2964,14662,14663],{},[2968,14664,14665],{},"Коли використовувати:",[2980,14667,14668,14671,14674],{},[2983,14669,14670],{},"Операції, що не змінюють структуру ресурсу",[2983,14672,14673],{},"Клієнт не потребує оновлених даних",[2983,14675,14676],{},"Економія трафіку (особливо для мобільних додатків)",[3038,14678,14680],{"id":14679},"патерн-4-валідація-з-problemdetails","Патерн 4: \"Валідація з ProblemDetails\"",[2964,14682,14683],{},"Повернення структурованих помилок валідації:",[3149,14685,14687],{"className":3151,"code":14686,"language":3153,"meta":3154,"style":3154},"[HttpPost]\npublic async Task\u003CActionResult\u003CProductResponseDto>> Create(CreateProductDto dto)\n{\n    // [ApiController] автоматично перевіряє ModelState\n    // Але для кастомної валідації:\n    \n    if (await _db.Products.AnyAsync(p => p.Name == dto.Name))\n    {\n        return Conflict(new ProblemDetails\n        {\n            Title = \"Product already exists\",\n            Detail = $\"A product with the name '{dto.Name}' already exists\",\n            Status = StatusCodes.Status409Conflict,\n            Type = \"https://api.example.com/errors/duplicate-product\",\n            Instance = HttpContext.Request.Path\n        });\n    }\n    \n    // Створення...\n}\n",[3088,14688,14689,14697,14725,14729,14734,14739,14743,14784,14788,14800,14804,14814,14836,14850,14862,14879,14883,14887,14891,14896],{"__ignoreMap":3154},[3158,14690,14691,14693,14695],{"class":3160,"line":3161},[3158,14692,4345],{"class":3175},[3158,14694,8872],{"class":4348},[3158,14696,5341],{"class":3175},[3158,14698,14699,14701,14703,14705,14707,14709,14711,14713,14715,14717,14719,14721,14723],{"class":3160,"line":3168},[3158,14700,4364],{"class":4363},[3158,14702,4367],{"class":4363},[3158,14704,4370],{"class":4348},[3158,14706,4373],{"class":3175},[3158,14708,4292],{"class":4348},[3158,14710,4373],{"class":3175},[3158,14712,8080],{"class":4348},[3158,14714,4581],{"class":3175},[3158,14716,8975],{"class":3171},[3158,14718,3176],{"class":3175},[3158,14720,8980],{"class":4348},[3158,14722,8983],{"class":3179},[3158,14724,3527],{"class":3175},[3158,14726,14727],{"class":3160,"line":3189},[3158,14728,4396],{"class":3175},[3158,14730,14731],{"class":3160,"line":3196},[3158,14732,14733],{"class":3164},"    // [ApiController] автоматично перевіряє ModelState\n",[3158,14735,14736],{"class":3160,"line":3202},[3158,14737,14738],{"class":3164},"    // Але для кастомної валідації:\n",[3158,14740,14741],{"class":3160,"line":3223},[3158,14742,3884],{"class":3175},[3158,14744,14745,14747,14749,14751,14753,14755,14757,14759,14762,14764,14766,14768,14770,14772,14774,14776,14778,14780,14782],{"class":3160,"line":3249},[3158,14746,4441],{"class":4440},[3158,14748,4444],{"class":3175},[3158,14750,4410],{"class":4363},[3158,14752,4413],{"class":3179},[3158,14754,3029],{"class":3175},[3158,14756,4418],{"class":3179},[3158,14758,3029],{"class":3175},[3158,14760,14761],{"class":3171},"AnyAsync",[3158,14763,3176],{"class":3175},[3158,14765,2964],{"class":3179},[3158,14767,6503],{"class":3175},[3158,14769,2964],{"class":3179},[3158,14771,3029],{"class":3175},[3158,14773,5966],{"class":3179},[3158,14775,9067],{"class":3175},[3158,14777,9009],{"class":3179},[3158,14779,3029],{"class":3175},[3158,14781,5966],{"class":3179},[3158,14783,7443],{"class":3175},[3158,14785,14786],{"class":3160,"line":3274},[3158,14787,6477],{"class":3175},[3158,14789,14790,14792,14794,14796,14798],{"class":3160,"line":3279},[3158,14791,4460],{"class":4440},[3158,14793,9136],{"class":3171},[3158,14795,3176],{"class":3175},[3158,14797,7281],{"class":4363},[3158,14799,8597],{"class":4348},[3158,14801,14802],{"class":3160,"line":3285},[3158,14803,6573],{"class":3175},[3158,14805,14806,14808,14810,14812],{"class":3160,"line":3305},[3158,14807,13584],{"class":3179},[3158,14809,4407],{"class":3175},[3158,14811,9157],{"class":4354},[3158,14813,6786],{"class":3175},[3158,14815,14816,14818,14820,14822,14824,14826,14828,14830,14832,14834],{"class":3160,"line":3310},[3158,14817,13595],{"class":3179},[3158,14819,4407],{"class":3175},[3158,14821,9169],{"class":4354},[3158,14823,7352],{"class":7351},[3158,14825,9009],{"class":3179},[3158,14827,3029],{"class":7351},[3158,14829,5966],{"class":3179},[3158,14831,7383],{"class":7351},[3158,14833,9182],{"class":4354},[3158,14835,6786],{"class":3175},[3158,14837,14838,14840,14842,14844,14846,14848],{"class":3160,"line":3316},[3158,14839,13614],{"class":3179},[3158,14841,4407],{"class":3175},[3158,14843,8086],{"class":3179},[3158,14845,3029],{"class":3175},[3158,14847,8951],{"class":3179},[3158,14849,6786],{"class":3175},[3158,14851,14852,14855,14857,14860],{"class":3160,"line":3443},[3158,14853,14854],{"class":3179},"            Type",[3158,14856,4407],{"class":3175},[3158,14858,14859],{"class":4354},"\"https://api.example.com/errors/duplicate-product\"",[3158,14861,6786],{"class":3175},[3158,14863,14864,14867,14869,14871,14873,14875,14877],{"class":3160,"line":3458},[3158,14865,14866],{"class":3179},"            Instance",[3158,14868,4407],{"class":3175},[3158,14870,8660],{"class":3179},[3158,14872,3029],{"class":3175},[3158,14874,8665],{"class":3179},[3158,14876,3029],{"class":3175},[3158,14878,8670],{"class":3179},[3158,14880,14881],{"class":3160,"line":3463},[3158,14882,7083],{"class":3175},[3158,14884,14885],{"class":3160,"line":3469},[3158,14886,3879],{"class":3175},[3158,14888,14889],{"class":3160,"line":3480},[3158,14890,3884],{"class":3175},[3158,14892,14893],{"class":3160,"line":3495},[3158,14894,14895],{"class":3164},"    // Створення...\n",[3158,14897,14898],{"class":3160,"line":3500},[3158,14899,4496],{"class":3175},[2964,14901,14902],{},[2968,14903,14904],{},"Структура ProblemDetails:",[3149,14906,14910],{"className":14907,"code":14908,"language":14909,"meta":3154,"style":3154},"language-json shiki shiki-themes light-plus dark-plus dark-plus","{\n  \"type\": \"https://api.example.com/errors/duplicate-product\",\n  \"title\": \"Product already exists\",\n  \"status\": 409,\n  \"detail\": \"A product with the name 'Laptop' already exists\",\n  \"instance\": \"/api/products\"\n}\n","json",[3088,14911,14912,14916,14929,14940,14952,14964,14974],{"__ignoreMap":3154},[3158,14913,14914],{"class":3160,"line":3161},[3158,14915,4396],{"class":3175},[3158,14917,14918,14922,14925,14927],{"class":3160,"line":3168},[3158,14919,14921],{"class":14920},"sLwNe","  \"type\"",[3158,14923,14924],{"class":3175},": ",[3158,14926,14859],{"class":4354},[3158,14928,6786],{"class":3175},[3158,14930,14931,14934,14936,14938],{"class":3160,"line":3189},[3158,14932,14933],{"class":14920},"  \"title\"",[3158,14935,14924],{"class":3175},[3158,14937,9157],{"class":4354},[3158,14939,6786],{"class":3175},[3158,14941,14942,14945,14947,14950],{"class":3160,"line":3196},[3158,14943,14944],{"class":14920},"  \"status\"",[3158,14946,14924],{"class":3175},[3158,14948,14949],{"class":3551},"409",[3158,14951,6786],{"class":3175},[3158,14953,14954,14957,14959,14962],{"class":3160,"line":3202},[3158,14955,14956],{"class":14920},"  \"detail\"",[3158,14958,14924],{"class":3175},[3158,14960,14961],{"class":4354},"\"A product with the name 'Laptop' already exists\"",[3158,14963,6786],{"class":3175},[3158,14965,14966,14969,14971],{"class":3160,"line":3223},[3158,14967,14968],{"class":14920},"  \"instance\"",[3158,14970,14924],{"class":3175},[3158,14972,14973],{"class":4354},"\"/api/products\"\n",[3158,14975,14976],{"class":3160,"line":3249},[3158,14977,4496],{"class":3175},[3038,14979,14981],{"id":14980},"патерн-5-умовне-повернення","Патерн 5: \"Умовне повернення\"",[2964,14983,14984],{},"Різні типи відповідей залежно від умов:",[3149,14986,14988],{"className":3151,"code":14987,"language":3153,"meta":3154,"style":3154},"[HttpGet(\"{id}/details\")]\npublic async Task\u003CIActionResult> GetDetails(int id, [FromQuery] string format = \"json\")\n{\n    var product = await _db.Products.FindAsync(id);\n    if (product is null) return NotFound();\n    \n    return format.ToLower() switch\n    {\n        \"json\" => Ok(MapToDto(product)),\n        \"xml\" => Ok(MapToDto(product)), // Content negotiation обробить\n        \"pdf\" => File(GeneratePdf(product), \"application/pdf\"),\n        \"csv\" => File(GenerateCsv(product), \"text/csv\"),\n        _ => BadRequest(new { message = \"Unsupported format\" })\n    };\n}\n",[3088,14989,14990,15003,15045,15049,15075,15095,15099,15116,15120,15140,15163,15187,15211,15236,15240],{"__ignoreMap":3154},[3158,14991,14992,14994,14996,14998,15001],{"class":3160,"line":3161},[3158,14993,4345],{"class":3175},[3158,14995,4349],{"class":4348},[3158,14997,3176],{"class":3175},[3158,14999,15000],{"class":4354},"\"{id}/details\"",[3158,15002,4358],{"class":3175},[3158,15004,15005,15007,15009,15011,15013,15015,15017,15020,15022,15024,15026,15028,15030,15032,15035,15038,15040,15043],{"class":3160,"line":3168},[3158,15006,4364],{"class":4363},[3158,15008,4367],{"class":4363},[3158,15010,4370],{"class":4348},[3158,15012,4373],{"class":3175},[3158,15014,3094],{"class":4348},[3158,15016,4378],{"class":3175},[3158,15018,15019],{"class":3171},"GetDetails",[3158,15021,3176],{"class":3175},[3158,15023,4386],{"class":4363},[3158,15025,4389],{"class":3179},[3158,15027,11531],{"class":3175},[3158,15029,11534],{"class":4348},[3158,15031,11537],{"class":3175},[3158,15033,15034],{"class":4363},"string",[3158,15036,15037],{"class":3179}," format",[3158,15039,4407],{"class":3175},[3158,15041,15042],{"class":4354},"\"json\"",[3158,15044,3527],{"class":3175},[3158,15046,15047],{"class":3160,"line":3189},[3158,15048,4396],{"class":3175},[3158,15050,15051,15053,15055,15057,15059,15061,15063,15065,15067,15069,15071,15073],{"class":3160,"line":3196},[3158,15052,4401],{"class":4363},[3158,15054,4404],{"class":3179},[3158,15056,4407],{"class":3175},[3158,15058,4410],{"class":4363},[3158,15060,4413],{"class":3179},[3158,15062,3029],{"class":3175},[3158,15064,4418],{"class":3179},[3158,15066,3029],{"class":3175},[3158,15068,4423],{"class":3171},[3158,15070,3176],{"class":3175},[3158,15072,4428],{"class":3179},[3158,15074,4431],{"class":3175},[3158,15076,15077,15079,15081,15083,15085,15087,15089,15091,15093],{"class":3160,"line":3202},[3158,15078,4441],{"class":4440},[3158,15080,4444],{"class":3175},[3158,15082,4447],{"class":3179},[3158,15084,4450],{"class":4363},[3158,15086,4453],{"class":4363},[3158,15088,4960],{"class":3175},[3158,15090,4963],{"class":4440},[3158,15092,4463],{"class":3171},[3158,15094,4968],{"class":3175},[3158,15096,15097],{"class":3160,"line":3223},[3158,15098,3884],{"class":3175},[3158,15100,15101,15103,15105,15107,15110,15113],{"class":3160,"line":3249},[3158,15102,4478],{"class":4440},[3158,15104,15037],{"class":3179},[3158,15106,3029],{"class":3175},[3158,15108,15109],{"class":3171},"ToLower",[3158,15111,15112],{"class":3175},"() ",[3158,15114,15115],{"class":4440},"switch\n",[3158,15117,15118],{"class":3160,"line":3274},[3158,15119,6477],{"class":3175},[3158,15121,15122,15125,15127,15129,15131,15133,15135,15137],{"class":3160,"line":3279},[3158,15123,15124],{"class":4354},"        \"json\"",[3158,15126,6503],{"class":3175},[3158,15128,3172],{"class":3171},[3158,15130,3176],{"class":3175},[3158,15132,8245],{"class":3171},[3158,15134,3176],{"class":3175},[3158,15136,4447],{"class":3179},[3158,15138,15139],{"class":3175},")),\n",[3158,15141,15142,15145,15147,15149,15151,15153,15155,15157,15160],{"class":3160,"line":3285},[3158,15143,15144],{"class":4354},"        \"xml\"",[3158,15146,6503],{"class":3175},[3158,15148,3172],{"class":3171},[3158,15150,3176],{"class":3175},[3158,15152,8245],{"class":3171},[3158,15154,3176],{"class":3175},[3158,15156,4447],{"class":3179},[3158,15158,15159],{"class":3175},")), ",[3158,15161,15162],{"class":3164},"// Content negotiation обробить\n",[3158,15164,15165,15168,15170,15172,15174,15177,15179,15181,15183,15185],{"class":3160,"line":3305},[3158,15166,15167],{"class":4354},"        \"pdf\"",[3158,15169,6503],{"class":3175},[3158,15171,3628],{"class":3171},[3158,15173,3176],{"class":3175},[3158,15175,15176],{"class":3171},"GeneratePdf",[3158,15178,3176],{"class":3175},[3158,15180,4447],{"class":3179},[3158,15182,8424],{"class":3175},[3158,15184,12932],{"class":4354},[3158,15186,9446],{"class":3175},[3158,15188,15189,15192,15194,15196,15198,15201,15203,15205,15207,15209],{"class":3160,"line":3310},[3158,15190,15191],{"class":4354},"        \"csv\"",[3158,15193,6503],{"class":3175},[3158,15195,3628],{"class":3171},[3158,15197,3176],{"class":3175},[3158,15199,15200],{"class":3171},"GenerateCsv",[3158,15202,3176],{"class":3175},[3158,15204,4447],{"class":3179},[3158,15206,8424],{"class":3175},[3158,15208,12342],{"class":4354},[3158,15210,9446],{"class":3175},[3158,15212,15213,15216,15218,15220,15222,15224,15226,15228,15230,15233],{"class":3160,"line":3316},[3158,15214,15215],{"class":4363},"        _",[3158,15217,6503],{"class":3175},[3158,15219,3344],{"class":3171},[3158,15221,3176],{"class":3175},[3158,15223,7281],{"class":4363},[3158,15225,5315],{"class":3175},[3158,15227,3450],{"class":3179},[3158,15229,4407],{"class":3175},[3158,15231,15232],{"class":4354},"\"Unsupported format\"",[3158,15234,15235],{"class":3175}," })\n",[3158,15237,15238],{"class":3160,"line":3443},[3158,15239,12032],{"class":3175},[3158,15241,15242],{"class":3160,"line":3458},[3158,15243,4496],{"class":3175},[3031,15245,15246,15249,15250,12089,15252,15254],{},[2968,15247,15248],{},"Про IActionResult:"," У цьому патерні ми використовуємо ",[3088,15251,3094],{},[3088,15253,3090],{},", оскільки повертаємо принципово різні типи (JSON, файл).",[3109,15256],{},[2959,15258,15260],{"id":15259},"документування-api-через-producesresponsetype","Документування API через ProducesResponseType",[2964,15262,15263,15264,15266,15267,15270],{},"Атрибут ",[3088,15265,3104],{}," — це не просто декорація. Він генерує ",[2968,15268,15269],{},"метадані OpenAPI",", що дозволяють Swagger UI та клієнтським генераторам (NSwag, OpenAPI Generator) розуміти структуру відповідей.",[3038,15272,15274],{"id":15273},"базовий-синтаксис","Базовий синтаксис",[3149,15276,15278],{"className":3151,"code":15277,"language":3153,"meta":3154,"style":3154},"[HttpGet(\"{id}\")]\n[ProducesResponseType(typeof(ProductResponseDto), StatusCodes.Status200OK)]\n[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]\npublic async Task\u003CActionResult\u003CProductResponseDto>> GetById(int id)\n{\n    // ...\n}\n",[3088,15279,15280,15292,15316,15340,15368,15372,15377],{"__ignoreMap":3154},[3158,15281,15282,15284,15286,15288,15290],{"class":3160,"line":3161},[3158,15283,4345],{"class":3175},[3158,15285,4349],{"class":4348},[3158,15287,3176],{"class":3175},[3158,15289,4355],{"class":4354},[3158,15291,4358],{"class":3175},[3158,15293,15294,15296,15298,15300,15302,15304,15306,15308,15310,15312,15314],{"class":3160,"line":3168},[3158,15295,4345],{"class":3175},[3158,15297,8065],{"class":4348},[3158,15299,3176],{"class":3175},[3158,15301,8070],{"class":4363},[3158,15303,3176],{"class":3175},[3158,15305,8080],{"class":4348},[3158,15307,8424],{"class":3175},[3158,15309,8086],{"class":3179},[3158,15311,3029],{"class":3175},[3158,15313,8091],{"class":3179},[3158,15315,4358],{"class":3175},[3158,15317,15318,15320,15322,15324,15326,15328,15330,15332,15334,15336,15338],{"class":3160,"line":3189},[3158,15319,4345],{"class":3175},[3158,15321,8065],{"class":4348},[3158,15323,3176],{"class":3175},[3158,15325,8070],{"class":4363},[3158,15327,3176],{"class":3175},[3158,15329,8447],{"class":4348},[3158,15331,8424],{"class":3175},[3158,15333,8086],{"class":3179},[3158,15335,3029],{"class":3175},[3158,15337,8456],{"class":3179},[3158,15339,4358],{"class":3175},[3158,15341,15342,15344,15346,15348,15350,15352,15354,15356,15358,15360,15362,15364,15366],{"class":3160,"line":3196},[3158,15343,4364],{"class":4363},[3158,15345,4367],{"class":4363},[3158,15347,4370],{"class":4348},[3158,15349,4373],{"class":3175},[3158,15351,4292],{"class":4348},[3158,15353,4373],{"class":3175},[3158,15355,8080],{"class":4348},[3158,15357,4581],{"class":3175},[3158,15359,4381],{"class":3171},[3158,15361,3176],{"class":3175},[3158,15363,4386],{"class":4363},[3158,15365,4389],{"class":3179},[3158,15367,3527],{"class":3175},[3158,15369,15370],{"class":3160,"line":3202},[3158,15371,4396],{"class":3175},[3158,15373,15374],{"class":3160,"line":3223},[3158,15375,15376],{"class":3164},"    // ...\n",[3158,15378,15379],{"class":3160,"line":3249},[3158,15380,4496],{"class":3175},[2964,15382,15383],{},[2968,15384,15385],{},"Що це дає:",[4273,15387,15388,15394,15400],{},[2983,15389,15390,15393],{},[2968,15391,15392],{},"Swagger UI"," показує приклади відповідей для кожного коду",[2983,15395,15396,15399],{},[2968,15397,15398],{},"Клієнтські генератори"," створюють типізовані методи",[2983,15401,15402,15405],{},[2968,15403,15404],{},"Документація"," стає самодостатньою",[3038,15407,15409],{"id":15408},"приклад-у-swagger-ui","Приклад у Swagger UI",[2964,15411,15412,15413,15415],{},"Після додавання ",[3088,15414,3104],{},", Swagger UI показує:",[3149,15417,15422],{"className":15418,"code":15420,"language":15421},[15419],"language-text","GET /api/products/{id}\n\nResponses:\n  200 - Success\n    Content-Type: application/json\n    Schema: ProductResponseDto\n    Example:\n    {\n      \"id\": 1,\n      \"name\": \"Laptop\",\n      \"price\": 1499.99,\n      ...\n    }\n  \n  404 - Not Found\n    Content-Type: application/problem+json\n    Schema: ProblemDetails\n    Example:\n    {\n      \"type\": \"https://tools.ietf.org/html/rfc9457\",\n      \"title\": \"Product not found\",\n      \"status\": 404,\n      ...\n    }\n","text",[3088,15423,15420],{"__ignoreMap":3154},[3038,15425,15427],{"id":15426},"множинні-типи-контенту","Множинні типи контенту",[2964,15429,15430],{},"Якщо endpoint повертає різні формати:",[3149,15432,15434],{"className":3151,"code":15433,"language":3153,"meta":3154,"style":3154},"[HttpGet(\"{id}\")]\n[Produces(\"application/json\", \"application/xml\")]\n[ProducesResponseType(typeof(ProductResponseDto), StatusCodes.Status200OK)]\npublic async Task\u003CActionResult\u003CProductResponseDto>> GetById(int id)\n{\n    // Content negotiation обробить Accept header\n}\n",[3088,15435,15436,15448,15465,15489,15517,15521,15526],{"__ignoreMap":3154},[3158,15437,15438,15440,15442,15444,15446],{"class":3160,"line":3161},[3158,15439,4345],{"class":3175},[3158,15441,4349],{"class":4348},[3158,15443,3176],{"class":3175},[3158,15445,4355],{"class":4354},[3158,15447,4358],{"class":3175},[3158,15449,15450,15452,15454,15456,15458,15460,15463],{"class":3160,"line":3168},[3158,15451,4345],{"class":3175},[3158,15453,7841],{"class":4348},[3158,15455,3176],{"class":3175},[3158,15457,7846],{"class":4354},[3158,15459,3132],{"class":3175},[3158,15461,15462],{"class":4354},"\"application/xml\"",[3158,15464,4358],{"class":3175},[3158,15466,15467,15469,15471,15473,15475,15477,15479,15481,15483,15485,15487],{"class":3160,"line":3189},[3158,15468,4345],{"class":3175},[3158,15470,8065],{"class":4348},[3158,15472,3176],{"class":3175},[3158,15474,8070],{"class":4363},[3158,15476,3176],{"class":3175},[3158,15478,8080],{"class":4348},[3158,15480,8424],{"class":3175},[3158,15482,8086],{"class":3179},[3158,15484,3029],{"class":3175},[3158,15486,8091],{"class":3179},[3158,15488,4358],{"class":3175},[3158,15490,15491,15493,15495,15497,15499,15501,15503,15505,15507,15509,15511,15513,15515],{"class":3160,"line":3196},[3158,15492,4364],{"class":4363},[3158,15494,4367],{"class":4363},[3158,15496,4370],{"class":4348},[3158,15498,4373],{"class":3175},[3158,15500,4292],{"class":4348},[3158,15502,4373],{"class":3175},[3158,15504,8080],{"class":4348},[3158,15506,4581],{"class":3175},[3158,15508,4381],{"class":3171},[3158,15510,3176],{"class":3175},[3158,15512,4386],{"class":4363},[3158,15514,4389],{"class":3179},[3158,15516,3527],{"class":3175},[3158,15518,15519],{"class":3160,"line":3202},[3158,15520,4396],{"class":3175},[3158,15522,15523],{"class":3160,"line":3223},[3158,15524,15525],{"class":3164},"    // Content negotiation обробить Accept header\n",[3158,15527,15528],{"class":3160,"line":3249},[3158,15529,4496],{"class":3175},[3038,15531,15533],{"id":15532},"повна-таблиця-http-кодів-та-методів-controllerbase","Повна таблиця HTTP-кодів та методів ControllerBase",[4741,15535,15536,15552],{},[4744,15537,15538],{},[4747,15539,15540,15543,15546,15549],{},[4750,15541,15542],{},"HTTP-код",[4750,15544,15545],{},"Метод ControllerBase",[4750,15547,15548],{},"Коли використовувати",[4750,15550,15551],{},"Приклад",[4758,15553,15554,15570,15586,15604,15621,15638,15656,15674,15690,15707,15725],{},[4747,15555,15556,15560,15564,15567],{},[4763,15557,15558],{},[2968,15559,2987],{},[4763,15561,15562],{},[3088,15563,3828],{},[4763,15565,15566],{},"Успішна операція з даними",[4763,15568,15569],{},"GET, PUT з поверненням даних",[4747,15571,15572,15576,15580,15583],{},[4763,15573,15574],{},[2968,15575,2993],{},[4763,15577,15578],{},[3088,15579,12076],{},[4763,15581,15582],{},"Ресурс створено",[4763,15584,15585],{},"POST",[4747,15587,15588,15593,15598,15601],{},[4763,15589,15590],{},[2968,15591,15592],{},"202 Accepted",[4763,15594,15595],{},[3088,15596,15597],{},"Accepted()",[4763,15599,15600],{},"Запит прийнято до обробки",[4763,15602,15603],{},"Асинхронні операції",[4747,15605,15606,15610,15615,15618],{},[4763,15607,15608],{},[2968,15609,2999],{},[4763,15611,15612],{},[3088,15613,15614],{},"NoContent()",[4763,15616,15617],{},"Успішно, без даних",[4763,15619,15620],{},"DELETE, PATCH без повернення",[4747,15622,15623,15627,15632,15635],{},[4763,15624,15625],{},[2968,15626,3011],{},[4763,15628,15629],{},[3088,15630,15631],{},"BadRequest()",[4763,15633,15634],{},"Невалідний запит",[4763,15636,15637],{},"Помилки валідації",[4747,15639,15640,15645,15650,15653],{},[4763,15641,15642],{},[2968,15643,15644],{},"401 Unauthorized",[4763,15646,15647],{},[3088,15648,15649],{},"Unauthorized()",[4763,15651,15652],{},"Не автентифікований",[4763,15654,15655],{},"Відсутній/невалідний токен",[4747,15657,15658,15663,15668,15671],{},[4763,15659,15660],{},[2968,15661,15662],{},"403 Forbidden",[4763,15664,15665],{},[3088,15666,15667],{},"Forbid()",[4763,15669,15670],{},"Немає прав доступу",[4763,15672,15673],{},"Недостатньо прав",[4747,15675,15676,15680,15684,15687],{},[4763,15677,15678],{},[2968,15679,3005],{},[4763,15681,15682],{},[3088,15683,14267],{},[4763,15685,15686],{},"Ресурс не знайдено",[4763,15688,15689],{},"GET за неіснуючим ID",[4747,15691,15692,15696,15701,15704],{},[4763,15693,15694],{},[2968,15695,3017],{},[4763,15697,15698],{},[3088,15699,15700],{},"Conflict()",[4763,15702,15703],{},"Конфлікт бізнес-логіки",[4763,15705,15706],{},"Дублікат, порушення правил",[4747,15708,15709,15714,15719,15722],{},[4763,15710,15711],{},[2968,15712,15713],{},"422 Unprocessable Entity",[4763,15715,15716],{},[3088,15717,15718],{},"UnprocessableEntity()",[4763,15720,15721],{},"Семантично невалідний",[4763,15723,15724],{},"Бізнес-валідація",[4747,15726,15727,15732,15737,15740],{},[4763,15728,15729],{},[2968,15730,15731],{},"500 Internal Server Error",[4763,15733,15734],{},[3088,15735,15736],{},"StatusCode(500)",[4763,15738,15739],{},"Помилка сервера",[4763,15741,15742],{},"Необроблені винятки",[3109,15744],{},[2959,15746,15748],{"id":15747},"практичні-завдання","Практичні завдання",[2964,15750,15751],{},"Закріпіть вивчений матеріал, виконавши наступні завдання.",[3038,15753,15755],{"id":15754},"рівень-1-базове-розуміння","Рівень 1: Базове розуміння",[5164,15757,15758,15762,15765,15786,15808,15812,15815,15828,15861,15865,15868,15984],{},[3038,15759,15761],{"id":15760},"завдання-11-вибір-типу-повернення","Завдання 1.1: Вибір типу повернення",[2964,15763,15764],{},"Для кожного сценарію оберіть правильний тип повернення:",[4273,15766,15767,15774,15780],{},[2983,15768,15769,15770,15773],{},"Метод ",[3088,15771,15772],{},"GetAll()"," повертає список товарів",[2983,15775,15769,15776,15779],{},[3088,15777,15778],{},"Delete()"," видаляє товар без повернення даних",[2983,15781,15769,15782,15785],{},[3088,15783,15784],{},"GetImage()"," повертає зображення або JSON-помилку",[15787,15788,15790],"collapsible",{"title":15789},"Показати відповіді",[4273,15791,15792,15798,15803],{},[2983,15793,15794,15797],{},[3088,15795,15796],{},"ActionResult\u003CIEnumerable\u003CProductResponseDto>>"," — є чіткий тип успішної відповіді",[2983,15799,15800,15802],{},[3088,15801,3094],{}," — немає даних у відповіді (204 No Content)",[2983,15804,15805,15807],{},[3088,15806,3094],{}," — повертає різні типи (файл або JSON)",[3038,15809,15811],{"id":15810},"завдання-12-правильний-http-код","Завдання 1.2: Правильний HTTP-код",[2964,15813,15814],{},"Який HTTP-код та метод використати для кожного сценарію?",[4273,15816,15817,15819,15822,15825],{},[2983,15818,8804],{},[2983,15820,15821],{},"Товар не знайдено за ID",[2983,15823,15824],{},"Спроба створити товар з дублікатом назви",[2983,15826,15827],{},"Залишок товару оновлено (без повернення даних)",[15787,15829,15830],{"title":15789},[4273,15831,15832,15839,15848,15855],{},[2983,15833,15834,12055,15836],{},[2968,15835,2993],{},[3088,15837,15838],{},"CreatedAtAction(nameof(GetById), new { id }, data)",[2983,15840,15841,12055,15843,3842,15845],{},[2968,15842,3005],{},[3088,15844,14267],{},[3088,15846,15847],{},"NotFound(ProblemDetails)",[2983,15849,15850,12055,15852],{},[2968,15851,3017],{},[3088,15853,15854],{},"Conflict(ProblemDetails)",[2983,15856,15857,12055,15859],{},[2968,15858,2999],{},[3088,15860,15614],{},[3038,15862,15864],{"id":15863},"завдання-13-виправлення-коду","Завдання 1.3: Виправлення коду",[2964,15866,15867],{},"Знайдіть та виправте помилки у коді:",[3149,15869,15871],{"className":3151,"code":15870,"language":3153,"meta":3154,"style":3154},"[HttpGet(\"{id}\")]\npublic async Task\u003CIActionResult> GetById(int id) // Помилка 1\n{\n    var product = await _db.Products.FindAsync(id);\n    if (product is null) return Ok(null); // Помилка 2\n    return product; // Помилка 3\n}\n",[3088,15872,15873,15885,15912,15916,15942,15969,15980],{"__ignoreMap":3154},[3158,15874,15875,15877,15879,15881,15883],{"class":3160,"line":3161},[3158,15876,4345],{"class":3175},[3158,15878,4349],{"class":4348},[3158,15880,3176],{"class":3175},[3158,15882,4355],{"class":4354},[3158,15884,4358],{"class":3175},[3158,15886,15887,15889,15891,15893,15895,15897,15899,15901,15903,15905,15907,15909],{"class":3160,"line":3168},[3158,15888,4364],{"class":4363},[3158,15890,4367],{"class":4363},[3158,15892,4370],{"class":4348},[3158,15894,4373],{"class":3175},[3158,15896,3094],{"class":4348},[3158,15898,4378],{"class":3175},[3158,15900,4381],{"class":3171},[3158,15902,3176],{"class":3175},[3158,15904,4386],{"class":4363},[3158,15906,4389],{"class":3179},[3158,15908,4960],{"class":3175},[3158,15910,15911],{"class":3164},"// Помилка 1\n",[3158,15913,15914],{"class":3160,"line":3189},[3158,15915,4396],{"class":3175},[3158,15917,15918,15920,15922,15924,15926,15928,15930,15932,15934,15936,15938,15940],{"class":3160,"line":3196},[3158,15919,4401],{"class":4363},[3158,15921,4404],{"class":3179},[3158,15923,4407],{"class":3175},[3158,15925,4410],{"class":4363},[3158,15927,4413],{"class":3179},[3158,15929,3029],{"class":3175},[3158,15931,4418],{"class":3179},[3158,15933,3029],{"class":3175},[3158,15935,4423],{"class":3171},[3158,15937,3176],{"class":3175},[3158,15939,4428],{"class":3179},[3158,15941,4431],{"class":3175},[3158,15943,15944,15946,15948,15950,15952,15954,15956,15958,15960,15962,15964,15966],{"class":3160,"line":3202},[3158,15945,4441],{"class":4440},[3158,15947,4444],{"class":3175},[3158,15949,4447],{"class":3179},[3158,15951,4450],{"class":4363},[3158,15953,4453],{"class":4363},[3158,15955,4960],{"class":3175},[3158,15957,4963],{"class":4440},[3158,15959,4481],{"class":3171},[3158,15961,3176],{"class":3175},[3158,15963,5127],{"class":4363},[3158,15965,4981],{"class":3175},[3158,15967,15968],{"class":3164},"// Помилка 2\n",[3158,15970,15971,15973,15975,15977],{"class":3160,"line":3223},[3158,15972,4478],{"class":4440},[3158,15974,4404],{"class":3179},[3158,15976,5097],{"class":3175},[3158,15978,15979],{"class":3164},"// Помилка 3\n",[3158,15981,15982],{"class":3160,"line":3249},[3158,15983,4496],{"class":3175},[15787,15985,15987,15992,16023,16028],{"title":15986},"Показати рішення",[2964,15988,15989],{},[2968,15990,15991],{},"Помилки:",[4273,15993,15994,16003,16010],{},[2983,15995,15996,15997,12089,15999,16002],{},"Використано ",[3088,15998,3094],{},[3088,16000,16001],{},"ActionResult\u003CProductResponseDto>"," (втрата type safety)",[2983,16004,16005,12089,16007,16009],{},[3088,16006,5145],{},[3088,16008,14267],{}," — неправильний HTTP-код",[2983,16011,16012,16013,16015,16016,16018,16019,16022],{},"Неможливо повернути ",[3088,16014,4447],{}," напряму з ",[3088,16017,3094],{}," (потрібен ",[3088,16020,16021],{},"Ok(product)",")",[2964,16024,16025],{},[2968,16026,16027],{},"Виправлений код:",[3149,16029,16031],{"className":3151,"code":16030,"language":3153,"meta":3154,"style":3154},"[HttpGet(\"{id}\")]\npublic async Task\u003CActionResult\u003CProductResponseDto>> GetById(int id)\n{\n    var product = await _db.Products.FindAsync(id);\n    if (product is null) return NotFound();\n    return MapToDto(product); // Неявна конвертація\n}\n",[3088,16032,16033,16045,16073,16077,16103,16123,16137],{"__ignoreMap":3154},[3158,16034,16035,16037,16039,16041,16043],{"class":3160,"line":3161},[3158,16036,4345],{"class":3175},[3158,16038,4349],{"class":4348},[3158,16040,3176],{"class":3175},[3158,16042,4355],{"class":4354},[3158,16044,4358],{"class":3175},[3158,16046,16047,16049,16051,16053,16055,16057,16059,16061,16063,16065,16067,16069,16071],{"class":3160,"line":3168},[3158,16048,4364],{"class":4363},[3158,16050,4367],{"class":4363},[3158,16052,4370],{"class":4348},[3158,16054,4373],{"class":3175},[3158,16056,4292],{"class":4348},[3158,16058,4373],{"class":3175},[3158,16060,8080],{"class":4348},[3158,16062,4581],{"class":3175},[3158,16064,4381],{"class":3171},[3158,16066,3176],{"class":3175},[3158,16068,4386],{"class":4363},[3158,16070,4389],{"class":3179},[3158,16072,3527],{"class":3175},[3158,16074,16075],{"class":3160,"line":3189},[3158,16076,4396],{"class":3175},[3158,16078,16079,16081,16083,16085,16087,16089,16091,16093,16095,16097,16099,16101],{"class":3160,"line":3196},[3158,16080,4401],{"class":4363},[3158,16082,4404],{"class":3179},[3158,16084,4407],{"class":3175},[3158,16086,4410],{"class":4363},[3158,16088,4413],{"class":3179},[3158,16090,3029],{"class":3175},[3158,16092,4418],{"class":3179},[3158,16094,3029],{"class":3175},[3158,16096,4423],{"class":3171},[3158,16098,3176],{"class":3175},[3158,16100,4428],{"class":3179},[3158,16102,4431],{"class":3175},[3158,16104,16105,16107,16109,16111,16113,16115,16117,16119,16121],{"class":3160,"line":3202},[3158,16106,4441],{"class":4440},[3158,16108,4444],{"class":3175},[3158,16110,4447],{"class":3179},[3158,16112,4450],{"class":4363},[3158,16114,4453],{"class":4363},[3158,16116,4960],{"class":3175},[3158,16118,4963],{"class":4440},[3158,16120,4463],{"class":3171},[3158,16122,4968],{"class":3175},[3158,16124,16125,16127,16129,16131,16133,16135],{"class":3160,"line":3223},[3158,16126,4478],{"class":4440},[3158,16128,8696],{"class":3171},[3158,16130,3176],{"class":3175},[3158,16132,4447],{"class":3179},[3158,16134,4981],{"class":3175},[3158,16136,14245],{"class":3164},[3158,16138,16139],{"class":3160,"line":3249},[3158,16140,4496],{"class":3175},[3109,16142],{},[3038,16144,16146],{"id":16145},"рівень-2-логіка-та-розширення","Рівень 2: Логіка та розширення",[5164,16148,16149,16153,16160,16177,16595,16599,16606,16612],{},[3038,16150,16152],{"id":16151},"завдання-21-метод-з-множинними-помилками","Завдання 2.1: Метод з множинними помилками",[2964,16154,16155,16156,16159],{},"Реалізуйте метод ",[3088,16157,16158],{},"ActivateProduct(int id)",", що активує деактивований товар. Можливі відповіді:",[2980,16161,16162,16167,16172],{},[2983,16163,16164,16166],{},[2968,16165,2987],{}," — товар активовано",[2983,16168,16169,16171],{},[2968,16170,3005],{}," — товар не існує",[2983,16173,16174,16176],{},[2968,16175,3017],{}," — товар вже активний",[15787,16178,16179],{"title":15986},[3149,16180,16182],{"className":3151,"code":16181,"language":3153,"meta":3154,"style":3154},"/// \u003Csummary>\n/// Активувати деактивований товар\n/// \u003C/summary>\n[HttpPost(\"{id}/activate\")]\n[ProducesResponseType(typeof(ProductResponseDto), StatusCodes.Status200OK)]\n[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]\n[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status409Conflict)]\npublic async Task\u003CActionResult\u003CProductResponseDto>> ActivateProduct(int id)\n{\n    var product = await _db.Products.FindAsync(id);\n    \n    if (product is null)\n    {\n        return NotFound(new ProblemDetails\n        {\n            Title = \"Product not found\",\n            Detail = $\"Product with ID {id} does not exist\",\n            Status = StatusCodes.Status404NotFound\n        });\n    }\n    \n    if (product.IsActive)\n    {\n        return Conflict(new ProblemDetails\n        {\n            Title = \"Product already active\",\n            Detail = $\"Product with ID {id} is already active\",\n            Status = StatusCodes.Status409Conflict\n        });\n    }\n    \n    product.IsActive = true;\n    product.UpdatedAt = DateTime.UtcNow;\n    await _db.SaveChangesAsync();\n    \n    return MapToDto(product);\n}\n",[3088,16183,16184,16194,16199,16209,16222,16246,16270,16294,16323,16327,16353,16357,16371,16375,16387,16391,16401,16419,16431,16435,16439,16443,16457,16461,16473,16477,16488,16507,16519,16523,16527,16531,16545,16563,16575,16579,16591],{"__ignoreMap":3154},[3158,16185,16186,16188,16190,16192],{"class":3160,"line":3161},[3158,16187,12253],{"class":3164},[3158,16189,4373],{"class":7976},[3158,16191,7980],{"class":7979},[3158,16193,7983],{"class":7976},[3158,16195,16196],{"class":3160,"line":3168},[3158,16197,16198],{"class":3164},"/// Активувати деактивований товар\n",[3158,16200,16201,16203,16205,16207],{"class":3160,"line":3189},[3158,16202,12253],{"class":3164},[3158,16204,7995],{"class":7976},[3158,16206,7980],{"class":7979},[3158,16208,7983],{"class":7976},[3158,16210,16211,16213,16215,16217,16220],{"class":3160,"line":3196},[3158,16212,4345],{"class":3175},[3158,16214,8872],{"class":4348},[3158,16216,3176],{"class":3175},[3158,16218,16219],{"class":4354},"\"{id}/activate\"",[3158,16221,4358],{"class":3175},[3158,16223,16224,16226,16228,16230,16232,16234,16236,16238,16240,16242,16244],{"class":3160,"line":3202},[3158,16225,4345],{"class":3175},[3158,16227,8065],{"class":4348},[3158,16229,3176],{"class":3175},[3158,16231,8070],{"class":4363},[3158,16233,3176],{"class":3175},[3158,16235,8080],{"class":4348},[3158,16237,8424],{"class":3175},[3158,16239,8086],{"class":3179},[3158,16241,3029],{"class":3175},[3158,16243,8091],{"class":3179},[3158,16245,4358],{"class":3175},[3158,16247,16248,16250,16252,16254,16256,16258,16260,16262,16264,16266,16268],{"class":3160,"line":3223},[3158,16249,4345],{"class":3175},[3158,16251,8065],{"class":4348},[3158,16253,3176],{"class":3175},[3158,16255,8070],{"class":4363},[3158,16257,3176],{"class":3175},[3158,16259,8447],{"class":4348},[3158,16261,8424],{"class":3175},[3158,16263,8086],{"class":3179},[3158,16265,3029],{"class":3175},[3158,16267,8456],{"class":3179},[3158,16269,4358],{"class":3175},[3158,16271,16272,16274,16276,16278,16280,16282,16284,16286,16288,16290,16292],{"class":3160,"line":3249},[3158,16273,4345],{"class":3175},[3158,16275,8065],{"class":4348},[3158,16277,3176],{"class":3175},[3158,16279,8070],{"class":4363},[3158,16281,3176],{"class":3175},[3158,16283,8447],{"class":4348},[3158,16285,8424],{"class":3175},[3158,16287,8086],{"class":3179},[3158,16289,3029],{"class":3175},[3158,16291,8951],{"class":3179},[3158,16293,4358],{"class":3175},[3158,16295,16296,16298,16300,16302,16304,16306,16308,16310,16312,16315,16317,16319,16321],{"class":3160,"line":3274},[3158,16297,4364],{"class":4363},[3158,16299,4367],{"class":4363},[3158,16301,4370],{"class":4348},[3158,16303,4373],{"class":3175},[3158,16305,4292],{"class":4348},[3158,16307,4373],{"class":3175},[3158,16309,8080],{"class":4348},[3158,16311,4581],{"class":3175},[3158,16313,16314],{"class":3171},"ActivateProduct",[3158,16316,3176],{"class":3175},[3158,16318,4386],{"class":4363},[3158,16320,4389],{"class":3179},[3158,16322,3527],{"class":3175},[3158,16324,16325],{"class":3160,"line":3279},[3158,16326,4396],{"class":3175},[3158,16328,16329,16331,16333,16335,16337,16339,16341,16343,16345,16347,16349,16351],{"class":3160,"line":3285},[3158,16330,4401],{"class":4363},[3158,16332,4404],{"class":3179},[3158,16334,4407],{"class":3175},[3158,16336,4410],{"class":4363},[3158,16338,4413],{"class":3179},[3158,16340,3029],{"class":3175},[3158,16342,4418],{"class":3179},[3158,16344,3029],{"class":3175},[3158,16346,4423],{"class":3171},[3158,16348,3176],{"class":3175},[3158,16350,4428],{"class":3179},[3158,16352,4431],{"class":3175},[3158,16354,16355],{"class":3160,"line":3305},[3158,16356,3884],{"class":3175},[3158,16358,16359,16361,16363,16365,16367,16369],{"class":3160,"line":3310},[3158,16360,4441],{"class":4440},[3158,16362,4444],{"class":3175},[3158,16364,4447],{"class":3179},[3158,16366,4450],{"class":4363},[3158,16368,4453],{"class":4363},[3158,16370,3527],{"class":3175},[3158,16372,16373],{"class":3160,"line":3316},[3158,16374,6477],{"class":3175},[3158,16376,16377,16379,16381,16383,16385],{"class":3160,"line":3443},[3158,16378,4460],{"class":4440},[3158,16380,4463],{"class":3171},[3158,16382,3176],{"class":3175},[3158,16384,7281],{"class":4363},[3158,16386,8597],{"class":4348},[3158,16388,16389],{"class":3160,"line":3458},[3158,16390,6573],{"class":3175},[3158,16392,16393,16395,16397,16399],{"class":3160,"line":3463},[3158,16394,13584],{"class":3179},[3158,16396,4407],{"class":3175},[3158,16398,8612],{"class":4354},[3158,16400,6786],{"class":3175},[3158,16402,16403,16405,16407,16409,16411,16413,16415,16417],{"class":3160,"line":3469},[3158,16404,13595],{"class":3179},[3158,16406,4407],{"class":3175},[3158,16408,8624],{"class":4354},[3158,16410,7352],{"class":7351},[3158,16412,4428],{"class":3179},[3158,16414,7383],{"class":7351},[3158,16416,8633],{"class":4354},[3158,16418,6786],{"class":3175},[3158,16420,16421,16423,16425,16427,16429],{"class":3160,"line":3480},[3158,16422,13614],{"class":3179},[3158,16424,4407],{"class":3175},[3158,16426,8086],{"class":3179},[3158,16428,3029],{"class":3175},[3158,16430,9884],{"class":3179},[3158,16432,16433],{"class":3160,"line":3495},[3158,16434,7083],{"class":3175},[3158,16436,16437],{"class":3160,"line":3500},[3158,16438,3879],{"class":3175},[3158,16440,16441],{"class":3160,"line":3506},[3158,16442,3884],{"class":3175},[3158,16444,16445,16447,16449,16451,16453,16455],{"class":3160,"line":3518},[3158,16446,4441],{"class":4440},[3158,16448,4444],{"class":3175},[3158,16450,4447],{"class":3179},[3158,16452,3029],{"class":3175},[3158,16454,6149],{"class":3179},[3158,16456,3527],{"class":3175},[3158,16458,16459],{"class":3160,"line":3959},[3158,16460,6477],{"class":3175},[3158,16462,16463,16465,16467,16469,16471],{"class":3160,"line":3965},[3158,16464,4460],{"class":4440},[3158,16466,9136],{"class":3171},[3158,16468,3176],{"class":3175},[3158,16470,7281],{"class":4363},[3158,16472,8597],{"class":4348},[3158,16474,16475],{"class":3160,"line":3971},[3158,16476,6573],{"class":3175},[3158,16478,16479,16481,16483,16486],{"class":3160,"line":3976},[3158,16480,13584],{"class":3179},[3158,16482,4407],{"class":3175},[3158,16484,16485],{"class":4354},"\"Product already active\"",[3158,16487,6786],{"class":3175},[3158,16489,16490,16492,16494,16496,16498,16500,16502,16505],{"class":3160,"line":3981},[3158,16491,13595],{"class":3179},[3158,16493,4407],{"class":3175},[3158,16495,8624],{"class":4354},[3158,16497,7352],{"class":7351},[3158,16499,4428],{"class":3179},[3158,16501,7383],{"class":7351},[3158,16503,16504],{"class":4354}," is already active\"",[3158,16506,6786],{"class":3175},[3158,16508,16509,16511,16513,16515,16517],{"class":3160,"line":3987},[3158,16510,13614],{"class":3179},[3158,16512,4407],{"class":3175},[3158,16514,8086],{"class":3179},[3158,16516,3029],{"class":3175},[3158,16518,11174],{"class":3179},[3158,16520,16521],{"class":3160,"line":3993},[3158,16522,7083],{"class":3175},[3158,16524,16525],{"class":3160,"line":3998},[3158,16526,3879],{"class":3175},[3158,16528,16529],{"class":3160,"line":4003},[3158,16530,3884],{"class":3175},[3158,16532,16533,16535,16537,16539,16541,16543],{"class":3160,"line":4009},[3158,16534,14619],{"class":3179},[3158,16536,3029],{"class":3175},[3158,16538,6149],{"class":3179},[3158,16540,4407],{"class":3175},[3158,16542,5571],{"class":4363},[3158,16544,5264],{"class":3175},[3158,16546,16547,16549,16551,16553,16555,16557,16559,16561],{"class":3160,"line":4015},[3158,16548,14619],{"class":3179},[3158,16550,3029],{"class":3175},[3158,16552,5622],{"class":3179},[3158,16554,4407],{"class":3175},[3158,16556,5600],{"class":3179},[3158,16558,3029],{"class":3175},[3158,16560,5605],{"class":3179},[3158,16562,5264],{"class":3175},[3158,16564,16565,16567,16569,16571,16573],{"class":3160,"line":4021},[3158,16566,14367],{"class":4363},[3158,16568,4413],{"class":3179},[3158,16570,3029],{"class":3175},[3158,16572,9388],{"class":3171},[3158,16574,4968],{"class":3175},[3158,16576,16577],{"class":3160,"line":4026},[3158,16578,3884],{"class":3175},[3158,16580,16581,16583,16585,16587,16589],{"class":3160,"line":4031},[3158,16582,4478],{"class":4440},[3158,16584,8696],{"class":3171},[3158,16586,3176],{"class":3175},[3158,16588,4447],{"class":3179},[3158,16590,4431],{"class":3175},[3158,16592,16593],{"class":3160,"line":4037},[3158,16594,4496],{"class":3175},[3038,16596,16598],{"id":16597},"завдання-22-експорт-з-фільтрацією","Завдання 2.2: Експорт з фільтрацією",[2964,16600,16601,16602,16605],{},"Розширте метод ",[3088,16603,16604],{},"ExportToCsv()",", додавши фільтрацію за категорією:",[3149,16607,16610],{"className":16608,"code":16609,"language":15421},[15419],"GET /api/products/export/csv?category=Electronics\n",[3088,16611,16609],{"__ignoreMap":3154},[15787,16613,16614],{"title":15986},[3149,16615,16617],{"className":3151,"code":16616,"language":3153,"meta":3154,"style":3154},"[HttpGet(\"export/csv\")]\n[Produces(\"text/csv\")]\npublic async Task\u003CIActionResult> ExportToCsv([FromQuery] string? category = null)\n{\n    var query = _db.Products.AsQueryable();\n    \n    if (!string.IsNullOrEmpty(category))\n    {\n        query = query.Where(p => p.Category == category);\n    }\n    \n    var products = await query.ToListAsync();\n    \n    var csv = new StringBuilder();\n    csv.AppendLine(\"Id,Name,Price,Stock,Category\");\n    \n    foreach (var product in products)\n    {\n        csv.AppendLine($\"{product.Id},\" +\n                      $\"\\\"{product.Name}\\\",\" +\n                      $\"{product.Price},\" +\n                      $\"{product.Stock},\" +\n                      $\"\\\"{product.Category ?? \"\"}\\\"\");\n    }\n    \n    var bytes = Encoding.UTF8.GetBytes(csv.ToString());\n    var filename = string.IsNullOrEmpty(category) \n        ? $\"products_{DateTime.UtcNow:yyyyMMdd}.csv\"\n        : $\"products_{category}_{DateTime.UtcNow:yyyyMMdd}.csv\";\n    \n    return File(bytes, \"text/csv\", filename);\n}\n",[3088,16618,16619,16631,16643,16679,16683,16706,16710,16729,16733,16765,16769,16773,16791,16795,16809,16824,16828,16844,16848,16874,16896,16914,16932,16958,16962,16966,16994,17015,17039,17073,17077,17098],{"__ignoreMap":3154},[3158,16620,16621,16623,16625,16627,16629],{"class":3160,"line":3161},[3158,16622,4345],{"class":3175},[3158,16624,4349],{"class":4348},[3158,16626,3176],{"class":3175},[3158,16628,12329],{"class":4354},[3158,16630,4358],{"class":3175},[3158,16632,16633,16635,16637,16639,16641],{"class":3160,"line":3168},[3158,16634,4345],{"class":3175},[3158,16636,7841],{"class":4348},[3158,16638,3176],{"class":3175},[3158,16640,12342],{"class":4354},[3158,16642,4358],{"class":3175},[3158,16644,16645,16647,16649,16651,16653,16655,16657,16659,16662,16664,16666,16668,16670,16673,16675,16677],{"class":3160,"line":3189},[3158,16646,4364],{"class":4363},[3158,16648,4367],{"class":4363},[3158,16650,4370],{"class":4348},[3158,16652,4373],{"class":3175},[3158,16654,3094],{"class":4348},[3158,16656,4378],{"class":3175},[3158,16658,12385],{"class":3171},[3158,16660,16661],{"class":3175},"([",[3158,16663,11534],{"class":4348},[3158,16665,11537],{"class":3175},[3158,16667,15034],{"class":4363},[3158,16669,5404],{"class":3175},[3158,16671,16672],{"class":3179},"category",[3158,16674,4407],{"class":3175},[3158,16676,5127],{"class":4363},[3158,16678,3527],{"class":3175},[3158,16680,16681],{"class":3160,"line":3196},[3158,16682,4396],{"class":3175},[3158,16684,16685,16687,16690,16692,16695,16697,16699,16701,16704],{"class":3160,"line":3202},[3158,16686,4401],{"class":4363},[3158,16688,16689],{"class":3179}," query",[3158,16691,4407],{"class":3175},[3158,16693,16694],{"class":3179},"_db",[3158,16696,3029],{"class":3175},[3158,16698,4418],{"class":3179},[3158,16700,3029],{"class":3175},[3158,16702,16703],{"class":3171},"AsQueryable",[3158,16705,4968],{"class":3175},[3158,16707,16708],{"class":3160,"line":3223},[3158,16709,3884],{"class":3175},[3158,16711,16712,16714,16716,16718,16720,16723,16725,16727],{"class":3160,"line":3249},[3158,16713,4441],{"class":4440},[3158,16715,13719],{"class":3175},[3158,16717,15034],{"class":4363},[3158,16719,3029],{"class":3175},[3158,16721,16722],{"class":3171},"IsNullOrEmpty",[3158,16724,3176],{"class":3175},[3158,16726,16672],{"class":3179},[3158,16728,7443],{"class":3175},[3158,16730,16731],{"class":3160,"line":3274},[3158,16732,6477],{"class":3175},[3158,16734,16735,16738,16740,16743,16745,16747,16749,16751,16753,16755,16757,16759,16761,16763],{"class":3160,"line":3279},[3158,16736,16737],{"class":3179},"        query",[3158,16739,4407],{"class":3175},[3158,16741,16742],{"class":3179},"query",[3158,16744,3029],{"class":3175},[3158,16746,8174],{"class":3171},[3158,16748,3176],{"class":3175},[3158,16750,2964],{"class":3179},[3158,16752,6503],{"class":3175},[3158,16754,2964],{"class":3179},[3158,16756,3029],{"class":3175},[3158,16758,5533],{"class":3179},[3158,16760,9067],{"class":3175},[3158,16762,16672],{"class":3179},[3158,16764,4431],{"class":3175},[3158,16766,16767],{"class":3160,"line":3285},[3158,16768,3879],{"class":3175},[3158,16770,16771],{"class":3160,"line":3305},[3158,16772,3884],{"class":3175},[3158,16774,16775,16777,16779,16781,16783,16785,16787,16789],{"class":3160,"line":3310},[3158,16776,4401],{"class":4363},[3158,16778,8155],{"class":3179},[3158,16780,4407],{"class":3175},[3158,16782,4410],{"class":4363},[3158,16784,16689],{"class":3179},[3158,16786,3029],{"class":3175},[3158,16788,8217],{"class":3171},[3158,16790,4968],{"class":3175},[3158,16792,16793],{"class":3160,"line":3316},[3158,16794,3884],{"class":3175},[3158,16796,16797,16799,16801,16803,16805,16807],{"class":3160,"line":3443},[3158,16798,4401],{"class":4363},[3158,16800,12449],{"class":3179},[3158,16802,4407],{"class":3175},[3158,16804,7281],{"class":4363},[3158,16806,12456],{"class":4348},[3158,16808,4968],{"class":3175},[3158,16810,16811,16813,16815,16817,16819,16822],{"class":3160,"line":3458},[3158,16812,12463],{"class":3179},[3158,16814,3029],{"class":3175},[3158,16816,12468],{"class":3171},[3158,16818,3176],{"class":3175},[3158,16820,16821],{"class":4354},"\"Id,Name,Price,Stock,Category\"",[3158,16823,4431],{"class":3175},[3158,16825,16826],{"class":3160,"line":3463},[3158,16827,3884],{"class":3175},[3158,16829,16830,16832,16834,16836,16838,16840,16842],{"class":3160,"line":3469},[3158,16831,12484],{"class":4440},[3158,16833,4444],{"class":3175},[3158,16835,7133],{"class":4363},[3158,16837,4404],{"class":3179},[3158,16839,12493],{"class":4440},[3158,16841,8155],{"class":3179},[3158,16843,3527],{"class":3175},[3158,16845,16846],{"class":3160,"line":3480},[3158,16847,6477],{"class":3175},[3158,16849,16850,16852,16854,16856,16858,16860,16862,16864,16866,16868,16870,16872],{"class":3160,"line":3495},[3158,16851,12506],{"class":3179},[3158,16853,3029],{"class":3175},[3158,16855,12468],{"class":3171},[3158,16857,3176],{"class":3175},[3158,16859,7348],{"class":4354},[3158,16861,7352],{"class":7351},[3158,16863,4447],{"class":3179},[3158,16865,3029],{"class":7351},[3158,16867,6597],{"class":3179},[3158,16869,7383],{"class":7351},[3158,16871,12527],{"class":4354},[3158,16873,12530],{"class":3175},[3158,16875,16876,16878,16880,16882,16884,16886,16888,16890,16892,16894],{"class":3160,"line":3500},[3158,16877,12535],{"class":4354},[3158,16879,12539],{"class":12538},[3158,16881,7352],{"class":7351},[3158,16883,4447],{"class":3179},[3158,16885,3029],{"class":7351},[3158,16887,5966],{"class":3179},[3158,16889,7383],{"class":7351},[3158,16891,12539],{"class":12538},[3158,16893,12527],{"class":4354},[3158,16895,12530],{"class":3175},[3158,16897,16898,16900,16902,16904,16906,16908,16910,16912],{"class":3160,"line":3506},[3158,16899,12535],{"class":4354},[3158,16901,7352],{"class":7351},[3158,16903,4447],{"class":3179},[3158,16905,3029],{"class":7351},[3158,16907,6043],{"class":3179},[3158,16909,7383],{"class":7351},[3158,16911,12527],{"class":4354},[3158,16913,12530],{"class":3175},[3158,16915,16916,16918,16920,16922,16924,16926,16928,16930],{"class":3160,"line":3518},[3158,16917,12535],{"class":4354},[3158,16919,7352],{"class":7351},[3158,16921,4447],{"class":3179},[3158,16923,3029],{"class":7351},[3158,16925,6088],{"class":3179},[3158,16927,7383],{"class":7351},[3158,16929,12527],{"class":4354},[3158,16931,12530],{"class":3175},[3158,16933,16934,16936,16938,16940,16942,16944,16946,16948,16950,16952,16954,16956],{"class":3160,"line":3959},[3158,16935,12535],{"class":4354},[3158,16937,12539],{"class":12538},[3158,16939,7352],{"class":7351},[3158,16941,4447],{"class":3179},[3158,16943,3029],{"class":7351},[3158,16945,5533],{"class":3179},[3158,16947,12572],{"class":3175},[3158,16949,12575],{"class":4354},[3158,16951,7383],{"class":7351},[3158,16953,12539],{"class":12538},[3158,16955,12662],{"class":4354},[3158,16957,4431],{"class":3175},[3158,16959,16960],{"class":3160,"line":3965},[3158,16961,3879],{"class":3175},[3158,16963,16964],{"class":3160,"line":3971},[3158,16965,3884],{"class":3175},[3158,16967,16968,16970,16972,16974,16976,16978,16980,16982,16984,16986,16988,16990,16992],{"class":3160,"line":3976},[3158,16969,4401],{"class":4363},[3158,16971,12679],{"class":3179},[3158,16973,4407],{"class":3175},[3158,16975,12684],{"class":3179},[3158,16977,3029],{"class":3175},[3158,16979,12689],{"class":3179},[3158,16981,3029],{"class":3175},[3158,16983,12694],{"class":3171},[3158,16985,3176],{"class":3175},[3158,16987,12699],{"class":3179},[3158,16989,3029],{"class":3175},[3158,16991,12704],{"class":3171},[3158,16993,12707],{"class":3175},[3158,16995,16996,16998,17001,17003,17005,17007,17009,17011,17013],{"class":3160,"line":3981},[3158,16997,4401],{"class":4363},[3158,16999,17000],{"class":3179}," filename",[3158,17002,4407],{"class":3175},[3158,17004,15034],{"class":4363},[3158,17006,3029],{"class":3175},[3158,17008,16722],{"class":3171},[3158,17010,3176],{"class":3175},[3158,17012,16672],{"class":3179},[3158,17014,6458],{"class":3175},[3158,17016,17017,17020,17023,17025,17027,17029,17031,17033,17035,17037],{"class":3160,"line":3987},[3158,17018,17019],{"class":3175},"        ? ",[3158,17021,17022],{"class":4354},"$\"products_",[3158,17024,7352],{"class":7351},[3158,17026,5600],{"class":3179},[3158,17028,3029],{"class":7351},[3158,17030,5605],{"class":3179},[3158,17032,3142],{"class":3175},[3158,17034,13158],{"class":3179},[3158,17036,7383],{"class":7351},[3158,17038,12762],{"class":4354},[3158,17040,17041,17043,17045,17047,17049,17051,17054,17056,17058,17060,17062,17064,17066,17068,17071],{"class":3160,"line":3993},[3158,17042,6463],{"class":3175},[3158,17044,17022],{"class":4354},[3158,17046,7352],{"class":7351},[3158,17048,16672],{"class":3179},[3158,17050,7383],{"class":7351},[3158,17052,17053],{"class":4354},"_",[3158,17055,7352],{"class":7351},[3158,17057,5600],{"class":3179},[3158,17059,3029],{"class":7351},[3158,17061,5605],{"class":3179},[3158,17063,3142],{"class":3175},[3158,17065,13158],{"class":3179},[3158,17067,7383],{"class":7351},[3158,17069,17070],{"class":4354},".csv\"",[3158,17072,5264],{"class":3175},[3158,17074,17075],{"class":3160,"line":3998},[3158,17076,3884],{"class":3175},[3158,17078,17079,17081,17083,17085,17087,17089,17091,17093,17096],{"class":3160,"line":4003},[3158,17080,4478],{"class":4440},[3158,17082,12723],{"class":3171},[3158,17084,3176],{"class":3175},[3158,17086,3633],{"class":3179},[3158,17088,3132],{"class":3175},[3158,17090,12342],{"class":4354},[3158,17092,3132],{"class":3175},[3158,17094,17095],{"class":3179},"filename",[3158,17097,4431],{"class":3175},[3158,17099,17100],{"class":3160,"line":4009},[3158,17101,4496],{"class":3175},[3109,17103],{},[3038,17105,17107],{"id":17106},"рівень-3-архітектура-та-створення","Рівень 3: Архітектура та створення",[5164,17109,17110,17114,17120,17126,17993,17997,18004,18047,18050],{},[3038,17111,17113],{"id":17112},"завдання-31-асинхронна-обробка","Завдання 3.1: Асинхронна обробка",[2964,17115,17116,17117,17119],{},"Реалізуйте endpoint для імпорту товарів з CSV-файлу. Оскільки обробка може тривати довго, поверніть ",[2968,17118,15592],{}," з URL для перевірки статусу:",[3149,17121,17124],{"className":17122,"code":17123,"language":15421},[15419],"POST /api/products/import\n→ 202 Accepted\nLocation: /api/products/import/status/{jobId}\n",[3088,17125,17123],{"__ignoreMap":3154},[15787,17127,17128],{"title":15986},[3149,17129,17131],{"className":3151,"code":17130,"language":3153,"meta":3154,"style":3154},"// DTO для статусу імпорту\npublic record ImportStatus\n{\n    public required string JobId { get; init; }\n    public required string Status { get; init; } // \"pending\", \"processing\", \"completed\", \"failed\"\n    public int ProcessedCount { get; init; }\n    public int TotalCount { get; init; }\n    public string? ErrorMessage { get; init; }\n}\n\n// Словник для зберігання статусів (у production використовуйте Redis/БД)\nprivate static readonly Dictionary\u003Cstring, ImportStatus> _importJobs = new();\n\n[HttpPost(\"import\")]\n[ProducesResponseType(typeof(ImportStatus), StatusCodes.Status202Accepted)]\npublic async Task\u003CIActionResult> ImportFromCsv(IFormFile file)\n{\n    if (file == null || file.Length == 0)\n    {\n        return BadRequest(new ProblemDetails\n        {\n            Title = \"Invalid file\",\n            Detail = \"CSV file is required\",\n            Status = StatusCodes.Status400BadRequest\n        });\n    }\n    \n    var jobId = Guid.NewGuid().ToString();\n    \n    var status = new ImportStatus\n    {\n        JobId = jobId,\n        Status = \"pending\",\n        ProcessedCount = 0,\n        TotalCount = 0\n    };\n    \n    _importJobs[jobId] = status;\n    \n    // Запускаємо обробку в фоні (у production використовуйте Hangfire/BackgroundService)\n    _ = Task.Run(async () => await ProcessImportAsync(jobId, file));\n    \n    return AcceptedAtAction(\n        nameof(GetImportStatus),\n        new { jobId },\n        status\n    );\n}\n\n[HttpGet(\"import/status/{jobId}\")]\n[ProducesResponseType(typeof(ImportStatus), StatusCodes.Status200OK)]\n[ProducesResponseType(StatusCodes.Status404NotFound)]\npublic IActionResult GetImportStatus(string jobId)\n{\n    if (!_importJobs.TryGetValue(jobId, out var status))\n    {\n        return NotFound(new ProblemDetails\n        {\n            Title = \"Job not found\",\n            Detail = $\"Import job with ID {jobId} does not exist\",\n            Status = StatusCodes.Status404NotFound\n        });\n    }\n    \n    return Ok(status);\n}\n\nprivate async Task ProcessImportAsync(string jobId, IFormFile file)\n{\n    // Симуляція обробки\n    await Task.Delay(5000);\n    \n    _importJobs[jobId] = _importJobs[jobId] with\n    {\n        Status = \"completed\",\n        ProcessedCount = 100,\n        TotalCount = 100\n    };\n}\n",[3088,17132,17133,17138,17147,17151,17172,17197,17216,17235,17255,17259,17263,17268,17299,17303,17316,17341,17368,17372,17401,17405,17417,17421,17432,17443,17455,17459,17463,17467,17490,17494,17507,17511,17523,17535,17546,17556,17560,17564,17581,17585,17590,17627,17631,17640,17651,17661,17666,17670,17674,17678,17691,17715,17731,17748,17752,17781,17785,17797,17801,17812,17831,17843,17847,17851,17855,17867,17871,17875,17899,17903,17908,17926,17930,17951,17955,17966,17976,17985,17989],{"__ignoreMap":3154},[3158,17134,17135],{"class":3160,"line":3161},[3158,17136,17137],{"class":3164},"// DTO для статусу імпорту\n",[3158,17139,17140,17142,17144],{"class":3160,"line":3168},[3158,17141,4364],{"class":4363},[3158,17143,5694],{"class":4363},[3158,17145,17146],{"class":4348}," ImportStatus\n",[3158,17148,17149],{"class":3160,"line":3189},[3158,17150,4396],{"class":3175},[3158,17152,17153,17155,17157,17159,17162,17164,17166,17168,17170],{"class":3160,"line":3196},[3158,17154,5306],{"class":4363},[3158,17156,5362],{"class":4363},[3158,17158,5365],{"class":4363},[3158,17160,17161],{"class":3179}," JobId",[3158,17163,5315],{"class":3175},[3158,17165,5318],{"class":4363},[3158,17167,5097],{"class":3175},[3158,17169,5750],{"class":4363},[3158,17171,5326],{"class":3175},[3158,17173,17174,17176,17178,17180,17183,17185,17187,17189,17191,17194],{"class":3160,"line":3202},[3158,17175,5306],{"class":4363},[3158,17177,5362],{"class":4363},[3158,17179,5365],{"class":4363},[3158,17181,17182],{"class":3179}," Status",[3158,17184,5315],{"class":3175},[3158,17186,5318],{"class":4363},[3158,17188,5097],{"class":3175},[3158,17190,5750],{"class":4363},[3158,17192,17193],{"class":3175},"; } ",[3158,17195,17196],{"class":3164},"// \"pending\", \"processing\", \"completed\", \"failed\"\n",[3158,17198,17199,17201,17203,17206,17208,17210,17212,17214],{"class":3160,"line":3223},[3158,17200,5306],{"class":4363},[3158,17202,5309],{"class":4363},[3158,17204,17205],{"class":3179}," ProcessedCount",[3158,17207,5315],{"class":3175},[3158,17209,5318],{"class":4363},[3158,17211,5097],{"class":3175},[3158,17213,5750],{"class":4363},[3158,17215,5326],{"class":3175},[3158,17217,17218,17220,17222,17225,17227,17229,17231,17233],{"class":3160,"line":3249},[3158,17219,5306],{"class":4363},[3158,17221,5309],{"class":4363},[3158,17223,17224],{"class":3179}," TotalCount",[3158,17226,5315],{"class":3175},[3158,17228,5318],{"class":4363},[3158,17230,5097],{"class":3175},[3158,17232,5750],{"class":4363},[3158,17234,5326],{"class":3175},[3158,17236,17237,17239,17241,17243,17245,17247,17249,17251,17253],{"class":3160,"line":3274},[3158,17238,5306],{"class":4363},[3158,17240,5365],{"class":4363},[3158,17242,5404],{"class":3175},[3158,17244,5712],{"class":3179},[3158,17246,5315],{"class":3175},[3158,17248,5318],{"class":4363},[3158,17250,5097],{"class":3175},[3158,17252,5750],{"class":4363},[3158,17254,5326],{"class":3175},[3158,17256,17257],{"class":3160,"line":3279},[3158,17258,4496],{"class":3175},[3158,17260,17261],{"class":3160,"line":3285},[3158,17262,3193],{"emptyLinePlaceholder":3192},[3158,17264,17265],{"class":3160,"line":3305},[3158,17266,17267],{"class":3164},"// Словник для зберігання статусів (у production використовуйте Redis/БД)\n",[3158,17269,17270,17272,17274,17276,17279,17281,17283,17285,17288,17290,17293,17295,17297],{"class":3160,"line":3310},[3158,17271,13180],{"class":4363},[3158,17273,11861],{"class":4363},[3158,17275,7874],{"class":4363},[3158,17277,17278],{"class":4348}," Dictionary",[3158,17280,4373],{"class":3175},[3158,17282,15034],{"class":4363},[3158,17284,3132],{"class":3175},[3158,17286,17287],{"class":4348},"ImportStatus",[3158,17289,4378],{"class":3175},[3158,17291,17292],{"class":3179},"_importJobs",[3158,17294,4407],{"class":3175},[3158,17296,7281],{"class":4363},[3158,17298,4968],{"class":3175},[3158,17300,17301],{"class":3160,"line":3316},[3158,17302,3193],{"emptyLinePlaceholder":3192},[3158,17304,17305,17307,17309,17311,17314],{"class":3160,"line":3443},[3158,17306,4345],{"class":3175},[3158,17308,8872],{"class":4348},[3158,17310,3176],{"class":3175},[3158,17312,17313],{"class":4354},"\"import\"",[3158,17315,4358],{"class":3175},[3158,17317,17318,17320,17322,17324,17326,17328,17330,17332,17334,17336,17339],{"class":3160,"line":3458},[3158,17319,4345],{"class":3175},[3158,17321,8065],{"class":4348},[3158,17323,3176],{"class":3175},[3158,17325,8070],{"class":4363},[3158,17327,3176],{"class":3175},[3158,17329,17287],{"class":4348},[3158,17331,8424],{"class":3175},[3158,17333,8086],{"class":3179},[3158,17335,3029],{"class":3175},[3158,17337,17338],{"class":3179},"Status202Accepted",[3158,17340,4358],{"class":3175},[3158,17342,17343,17345,17347,17349,17351,17353,17355,17358,17360,17363,17366],{"class":3160,"line":3463},[3158,17344,4364],{"class":4363},[3158,17346,4367],{"class":4363},[3158,17348,4370],{"class":4348},[3158,17350,4373],{"class":3175},[3158,17352,3094],{"class":4348},[3158,17354,4378],{"class":3175},[3158,17356,17357],{"class":3171},"ImportFromCsv",[3158,17359,3176],{"class":3175},[3158,17361,17362],{"class":4348},"IFormFile",[3158,17364,17365],{"class":3179}," file",[3158,17367,3527],{"class":3175},[3158,17369,17370],{"class":3160,"line":3469},[3158,17371,4396],{"class":3175},[3158,17373,17374,17376,17378,17381,17383,17385,17388,17390,17392,17395,17397,17399],{"class":3160,"line":3480},[3158,17375,4441],{"class":4440},[3158,17377,4444],{"class":3175},[3158,17379,17380],{"class":3179},"file",[3158,17382,9067],{"class":3175},[3158,17384,5127],{"class":4363},[3158,17386,17387],{"class":3175}," || ",[3158,17389,17380],{"class":3179},[3158,17391,3029],{"class":3175},[3158,17393,17394],{"class":3179},"Length",[3158,17396,9067],{"class":3175},[3158,17398,5475],{"class":3551},[3158,17400,3527],{"class":3175},[3158,17402,17403],{"class":3160,"line":3495},[3158,17404,6477],{"class":3175},[3158,17406,17407,17409,17411,17413,17415],{"class":3160,"line":3500},[3158,17408,4460],{"class":4440},[3158,17410,11579],{"class":3171},[3158,17412,3176],{"class":3175},[3158,17414,7281],{"class":4363},[3158,17416,8597],{"class":4348},[3158,17418,17419],{"class":3160,"line":3506},[3158,17420,6573],{"class":3175},[3158,17422,17423,17425,17427,17430],{"class":3160,"line":3518},[3158,17424,13584],{"class":3179},[3158,17426,4407],{"class":3175},[3158,17428,17429],{"class":4354},"\"Invalid file\"",[3158,17431,6786],{"class":3175},[3158,17433,17434,17436,17438,17441],{"class":3160,"line":3959},[3158,17435,13595],{"class":3179},[3158,17437,4407],{"class":3175},[3158,17439,17440],{"class":4354},"\"CSV file is required\"",[3158,17442,6786],{"class":3175},[3158,17444,17445,17447,17449,17451,17453],{"class":3160,"line":3965},[3158,17446,13614],{"class":3179},[3158,17448,4407],{"class":3175},[3158,17450,8086],{"class":3179},[3158,17452,3029],{"class":3175},[3158,17454,11628],{"class":3179},[3158,17456,17457],{"class":3160,"line":3971},[3158,17458,7083],{"class":3175},[3158,17460,17461],{"class":3160,"line":3976},[3158,17462,3879],{"class":3175},[3158,17464,17465],{"class":3160,"line":3981},[3158,17466,3884],{"class":3175},[3158,17468,17469,17471,17474,17476,17479,17481,17484,17486,17488],{"class":3160,"line":3987},[3158,17470,4401],{"class":4363},[3158,17472,17473],{"class":3179}," jobId",[3158,17475,4407],{"class":3175},[3158,17477,17478],{"class":3179},"Guid",[3158,17480,3029],{"class":3175},[3158,17482,17483],{"class":3171},"NewGuid",[3158,17485,7373],{"class":3175},[3158,17487,12704],{"class":3171},[3158,17489,4968],{"class":3175},[3158,17491,17492],{"class":3160,"line":3993},[3158,17493,3884],{"class":3175},[3158,17495,17496,17498,17501,17503,17505],{"class":3160,"line":3998},[3158,17497,4401],{"class":4363},[3158,17499,17500],{"class":3179}," status",[3158,17502,4407],{"class":3175},[3158,17504,7281],{"class":4363},[3158,17506,17146],{"class":4348},[3158,17508,17509],{"class":3160,"line":4003},[3158,17510,6477],{"class":3175},[3158,17512,17513,17516,17518,17521],{"class":3160,"line":4009},[3158,17514,17515],{"class":3179},"        JobId",[3158,17517,4407],{"class":3175},[3158,17519,17520],{"class":3179},"jobId",[3158,17522,6786],{"class":3175},[3158,17524,17525,17528,17530,17533],{"class":3160,"line":4015},[3158,17526,17527],{"class":3179},"        Status",[3158,17529,4407],{"class":3175},[3158,17531,17532],{"class":4354},"\"pending\"",[3158,17534,6786],{"class":3175},[3158,17536,17537,17540,17542,17544],{"class":3160,"line":4021},[3158,17538,17539],{"class":3179},"        ProcessedCount",[3158,17541,4407],{"class":3175},[3158,17543,5475],{"class":3551},[3158,17545,6786],{"class":3175},[3158,17547,17548,17551,17553],{"class":3160,"line":4026},[3158,17549,17550],{"class":3179},"        TotalCount",[3158,17552,4407],{"class":3175},[3158,17554,17555],{"class":3551},"0\n",[3158,17557,17558],{"class":3160,"line":4031},[3158,17559,12032],{"class":3175},[3158,17561,17562],{"class":3160,"line":4037},[3158,17563,3884],{"class":3175},[3158,17565,17566,17569,17571,17573,17576,17579],{"class":3160,"line":4043},[3158,17567,17568],{"class":3179},"    _importJobs",[3158,17570,4345],{"class":3175},[3158,17572,17520],{"class":3179},[3158,17574,17575],{"class":3175},"] = ",[3158,17577,17578],{"class":3179},"status",[3158,17580,5264],{"class":3175},[3158,17582,17583],{"class":3160,"line":4048},[3158,17584,3884],{"class":3175},[3158,17586,17587],{"class":3160,"line":4053},[3158,17588,17589],{"class":3164},"    // Запускаємо обробку в фоні (у production використовуйте Hangfire/BackgroundService)\n",[3158,17591,17592,17595,17597,17600,17602,17604,17606,17609,17612,17614,17617,17619,17621,17623,17625],{"class":3160,"line":4059},[3158,17593,17594],{"class":3179},"    _",[3158,17596,4407],{"class":3175},[3158,17598,17599],{"class":3179},"Task",[3158,17601,3029],{"class":3175},[3158,17603,7690],{"class":3171},[3158,17605,3176],{"class":3175},[3158,17607,17608],{"class":4363},"async",[3158,17610,17611],{"class":3175}," () => ",[3158,17613,4410],{"class":4363},[3158,17615,17616],{"class":3171}," ProcessImportAsync",[3158,17618,3176],{"class":3175},[3158,17620,17520],{"class":3179},[3158,17622,3132],{"class":3175},[3158,17624,17380],{"class":3179},[3158,17626,7205],{"class":3175},[3158,17628,17629],{"class":3160,"line":4065},[3158,17630,3884],{"class":3175},[3158,17632,17633,17635,17638],{"class":3160,"line":4070},[3158,17634,4478],{"class":4440},[3158,17636,17637],{"class":3171}," AcceptedAtAction",[3158,17639,6732],{"class":3175},[3158,17641,17642,17644,17646,17649],{"class":3160,"line":4075},[3158,17643,14392],{"class":4363},[3158,17645,3176],{"class":3175},[3158,17647,17648],{"class":3179},"GetImportStatus",[3158,17650,9446],{"class":3175},[3158,17652,17653,17655,17657,17659],{"class":3160,"line":4081},[3158,17654,14407],{"class":4363},[3158,17656,5315],{"class":3175},[3158,17658,17520],{"class":3179},[3158,17660,9467],{"class":3175},[3158,17662,17663],{"class":3160,"line":4087},[3158,17664,17665],{"class":3179},"        status\n",[3158,17667,17668],{"class":3160,"line":4092},[3158,17669,12767],{"class":3175},[3158,17671,17672],{"class":3160,"line":4097},[3158,17673,4496],{"class":3175},[3158,17675,17676],{"class":3160,"line":4103},[3158,17677,3193],{"emptyLinePlaceholder":3192},[3158,17679,17680,17682,17684,17686,17689],{"class":3160,"line":4109},[3158,17681,4345],{"class":3175},[3158,17683,4349],{"class":4348},[3158,17685,3176],{"class":3175},[3158,17687,17688],{"class":4354},"\"import/status/{jobId}\"",[3158,17690,4358],{"class":3175},[3158,17692,17693,17695,17697,17699,17701,17703,17705,17707,17709,17711,17713],{"class":3160,"line":4114},[3158,17694,4345],{"class":3175},[3158,17696,8065],{"class":4348},[3158,17698,3176],{"class":3175},[3158,17700,8070],{"class":4363},[3158,17702,3176],{"class":3175},[3158,17704,17287],{"class":4348},[3158,17706,8424],{"class":3175},[3158,17708,8086],{"class":3179},[3158,17710,3029],{"class":3175},[3158,17712,8091],{"class":3179},[3158,17714,4358],{"class":3175},[3158,17716,17717,17719,17721,17723,17725,17727,17729],{"class":3160,"line":4119},[3158,17718,4345],{"class":3175},[3158,17720,8065],{"class":4348},[3158,17722,3176],{"class":3175},[3158,17724,8086],{"class":3179},[3158,17726,3029],{"class":3175},[3158,17728,8456],{"class":3179},[3158,17730,4358],{"class":3175},[3158,17732,17733,17735,17737,17740,17742,17744,17746],{"class":3160,"line":4125},[3158,17734,4364],{"class":4363},[3158,17736,13925],{"class":4348},[3158,17738,17739],{"class":3171}," GetImportStatus",[3158,17741,3176],{"class":3175},[3158,17743,15034],{"class":4363},[3158,17745,17473],{"class":3179},[3158,17747,3527],{"class":3175},[3158,17749,17750],{"class":3160,"line":4131},[3158,17751,4396],{"class":3175},[3158,17753,17754,17756,17758,17760,17762,17765,17767,17769,17771,17774,17777,17779],{"class":3160,"line":4136},[3158,17755,4441],{"class":4440},[3158,17757,13719],{"class":3175},[3158,17759,17292],{"class":3179},[3158,17761,3029],{"class":3175},[3158,17763,17764],{"class":3171},"TryGetValue",[3158,17766,3176],{"class":3175},[3158,17768,17520],{"class":3179},[3158,17770,3132],{"class":3175},[3158,17772,17773],{"class":4363},"out",[3158,17775,17776],{"class":4363}," var",[3158,17778,17500],{"class":3179},[3158,17780,7443],{"class":3175},[3158,17782,17783],{"class":3160,"line":4141},[3158,17784,6477],{"class":3175},[3158,17786,17787,17789,17791,17793,17795],{"class":3160,"line":4147},[3158,17788,4460],{"class":4440},[3158,17790,4463],{"class":3171},[3158,17792,3176],{"class":3175},[3158,17794,7281],{"class":4363},[3158,17796,8597],{"class":4348},[3158,17798,17799],{"class":3160,"line":4153},[3158,17800,6573],{"class":3175},[3158,17802,17803,17805,17807,17810],{"class":3160,"line":4159},[3158,17804,13584],{"class":3179},[3158,17806,4407],{"class":3175},[3158,17808,17809],{"class":4354},"\"Job not found\"",[3158,17811,6786],{"class":3175},[3158,17813,17814,17816,17818,17821,17823,17825,17827,17829],{"class":3160,"line":4165},[3158,17815,13595],{"class":3179},[3158,17817,4407],{"class":3175},[3158,17819,17820],{"class":4354},"$\"Import job with ID ",[3158,17822,7352],{"class":7351},[3158,17824,17520],{"class":3179},[3158,17826,7383],{"class":7351},[3158,17828,8633],{"class":4354},[3158,17830,6786],{"class":3175},[3158,17832,17833,17835,17837,17839,17841],{"class":3160,"line":4170},[3158,17834,13614],{"class":3179},[3158,17836,4407],{"class":3175},[3158,17838,8086],{"class":3179},[3158,17840,3029],{"class":3175},[3158,17842,9884],{"class":3179},[3158,17844,17845],{"class":3160,"line":4176},[3158,17846,7083],{"class":3175},[3158,17848,17849],{"class":3160,"line":4182},[3158,17850,3879],{"class":3175},[3158,17852,17853],{"class":3160,"line":4188},[3158,17854,3884],{"class":3175},[3158,17856,17857,17859,17861,17863,17865],{"class":3160,"line":4194},[3158,17858,4478],{"class":4440},[3158,17860,4481],{"class":3171},[3158,17862,3176],{"class":3175},[3158,17864,17578],{"class":3179},[3158,17866,4431],{"class":3175},[3158,17868,17869],{"class":3160,"line":4199},[3158,17870,4496],{"class":3175},[3158,17872,17873],{"class":3160,"line":4205},[3158,17874,3193],{"emptyLinePlaceholder":3192},[3158,17876,17877,17879,17881,17883,17885,17887,17889,17891,17893,17895,17897],{"class":3160,"line":4210},[3158,17878,13180],{"class":4363},[3158,17880,4367],{"class":4363},[3158,17882,4370],{"class":4348},[3158,17884,17616],{"class":3171},[3158,17886,3176],{"class":3175},[3158,17888,15034],{"class":4363},[3158,17890,17473],{"class":3179},[3158,17892,3132],{"class":3175},[3158,17894,17362],{"class":4348},[3158,17896,17365],{"class":3179},[3158,17898,3527],{"class":3175},[3158,17900,17901],{"class":3160,"line":4216},[3158,17902,4396],{"class":3175},[3158,17904,17905],{"class":3160,"line":4222},[3158,17906,17907],{"class":3164},"    // Симуляція обробки\n",[3158,17909,17910,17912,17914,17916,17919,17921,17924],{"class":3160,"line":4227},[3158,17911,14367],{"class":4363},[3158,17913,4370],{"class":3179},[3158,17915,3029],{"class":3175},[3158,17917,17918],{"class":3171},"Delay",[3158,17920,3176],{"class":3175},[3158,17922,17923],{"class":3551},"5000",[3158,17925,4431],{"class":3175},[3158,17927,17928],{"class":3160,"line":4233},[3158,17929,3884],{"class":3175},[3158,17931,17932,17934,17936,17938,17940,17942,17944,17946,17948],{"class":3160,"line":4239},[3158,17933,17568],{"class":3179},[3158,17935,4345],{"class":3175},[3158,17937,17520],{"class":3179},[3158,17939,17575],{"class":3175},[3158,17941,17292],{"class":3179},[3158,17943,4345],{"class":3175},[3158,17945,17520],{"class":3179},[3158,17947,11537],{"class":3175},[3158,17949,17950],{"class":4363},"with\n",[3158,17952,17953],{"class":3160,"line":4245},[3158,17954,6477],{"class":3175},[3158,17956,17957,17959,17961,17964],{"class":3160,"line":4251},[3158,17958,17527],{"class":3179},[3158,17960,4407],{"class":3175},[3158,17962,17963],{"class":4354},"\"completed\"",[3158,17965,6786],{"class":3175},[3158,17967,17968,17970,17972,17974],{"class":3160,"line":4257},[3158,17969,17539],{"class":3179},[3158,17971,4407],{"class":3175},[3158,17973,5520],{"class":3551},[3158,17975,6786],{"class":3175},[3158,17977,17978,17980,17982],{"class":3160,"line":4263},[3158,17979,17550],{"class":3179},[3158,17981,4407],{"class":3175},[3158,17983,17984],{"class":3551},"100\n",[3158,17986,17987],{"class":3160,"line":8728},[3158,17988,12032],{"class":3175},[3158,17990,17991],{"class":3160,"line":8739},[3158,17992,4496],{"class":3175},[3038,17994,17996],{"id":17995},"завдання-32-повний-crud-для-categories","Завдання 3.2: Повний CRUD для Categories",[2964,17998,17999,18000,18003],{},"Створіть новий контролер ",[3088,18001,18002],{},"CategoriesController"," з повним CRUD та правильними типами повернення:",[2980,18005,18006,18015,18023,18031,18039],{},[2983,18007,18008,18011,18012],{},[3088,18009,18010],{},"GET /api/categories"," → ",[3088,18013,18014],{},"ActionResult\u003CIEnumerable\u003CCategoryDto>>",[2983,18016,18017,18011,18020],{},[3088,18018,18019],{},"GET /api/categories/{id}",[3088,18021,18022],{},"ActionResult\u003CCategoryDto>",[2983,18024,18025,18011,18028,18030],{},[3088,18026,18027],{},"POST /api/categories",[3088,18029,18022],{}," (201 Created)",[2983,18032,18033,18011,18036,18038],{},[3088,18034,18035],{},"PUT /api/categories/{id}",[3088,18037,18022],{}," (200 OK)",[2983,18040,18041,18011,18044,18046],{},[3088,18042,18043],{},"DELETE /api/categories/{id}",[3088,18045,3094],{}," (204 No Content або 409 Conflict)",[2964,18048,18049],{},"Додайте бізнес-правило: категорію не можна видалити, якщо в ній є товари.",[15787,18051,18053],{"title":18052},"Показати структуру рішення",[3149,18054,18056],{"className":3151,"code":18055,"language":3153,"meta":3154,"style":3154},"[ApiController]\n[Route(\"api/[controller]\")]\npublic class CategoriesController : ControllerBase\n{\n    private readonly ProductDbContext _db;\n\n    public CategoriesController(ProductDbContext db)\n    {\n        _db = db;\n    }\n\n    [HttpGet]\n    [ProducesResponseType(typeof(IEnumerable\u003Cstring>), StatusCodes.Status200OK)]\n    public async Task\u003CActionResult\u003CIEnumerable\u003Cstring>>> GetAll()\n    {\n        var categories = await _db.Products\n            .Where(p => p.Category != null)\n            .Select(p => p.Category!)\n            .Distinct()\n            .OrderBy(c => c)\n            .ToListAsync();\n        \n        return Ok(categories);\n    }\n\n    [HttpDelete(\"{name}\")]\n    [ProducesResponseType(StatusCodes.Status204NoContent)]\n    [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status409Conflict)]\n    public async Task\u003CIActionResult> Delete(string name)\n    {\n        var productsInCategory = await _db.Products\n            .CountAsync(p => p.Category == name);\n        \n        if (productsInCategory > 0)\n        {\n            return Conflict(new ProblemDetails\n            {\n                Title = \"Cannot delete category\",\n                Detail = $\"Category '{name}' has {productsInCategory} products\",\n                Status = StatusCodes.Status409Conflict\n            });\n        }\n        \n        // Логіка видалення...\n        return NoContent();\n    }\n    \n    // Інші методи...\n}\n",[3088,18057,18058,18066,18078,18091,18095,18107,18111,18125,18129,18139,18143,18147,18155,18183,18209,18213,18230,18255,18276,18285,18302,18310,18314,18327,18331,18335,18348,18364,18388,18412,18416,18433,18459,18463,18478,18482,18494,18498,18509,18538,18550,18554,18558,18562,18567,18575,18579,18583,18588],{"__ignoreMap":3154},[3158,18059,18060,18062,18064],{"class":3160,"line":3161},[3158,18061,4345],{"class":3175},[3158,18063,7818],{"class":4348},[3158,18065,5341],{"class":3175},[3158,18067,18068,18070,18072,18074,18076],{"class":3160,"line":3168},[3158,18069,4345],{"class":3175},[3158,18071,7827],{"class":4348},[3158,18073,3176],{"class":3175},[3158,18075,7832],{"class":4354},[3158,18077,4358],{"class":3175},[3158,18079,18080,18082,18084,18087,18089],{"class":3160,"line":3189},[3158,18081,4364],{"class":4363},[3158,18083,5294],{"class":4363},[3158,18085,18086],{"class":4348}," CategoriesController",[3158,18088,6427],{"class":3175},[3158,18090,7862],{"class":4348},[3158,18092,18093],{"class":3160,"line":3196},[3158,18094,4396],{"class":3175},[3158,18096,18097,18099,18101,18103,18105],{"class":3160,"line":3202},[3158,18098,7871],{"class":4363},[3158,18100,7874],{"class":4363},[3158,18102,6424],{"class":4348},[3158,18104,4413],{"class":3179},[3158,18106,5264],{"class":3175},[3158,18108,18109],{"class":3160,"line":3223},[3158,18110,3193],{"emptyLinePlaceholder":3192},[3158,18112,18113,18115,18117,18119,18121,18123],{"class":3160,"line":3249},[3158,18114,5306],{"class":4363},[3158,18116,18086],{"class":3171},[3158,18118,3176],{"class":3175},[3158,18120,6450],{"class":4348},[3158,18122,7542],{"class":3179},[3158,18124,3527],{"class":3175},[3158,18126,18127],{"class":3160,"line":3274},[3158,18128,6477],{"class":3175},[3158,18130,18131,18133,18135,18137],{"class":3160,"line":3279},[3158,18132,7942],{"class":3179},[3158,18134,4407],{"class":3175},[3158,18136,7947],{"class":3179},[3158,18138,5264],{"class":3175},[3158,18140,18141],{"class":3160,"line":3285},[3158,18142,3879],{"class":3175},[3158,18144,18145],{"class":3160,"line":3305},[3158,18146,3193],{"emptyLinePlaceholder":3192},[3158,18148,18149,18151,18153],{"class":3160,"line":3310},[3158,18150,5335],{"class":3175},[3158,18152,4349],{"class":4348},[3158,18154,5341],{"class":3175},[3158,18156,18157,18159,18161,18163,18165,18167,18169,18171,18173,18175,18177,18179,18181],{"class":3160,"line":3316},[3158,18158,5335],{"class":3175},[3158,18160,8065],{"class":4348},[3158,18162,3176],{"class":3175},[3158,18164,8070],{"class":4363},[3158,18166,3176],{"class":3175},[3158,18168,8075],{"class":4348},[3158,18170,4373],{"class":3175},[3158,18172,15034],{"class":4363},[3158,18174,8083],{"class":3175},[3158,18176,8086],{"class":3179},[3158,18178,3029],{"class":3175},[3158,18180,8091],{"class":3179},[3158,18182,4358],{"class":3175},[3158,18184,18185,18187,18189,18191,18193,18195,18197,18199,18201,18203,18205,18207],{"class":3160,"line":3443},[3158,18186,5306],{"class":4363},[3158,18188,4367],{"class":4363},[3158,18190,4370],{"class":4348},[3158,18192,4373],{"class":3175},[3158,18194,4292],{"class":4348},[3158,18196,4373],{"class":3175},[3158,18198,8075],{"class":4348},[3158,18200,4373],{"class":3175},[3158,18202,15034],{"class":4363},[3158,18204,8116],{"class":3175},[3158,18206,8119],{"class":3171},[3158,18208,8122],{"class":3175},[3158,18210,18211],{"class":3160,"line":3458},[3158,18212,6477],{"class":3175},[3158,18214,18215,18217,18220,18222,18224,18226,18228],{"class":3160,"line":3463},[3158,18216,8152],{"class":4363},[3158,18218,18219],{"class":3179}," categories",[3158,18221,4407],{"class":3175},[3158,18223,4410],{"class":4363},[3158,18225,4413],{"class":3179},[3158,18227,3029],{"class":3175},[3158,18229,8166],{"class":3179},[3158,18231,18232,18234,18236,18238,18240,18242,18244,18246,18248,18251,18253],{"class":3160,"line":3469},[3158,18233,8171],{"class":3175},[3158,18235,8174],{"class":3171},[3158,18237,3176],{"class":3175},[3158,18239,2964],{"class":3179},[3158,18241,6503],{"class":3175},[3158,18243,2964],{"class":3179},[3158,18245,3029],{"class":3175},[3158,18247,5533],{"class":3179},[3158,18249,18250],{"class":3175}," != ",[3158,18252,5127],{"class":4363},[3158,18254,3527],{"class":3175},[3158,18256,18257,18259,18261,18263,18265,18267,18269,18271,18273],{"class":3160,"line":3480},[3158,18258,8171],{"class":3175},[3158,18260,8240],{"class":3171},[3158,18262,3176],{"class":3175},[3158,18264,2964],{"class":3179},[3158,18266,6503],{"class":3175},[3158,18268,2964],{"class":3179},[3158,18270,3029],{"class":3175},[3158,18272,5533],{"class":3179},[3158,18274,18275],{"class":3175},"!)\n",[3158,18277,18278,18280,18283],{"class":3160,"line":3495},[3158,18279,8171],{"class":3175},[3158,18281,18282],{"class":3171},"Distinct",[3158,18284,8122],{"class":3175},[3158,18286,18287,18289,18291,18293,18296,18298,18300],{"class":3160,"line":3500},[3158,18288,8171],{"class":3175},[3158,18290,13044],{"class":3171},[3158,18292,3176],{"class":3175},[3158,18294,18295],{"class":3179},"c",[3158,18297,6503],{"class":3175},[3158,18299,18295],{"class":3179},[3158,18301,3527],{"class":3175},[3158,18303,18304,18306,18308],{"class":3160,"line":3506},[3158,18305,8171],{"class":3175},[3158,18307,8217],{"class":3171},[3158,18309,4968],{"class":3175},[3158,18311,18312],{"class":3160,"line":3518},[3158,18313,8147],{"class":3175},[3158,18315,18316,18318,18320,18322,18325],{"class":3160,"line":3959},[3158,18317,4460],{"class":4440},[3158,18319,4481],{"class":3171},[3158,18321,3176],{"class":3175},[3158,18323,18324],{"class":3179},"categories",[3158,18326,4431],{"class":3175},[3158,18328,18329],{"class":3160,"line":3965},[3158,18330,3879],{"class":3175},[3158,18332,18333],{"class":3160,"line":3971},[3158,18334,3193],{"emptyLinePlaceholder":3192},[3158,18336,18337,18339,18341,18343,18346],{"class":3160,"line":3976},[3158,18338,5335],{"class":3175},[3158,18340,10338],{"class":4348},[3158,18342,3176],{"class":3175},[3158,18344,18345],{"class":4354},"\"{name}\"",[3158,18347,4358],{"class":3175},[3158,18349,18350,18352,18354,18356,18358,18360,18362],{"class":3160,"line":3981},[3158,18351,5335],{"class":3175},[3158,18353,8065],{"class":4348},[3158,18355,3176],{"class":3175},[3158,18357,8086],{"class":3179},[3158,18359,3029],{"class":3175},[3158,18361,10360],{"class":3179},[3158,18363,4358],{"class":3175},[3158,18365,18366,18368,18370,18372,18374,18376,18378,18380,18382,18384,18386],{"class":3160,"line":3987},[3158,18367,5335],{"class":3175},[3158,18369,8065],{"class":4348},[3158,18371,3176],{"class":3175},[3158,18373,8070],{"class":4363},[3158,18375,3176],{"class":3175},[3158,18377,8447],{"class":4348},[3158,18379,8424],{"class":3175},[3158,18381,8086],{"class":3179},[3158,18383,3029],{"class":3175},[3158,18385,8951],{"class":3179},[3158,18387,4358],{"class":3175},[3158,18389,18390,18392,18394,18396,18398,18400,18402,18404,18406,18408,18410],{"class":3160,"line":3993},[3158,18391,5306],{"class":4363},[3158,18393,4367],{"class":4363},[3158,18395,4370],{"class":4348},[3158,18397,4373],{"class":3175},[3158,18399,3094],{"class":4348},[3158,18401,4378],{"class":3175},[3158,18403,10405],{"class":3171},[3158,18405,3176],{"class":3175},[3158,18407,15034],{"class":4363},[3158,18409,8308],{"class":3179},[3158,18411,3527],{"class":3175},[3158,18413,18414],{"class":3160,"line":3998},[3158,18415,6477],{"class":3175},[3158,18417,18418,18420,18423,18425,18427,18429,18431],{"class":3160,"line":4003},[3158,18419,8152],{"class":4363},[3158,18421,18422],{"class":3179}," productsInCategory",[3158,18424,4407],{"class":3175},[3158,18426,4410],{"class":4363},[3158,18428,4413],{"class":3179},[3158,18430,3029],{"class":3175},[3158,18432,8166],{"class":3179},[3158,18434,18435,18437,18440,18442,18444,18446,18448,18450,18452,18454,18457],{"class":3160,"line":4009},[3158,18436,8171],{"class":3175},[3158,18438,18439],{"class":3171},"CountAsync",[3158,18441,3176],{"class":3175},[3158,18443,2964],{"class":3179},[3158,18445,6503],{"class":3175},[3158,18447,2964],{"class":3179},[3158,18449,3029],{"class":3175},[3158,18451,5533],{"class":3179},[3158,18453,9067],{"class":3175},[3158,18455,18456],{"class":3179},"name",[3158,18458,4431],{"class":3175},[3158,18460,18461],{"class":3160,"line":4015},[3158,18462,8147],{"class":3175},[3158,18464,18465,18467,18469,18472,18474,18476],{"class":3160,"line":4021},[3158,18466,8548],{"class":4440},[3158,18468,4444],{"class":3175},[3158,18470,18471],{"class":3179},"productsInCategory",[3158,18473,11096],{"class":3175},[3158,18475,5475],{"class":3551},[3158,18477,3527],{"class":3175},[3158,18479,18480],{"class":3160,"line":4026},[3158,18481,6573],{"class":3175},[3158,18483,18484,18486,18488,18490,18492],{"class":3160,"line":4031},[3158,18485,8588],{"class":4440},[3158,18487,9136],{"class":3171},[3158,18489,3176],{"class":3175},[3158,18491,7281],{"class":4363},[3158,18493,8597],{"class":4348},[3158,18495,18496],{"class":3160,"line":4037},[3158,18497,8602],{"class":3175},[3158,18499,18500,18502,18504,18507],{"class":3160,"line":4043},[3158,18501,8607],{"class":3179},[3158,18503,4407],{"class":3175},[3158,18505,18506],{"class":4354},"\"Cannot delete category\"",[3158,18508,6786],{"class":3175},[3158,18510,18511,18513,18515,18518,18520,18522,18524,18527,18529,18531,18533,18536],{"class":3160,"line":4048},[3158,18512,8619],{"class":3179},[3158,18514,4407],{"class":3175},[3158,18516,18517],{"class":4354},"$\"Category '",[3158,18519,7352],{"class":7351},[3158,18521,18456],{"class":3179},[3158,18523,7383],{"class":7351},[3158,18525,18526],{"class":4354},"' has ",[3158,18528,7352],{"class":7351},[3158,18530,18471],{"class":3179},[3158,18532,7383],{"class":7351},[3158,18534,18535],{"class":4354}," products\"",[3158,18537,6786],{"class":3175},[3158,18539,18540,18542,18544,18546,18548],{"class":3160,"line":4053},[3158,18541,8640],{"class":3179},[3158,18543,4407],{"class":3175},[3158,18545,8086],{"class":3179},[3158,18547,3029],{"class":3175},[3158,18549,11174],{"class":3179},[3158,18551,18552],{"class":3160,"line":4059},[3158,18553,8675],{"class":3175},[3158,18555,18556],{"class":3160,"line":4065},[3158,18557,8680],{"class":3175},[3158,18559,18560],{"class":3160,"line":4070},[3158,18561,8147],{"class":3175},[3158,18563,18564],{"class":3160,"line":4075},[3158,18565,18566],{"class":3164},"        // Логіка видалення...\n",[3158,18568,18569,18571,18573],{"class":3160,"line":4081},[3158,18570,4460],{"class":4440},[3158,18572,10648],{"class":3171},[3158,18574,4968],{"class":3175},[3158,18576,18577],{"class":3160,"line":4087},[3158,18578,3879],{"class":3175},[3158,18580,18581],{"class":3160,"line":4092},[3158,18582,3884],{"class":3175},[3158,18584,18585],{"class":3160,"line":4097},[3158,18586,18587],{"class":3164},"    // Інші методи...\n",[3158,18589,18590],{"class":3160,"line":4103},[3158,18591,4496],{"class":3175},[3109,18593],{},[2959,18595,18597],{"id":18596},"підсумок","Підсумок",[2964,18599,18600,18601,18604],{},"У цій статті ми здійснили глибоке занурення в світ типів повернення ASP.NET Core Web API. Ви навчилися не просто повертати дані, а ",[2968,18602,18603],{},"формувати семантично правильні HTTP-відповіді",", що роблять ваш API передбачуваним та зручним для клієнтів.",[2964,18606,18607],{},[2968,18608,18609],{},"Ключові висновки:",[4273,18611,18612,18626,18638,18644,18650,18658],{},[2983,18613,18614,18617,18618,3132,18620,3132,18622,18625],{},[2968,18615,18616],{},"ControllerBase — фабрика результатів:"," Використовуйте допоміжні методи (",[3088,18619,4706],{},[3088,18621,14267],{},[3088,18623,18624],{},"Created()",") замість ручного конструювання результатів — це робить код самодокументованим.",[2983,18627,18628,18631,18632,18634,18635,18637],{},[2968,18629,18630],{},"ActionResult\u003CT> > IActionResult:"," Завжди віддавайте перевагу ",[3088,18633,3090],{}," для type safety та автоматичної документації OpenAPI. Використовуйте ",[3088,18636,3094],{}," лише для методів з принципово різними типами відповідей.",[2983,18639,18640,18643],{},[2968,18641,18642],{},"Правильні HTTP-коди:"," Кожен код несе семантичне значення. 200 ≠ 201 ≠ 204 — вибір коду впливає на те, як клієнт обробляє відповідь.",[2983,18645,18646,18649],{},[2968,18647,18648],{},"ProblemDetails для помилок:"," Використовуйте стандартизований формат RFC 9457 для всіх помилок — це забезпечує консистентність та полегшує обробку на клієнті.",[2983,18651,18652,5183,18655,18657],{},[2968,18653,18654],{},"Документування через атрибути:",[3088,18656,3104],{}," — це не опціональна декорація, а критично важлива частина API-контракту.",[2983,18659,18660,18663,18664,3132,18666,18669],{},[2968,18661,18662],{},"Файли — теж результати:"," API може повертати не лише JSON — використовуйте ",[3088,18665,12793],{},[3088,18667,18668],{},"PhysicalFile()"," для експорту даних у різних форматах.",[2964,18671,18672,18673,18676],{},"У наступній статті ми розглянемо ",[2968,18674,18675],{},"Content Negotiation"," — механізм, що дозволяє одному endpoint повертати дані у різних форматах (JSON, XML, CSV) залежно від запиту клієнта.",[3109,18678],{},[2959,18680,18682],{"id":18681},"додаткові-ресурси","Додаткові ресурси",[18684,18685,18686,18693,18699,18705],"card-group",{},[18687,18688,18692],"card",{"icon":15,"target":18689,"title":18690,"to":18691},"_blank","ActionResult документація","https://learn.microsoft.com/en-us/aspnet/core/web-api/action-return-types","Офіційна документація про типи повернення",[18687,18694,18698],{"icon":18695,"target":18689,"title":18696,"to":18697},"i-lucide-list-checks","HTTP Status Codes","https://httpstatuses.com/","Повний довідник HTTP-кодів з поясненнями",[18687,18700,18704],{"icon":18701,"target":18689,"title":18702,"to":18703},"i-lucide-alert-circle","ProblemDetails (RFC 9457)","https://www.rfc-editor.org/rfc/rfc9457.html","Специфікація формату помилок",[18687,18706,18710],{"icon":18707,"target":18689,"title":18708,"to":18709},"i-lucide-file-down","File Results","https://learn.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads","Робота з файлами в ASP.NET Core",[3109,18712],{},[3031,18714,18715,5183,18718,18722],{},[2968,18716,18717],{},"Наступна стаття:",[18719,18720,18721],"a",{"href":1304},"Content Negotiation: JSON, XML та власні форматери"," — як один endpoint може повертати дані у різних форматах залежно від Accept header.",[18724,18725,18726],"style",{},"html pre.shiki code .spJ8K, html code.shiki .spJ8K{--shiki-light:#008000;--shiki-default:#6A9955;--shiki-dark:#6A9955}html pre.shiki code .s8Opu, html code.shiki .s8Opu{--shiki-light:#795E26;--shiki-default:#DCDCAA;--shiki-dark:#DCDCAA}html pre.shiki code .sHH4Y, html code.shiki .sHH4Y{--shiki-light:#000000;--shiki-default:#D4D4D4;--shiki-dark:#D4D4D4}html pre.shiki code .siwwj, html code.shiki .siwwj{--shiki-light:#001080;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJj4R, html code.shiki .sJj4R{--shiki-light:#098658;--shiki-default:#B5CEA8;--shiki-dark:#B5CEA8}html pre.shiki code .sN1BT, html code.shiki .sN1BT{--shiki-light:#267F99;--shiki-default:#4EC9B0;--shiki-dark:#4EC9B0}html pre.shiki code .sbdoH, html code.shiki .sbdoH{--shiki-light:#A31515;--shiki-default:#CE9178;--shiki-dark:#CE9178}html pre.shiki code .su1O8, html code.shiki .su1O8{--shiki-light:#0000FF;--shiki-default:#569CD6;--shiki-dark:#569CD6}html pre.shiki code .sCDza, html code.shiki .sCDza{--shiki-light:#AF00DB;--shiki-default:#CE92A4;--shiki-dark:#CE92A4}html pre.shiki code .sD7JJ, html code.shiki .sD7JJ{--shiki-light:#000000FF;--shiki-default:#D4D4D4;--shiki-dark:#D4D4D4}html pre.shiki code .s0P7L, html code.shiki .s0P7L{--shiki-light:#800000;--shiki-default:#808080;--shiki-dark:#808080}html pre.shiki code .sKtos, html code.shiki .sKtos{--shiki-light:#800000;--shiki-default:#569CD6;--shiki-dark:#569CD6}html pre.shiki code .sa4r_, html code.shiki .sa4r_{--shiki-light:#E50000;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}html pre.shiki code .sjcCO, html code.shiki .sjcCO{--shiki-light:#EE0000;--shiki-default:#D7BA7D;--shiki-dark:#D7BA7D}html pre.shiki code .sLwNe, html code.shiki .sLwNe{--shiki-light:#0451A5;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}",{"title":3154,"searchDepth":3168,"depth":3168,"links":18728},[18729,18732,18737,18746,18753,18760,18766,18778,18779],{"id":2961,"depth":3168,"text":2962,"children":18730},[18731],{"id":3040,"depth":3189,"text":3041},{"id":3113,"depth":3168,"text":3114,"children":18733},[18734,18735,18736],{"id":3117,"depth":3189,"text":3118},{"id":3832,"depth":3189,"text":3833},{"id":4321,"depth":3189,"text":4322},{"id":5151,"depth":3168,"text":5152,"children":18738},[18739,18740,18741,18742,18743,18744,18745],{"id":5161,"depth":3189,"text":5162},{"id":5168,"depth":3189,"text":5169},{"id":5231,"depth":3189,"text":5232},{"id":5639,"depth":3189,"text":5640},{"id":6357,"depth":3189,"text":6358},{"id":7094,"depth":3189,"text":7095},{"id":7706,"depth":3189,"text":7707},{"id":12103,"depth":3168,"text":12104,"children":18747},[18748,18749,18750,18751,18752],{"id":12110,"depth":3189,"text":12111},{"id":12237,"depth":3189,"text":12238},{"id":12803,"depth":3189,"text":12804},{"id":13280,"depth":3189,"text":13281},{"id":13836,"depth":3189,"text":13837},{"id":14107,"depth":3168,"text":14108,"children":18754},[18755,18756,18757,18758,18759],{"id":14118,"depth":3189,"text":14119},{"id":14274,"depth":3189,"text":14275},{"id":14504,"depth":3189,"text":14505},{"id":14679,"depth":3189,"text":14680},{"id":14980,"depth":3189,"text":14981},{"id":15259,"depth":3168,"text":15260,"children":18761},[18762,18763,18764,18765],{"id":15273,"depth":3189,"text":15274},{"id":15408,"depth":3189,"text":15409},{"id":15426,"depth":3189,"text":15427},{"id":15532,"depth":3189,"text":15533},{"id":15747,"depth":3168,"text":15748,"children":18767},[18768,18769,18770,18771,18772,18773,18774,18775,18776,18777],{"id":15754,"depth":3189,"text":15755},{"id":15760,"depth":3189,"text":15761},{"id":15810,"depth":3189,"text":15811},{"id":15863,"depth":3189,"text":15864},{"id":16145,"depth":3189,"text":16146},{"id":16151,"depth":3189,"text":16152},{"id":16597,"depth":3189,"text":16598},{"id":17106,"depth":3189,"text":17107},{"id":17112,"depth":3189,"text":17113},{"id":17995,"depth":3189,"text":17996},{"id":18596,"depth":3168,"text":18597},{"id":18681,"depth":3168,"text":18682},"Глибоке занурення в ієрархію результатів ASP.NET Core Web API. Типи повернення, HTTP-коди, ProducesResponseType та патерни формування відповідей.","md",null,{},{"title":1299,"description":18780},"IXoLTa9k1layT0D_RaRx7qoIVc7Ru3oNEo8unhF5bZg",[18787,18789],{"title":1295,"path":1296,"stem":1297,"description":18788,"children":-1},"Еволюція від endpoint-орієнтованого підходу до структурованої архітектури Web API Controllers. Порівняння парадигм, міграційні патерни та обґрунтування вибору підходу.",{"title":1303,"path":1304,"stem":1305,"description":18790,"children":-1},"Механізм узгодження формату відповіді між клієнтом та сервером. System.Text.Json vs Newtonsoft.Json, XML-серіалізація та створення кастомних форматерів для CSV, YAML, MessagePack.",1777912427295]