{"id":462832,"date":"2025-06-10T21:00:29","date_gmt":"2025-06-10T21:00:29","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=462832"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=462832","title":{"rendered":"<span>Minimal API: \u0418\u0437\u0431\u0430\u0432\u043b\u044f\u0435\u043c\u0441\u044f \u043e\u0442 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0430\u044e\u0449\u0438\u0445 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0432 ASP.NET Core<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u042f, \u0434\u0443\u043c\u0430\u044e, \u043c\u043d\u043e\u0433\u0438\u0435 \u0443\u0436\u0435 \u0441\u043b\u044b\u0448\u0430\u043b\u0438 \u043e \u043f\u043e\u044f\u0432\u0438\u0432\u0448\u0438\u0445\u0441\u044f \u0432 .NET 6 Minimal API &#8212; \u043b\u0435\u0433\u043a\u043e\u0432\u0435\u0441\u043d\u043e\u0439 \u0437\u0430\u043c\u0435\u043d\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432\/MVC. \u041a\u0442\u043e-\u0442\u043e \u0443\u0436\u0435 \u0443\u0441\u043f\u0435\u043b \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0438 \u0437\u0430\u0434\u0430\u043b\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c: &#171;\u0412\u0430\u0448\u0435 API \u0432 3 \u0441\u0442\u0440\u043e\u0447\u043a\u0438, \u044d\u0442\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0437\u0434\u043e\u0440\u043e\u0432\u043e, \u043d\u043e \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0441 \u0441\u043e\u0442\u043d\u044f\u043c\u0438 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432, \u043a\u0443\u0447\u0435\u0439 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432, \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432, \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438 OpenAPI\/Swagger \u0438 \u043f\u0440\u043e\u0447\u0438\u0445 \u0440\u0430\u0434\u043e\u0441\u0442\u044f\u0445?&#187;<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0447\u0443 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u044d\u0442\u043e\u0442 \u0432\u043e\u043f\u0440\u043e\u0441: \u043f\u0440\u043e\u0439\u0434\u0435\u043c\u0441\u044f \u043e\u0442 \u043e\u0441\u043d\u043e\u0432, \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432, \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u043e\u0432, \u0438 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043c \u043d\u044e\u0430\u043d\u0441\u0430\u043c\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442 \u043f\u0440\u0438 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u043d\u0430 Minimal API \u0432 \u043a\u0440\u0443\u043f\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<p>\u0410 \u0437\u0430\u0431\u0435\u0433\u0430\u044f \u0447\u0443\u0442\u044c \u0432\u043f\u0435\u0440\u0435\u0434: \u0435\u0441\u043b\u0438 \u0434\u0443\u043c\u0430\u0435\u0442\u0435, \u0441\u0442\u043e\u0438\u0442 \u043b\u0438 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 Mini API, \u0432\u043e\u0442 \u0432\u0430\u043c \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f: \u043e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0436\u0438\u0442\u044c \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0432\u043c\u0435\u0441\u0442\u0435, \u043f\u0440\u0438\u0447\u0435\u043c \u0434\u0430\u0436\u0435 \u0431\u0435\u0437 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b: \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u0432\u0441\u0435 \u0440\u0430\u0437\u043e\u043c &#8212; \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c.<\/p>\n<p>\u0411\u043e\u043d\u0443\u0441\u043e\u043c, \u0437\u0430\u043c\u0435\u043d\u0438\u043c SwaggerGen \u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e OpenAPI \u043e\u0442 Microsoft.<\/p>\n<h2>\u0417\u0430\u0447\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Minimal API?<\/h2>\n<p>\u041c\u044b \u0441 \u0432\u0430\u043c\u0438, (\u043d\u0430\u0434\u0435\u044e\u0441\u044c) \u043d\u0435 \u0433\u043e\u043d\u0438\u043c\u0441\u044f \u0437\u0430 \u043c\u043e\u0434\u043d\u044b\u043c\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u0430\u043c\u0438 &#171;\u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e&#187;, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f, \u0437\u0430\u0447\u0435\u043c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043d\u0430 Minimal API:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d8f\/76b\/341\/d8f76b341d70cff42aeca30849ba1346.png\" alt=\"\u0418\u0437 \u0441\u0442\u0430\u0442\u044c\u0438 https:\/\/piyushdoorwar.medium.com\/how-to-use-minimal-apis-in-net-8-without-cluttering-program-cs-e6ea1d513137  \" title=\"\u0418\u0437 \u0441\u0442\u0430\u0442\u044c\u0438 https:\/\/piyushdoorwar.medium.com\/how-to-use-minimal-apis-in-net-8-without-cluttering-program-cs-e6ea1d513137  \" width=\"1225\" height=\"879\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d8f\/76b\/341\/d8f76b341d70cff42aeca30849ba1346.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d8f\/76b\/341\/d8f76b341d70cff42aeca30849ba1346.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0418\u0437 \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/piyushdoorwar.medium.com\/how-to-use-minimal-apis-in-net-8-without-cluttering-program-cs-e6ea1d513137\" rel=\"noopener noreferrer nofollow\">https:\/\/piyushdoorwar.medium.com\/how-to-use-minimal-apis-in-net-8-without-cluttering-program-cs-e6ea1d513137<\/a>  <\/figcaption><\/div>\n<\/figure>\n<ul>\n<li>\n<p>\u041f\u0440\u043e\u0441\u0442\u043e\u0442\u0430 \u0438 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c.<br \/>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b \u043f\u043e\u0434 <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/mvc\/overview?view=aspnetcore-9.0\" rel=\"noopener noreferrer nofollow\">MVC<\/a>, Mini API \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434 API \/ <a href=\"https:\/\/deviq.com\/design-patterns\/repr-design-pattern\" rel=\"noopener noreferrer nofollow\">REPR<\/a> \u043f\u0430\u0442\u0442\u0435\u0440\u043d. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u043f\u043e\u0434 \u043d\u0443\u0436\u0434\u044b \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0438 \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 Microsoft<br \/>\u0420\u0435\u0444\u0435\u0440\u0435\u043d\u0441\u043d\u044b\u0439 <a href=\"https:\/\/github.com\/dotnet\/eShop\" rel=\"noopener noreferrer nofollow\">eShop<\/a> \u0443\u0436\u0435 \u043f\u0435\u0440\u0435\u0448\u0435\u043b \u043d\u0430 Mini API, \u0430 \u043f\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c <a href=\"http:\/\/ASP.NET\" rel=\"noopener noreferrer nofollow\">ASP.NET<\/a> Core <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/release-notes\/aspnetcore-9.0?view=aspnetcore-9.0#minimal-apis\" rel=\"noopener noreferrer nofollow\">9<\/a> \u0438 <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/release-notes\/aspnetcore-10.0?view=aspnetcore-9.0#minimal-apis\" rel=\"noopener noreferrer nofollow\">10<\/a> \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 Mini API \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442 \u043d\u043e\u0432\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 &#8212; \u043a\u0443\u0434\u0430 \u0430\u043a\u0442\u0438\u0432\u043d\u0435\u0435, \u0447\u0435\u043c \u0434\u043b\u044f MVC. \u0412\u043e \u043c\u043d\u043e\u0433\u043e\u043c, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u044d\u0442\u043e \u043e\u0431\u0443\u0441\u043b\u043e\u0432\u043b\u0435\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445, \u043d\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430. \u0421\u0443\u0431\u044a\u0435\u043a\u0442\u0438\u0432\u043d\u043e, \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0434\u0432\u0438\u0436\u0443\u0442\u0441\u044f \u0432 \u0441\u0442\u0430\u0442\u0443\u0441 \u043b\u0435\u0433\u0430\u0441\u0438. \u041e\u0447\u0435\u043d\u044c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0432\u0440\u044f\u0434 \u043b\u0438 \u043e\u043d\u0438 \u0441\u0442\u0430\u043d\u0443\u0442 deprecated \u0432 \u043a\u0430\u043a\u043e\u043c-\u043d\u0438\u0431\u0443\u0434\u044c .Net 11 (\u0441\u043a\u043e\u0440\u0435\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0432 .Net 15 &#8212; \u0434\u0430\u043c \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0433\u043d\u043e\u0437. \u0418 \u0442\u043e, \u044d\u0442\u043e \u0434\u043b\u044f \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u043b\u0435\u0433\u0430\u0441\u0438, \u0431\u0435\u0437 \u0432\u044b\u043f\u0438\u043b\u0438\u0432\u0430\u043d\u0438\u044f \u0438\u0437 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430). \u0418 \u044d\u0442\u043e \u043c\u043e\u0435 \u0441\u0443\u0431\u044a\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u043e\u0449\u0443\u0449\u0435\u043d\u0438\u0435: \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u0439 \u043e\u0442 Microsoft \u043d\u0430 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443 \u043d\u0435 \u0431\u044b\u043b\u043e, \u043b\u0438\u0448\u044c \u043a\u043e\u0441\u0432\u0435\u043d\u043d\u044b\u0435 \u043e \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0438 Mini API.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0445\u043e\u0436\u0435\u0441\u0442\u044c \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430\u043c\u0438<br \/>\u041d\u0430\u043c \u043d\u0435 \u043f\u0440\u0438\u0432\u044b\u043a\u0430\u0442\u044c \u043a \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u043c, \u043d\u043e \u0443 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u0440\u0443\u043f\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432 &#8212; JS (Fastify\/Express), Python (Flask, FastAPI), Go (Gin), \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435, \u0443\u0436\u0435 \u0434\u0430\u0432\u043d\u043e \u0435\u0441\u0442\u044c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u043f\u043e \u0441\u0445\u043e\u0436\u0435\u0439 \u0441\u0445\u0435\u043c\u0435 \u0441 MinimalAPI. \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u0441 \u044f\u0437\u044b\u043a\u0430 \u043d\u0430 \u044f\u0437\u044b\u043a \u043b\u0435\u0433\u0447\u0435, \u0430 \u0432\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u044d\u0442\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043d\u0430\u043c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0438 \u0431\u0435\u0437 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0436\u0438\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0438<br \/>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434\u044b, \u044f\u0432\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0432 \u0432\u0430\u0448\u0435\u043c \u043a\u043e\u0434\u0435, \u0430 \u043d\u0435 \u043f\u043e\u0438\u0441\u043a\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u043f\u043e \u0432\u0441\u0435\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044e \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u044b \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u043e (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b \u043d\u0435 \u0437\u0430\u043f\u0438\u0445\u043d\u0435\u0442\u0435 \u0432 \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442 \u043c\u0430\u0441\u0441\u0438\u0432, \u0438\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u043a\u043e\u043d\u0444\u0438\u0433\u0430), \u0430 \u0442\u0430\u043a\u0436\u0435 \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0435\u0442 \u0435\u0449\u0435 2 \u043f\u043b\u044e\u0441\u0430:<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/fundamentals\/native-aot?view=aspnetcore-9.0\" rel=\"noopener noreferrer nofollow\">NativeAOT<\/a> <br \/>NativeAOT &#8212; \u0441\u0435\u0439\u0447\u0430\u0441 \u0442\u0440\u0435\u043d\u0434 \u0432 \u043c\u0438\u0440\u0435 .Net, \u0438 \u0432\u0440\u044f\u0434 \u043b\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442 \u0435\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0438 \u043e\u0442 Mini API, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u043d\u0430 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c. \u0412\u043f\u0440\u043e\u0447\u0435\u043c, \u0431\u044d\u043a\u0435\u043d\u0434 &#8212; \u044d\u0442\u043e \u0442\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c, \u0433\u0434\u0435 NativeAOT \u043c\u043e\u0436\u0435\u0442 \u0443\u0445\u0443\u0434\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c. \u0412\u043e\u043e\u0431\u0449\u0435, \u044d\u0442\u043e \u0442\u0435\u043c\u0430 \u0434\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438, \u043d\u043e <a href=\"https:\/\/bitmiracle.com\/pdf-library\/howto\/native-aot-performance\" rel=\"noopener noreferrer nofollow\">\u0432\u043e\u0442<\/a> \u0432\u0430\u043c \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435, \u0438 <a href=\"https:\/\/www.reddit.com\/r\/dotnet\/comments\/zoxhkp\/comment\/j0pmo0t\/?utm_source=share&amp;utm_medium=web3x&amp;utm_name=web3xcss&amp;utm_term=1&amp;utm_content=share_button\" rel=\"noopener noreferrer nofollow\">\u0432\u043e\u0442<\/a> \u043a\u0440\u0430\u0442\u043a\u043e\u0435 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0435\u043c\u0443. \u041d\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c\u0441\u044f &#8212; .Net \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u043e.<\/p>\n<\/li>\n<li>\n<p>\u0423\u043b\u0443\u0447\u0448\u0435\u043d\u043d\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c<br \/><a href=\"https:\/\/dev.to\/stevsharp\/minimal-api-performance-benchmark-14ln\" rel=\"noopener noreferrer nofollow\">\u0412\u043e\u0442<\/a> \u0438 <a href=\"https:\/\/steven-giesel.com\/blogPost\/698c45c3-58c5-4157-b4da-2cde4e27862e\" rel=\"noopener noreferrer nofollow\">\u0432\u043e\u0442<\/a> \u0432\u0430\u043c \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0438. \u0421\u043f\u043e\u0439\u043b\u0435\u0440: \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043e\u0432 \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u043d\u0430 \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043e\u0432 \u043f\u043e \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438. \u0412 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0431\u041e\u043b\u044c\u0448\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0430\u0448 \u043a\u043e\u0434, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0436\u0434\u0430\u0442\u044c \u0441\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044f RPS \u043d\u0435 \u0441\u0442\u043e\u0438\u0442. \u041d\u043e \u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u0441 \u0434\u0435\u0441\u044f\u0442\u043a\u0430\u043c\u0438 \u0438 \u0441\u043e\u0442\u043d\u044f\u043c\u0438 \u0442\u044b\u0441\u044f\u0447 RPS, \u0433\u0434\u0435 \u0432\u044b \u043e\u0442\u0447\u0430\u044f\u043d\u043d\u043e \u0431\u043e\u0440\u0435\u0442\u0435\u0441\u044c \u0437\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 GC, \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u0438\u0445 \u043d\u0430 Mini API \u043c\u043e\u0436\u0435\u0442 \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043d\u0435\u043f\u043b\u043e\u0445\u043e\u0439 \u0438\u0434\u0435\u0435\u0439, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044f \u0442\u0440\u0435\u043d\u0434 \u043d\u0430 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 .Net.<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438:<\/p>\n<ul>\n<li>\n<p>\u041d\u0435 \u0432\u0435\u0441\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u043f\u043e\u043a\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d<br \/>\u0412 <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/fundamentals\/apis?view=aspnetcore-9.0\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435 Microsoft<\/a> \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0447\u0435\u0433\u043e \u043f\u043e\u043a\u0430 \u043d\u0435\u0442. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 &#8212; \u044d\u0442\u043e \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f (\u0440\u0435\u0448\u0430\u0435\u043c\u043e, \u043d\u0430\u043f\u0438\u0448\u0443 \u043f\u0440\u043e \u044d\u0442\u043e \u043d\u0438\u0436\u0435) \u0438 \u043d\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 View \u0438\u0437 MVC (\u043d\u043e Razor Pages \u0435\u0441\u0442\u044c) <\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u043d\u043e\u0441 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 &#8212; \u0434\u043d\u0438\/\u043d\u0435\u0434\u0435\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u044b<br \/>\u0414\u0430\u0436\u0435 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u043f\u0435\u0440\u0432\u044b\u0439 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043c\u043e\u0436\u0435\u0442 \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u043d\u0430 \u0434\u0435\u043d\u0435\u043a-\u0434\u0440\u0443\u0433\u043e\u0439: \u0438\u0437-\u0437\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0432\u0441\u0435 \u0432\u0430\u0448\u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u044b, \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0438 \u0442.\u043f. \u0414\u0430\u043b\u044c\u0448\u0435 \u043f\u043e\u0439\u0434\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u043d\u043e \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u0445\u0432\u0430\u0442\u0438\u0442. \u041c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c Cursor \u043d\u0430\u0442\u0440\u0430\u0432\u0438\u0442\u044c \u043d\u0430 \u044d\u0442\u043e \u0434\u0435\u043b\u043e &#8212; \u0435\u0441\u0442\u044c \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c \u0447\u0442\u043e \u043f\u0440\u043e\u043a\u0430\u0442\u0438\u0442.<\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0442\u043e\u0433\u043e, \u043c\u043e\u0435 \u043b\u0438\u0447\u043d\u043e\u0435 \u043c\u043d\u0435\u043d\u0438\u0435: \u0435\u0441\u043b\u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\/\u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0441 \u043f\u0440\u0438\u0446\u0435\u043b\u043e\u043c \u043d\u0430 .Net 10 (\u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u043d\u0430\u0434 \u043f\u043e\u043a\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c), \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u0441\u0442\u043e\u0438\u0442. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u044d\u043d\u0442\u0435\u0440\u043f\u0440\u0430\u0439\u0437 \u043f\u0440\u043e\u0435\u043a\u0442, \u0432\u0441\u0435 \u0438 \u0442\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0430 \u0432 \u0431\u044d\u043a\u043b\u043e\u0433\u0435 \u0438 \u0442\u0430\u043a \u043a\u0443\u0447\u0430 \u0437\u0430\u0434\u0430\u0447 \u043f\u043e \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0443, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u044b \u043d\u0435 \u0434\u0430\u044e\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043a\u0430 \u0438 \u043f\u043e\u0436\u0438\u0442\u044c \u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u043c\u0438. \u0415\u0441\u043b\u0438, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0438 NativeAOT \u043d\u0435 \u043d\u0443\u0436\u0435\u043d.<\/p>\n<h2>Hello World!<\/h2>\n<p>\u0414\u043b\u044f \u0442\u0435\u0445 \u043a\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u043a\u043e\u043c, \u0432 \u044d\u0442\u043e\u0439 \u0433\u043b\u0430\u0432\u0435 \u0432\u043a\u0440\u0430\u0442\u0446\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u0441 Mini API. \u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432  <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/tutorials\/min-web-api?view=aspnetcore-9.0&amp;tabs=visual-studio\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043e\u0442 Microsoft<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/habr.com\/ru\/companies\/otus\/articles\/666676\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0430 \u0445\u0430\u0431\u0440\u0435<\/a>. <\/p>\n<pre><code class=\"cs\">var app = WebApplication.CreateBuilder(args).Build();  app.MapGet(\"\/\", () =&gt; \"Hello World!\");  app.Run();<\/code><\/pre>\n<p>\u041a\u0440\u0430\u0441\u0438\u0432\u043e, \u043f\u0440\u0430\u0432\u0434\u0430? \u041d\u0443 \u043b\u0430\u0434\u043d\u043e, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u043c\u044b \u0432 Program.cs \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u043d\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0435\u043c. \u0414\u043e\u0431\u0430\u0432\u043b\u044e \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u0434 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u0438\u0437 \u0441\u0432\u043e\u0435\u0439 <a href=\"https:\/\/habr.com\/ru\/articles\/916704\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u0440\u043e VSA<\/a>. \u0412\u0432\u0435\u0434\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 IEndpoint \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432.<\/p>\n<pre><code class=\"cs\">public interface IEndpoint { void Register(IEndpointRouteBuilder endpointsBuilder); }<\/code><\/pre>\n<p>\u041d\u0430\u0448\u0438 \u043a\u043b\u0430\u0441\u0441\u044b \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441. \u0425\u043e\u0442\u0438\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435? \u041f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0439\u0442\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 IEndpoitns(Provider). Minimal API &#8212; \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0433\u0438\u0431\u043a\u0430\u044f \u0448\u0442\u0443\u043a\u0430, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0439\u0442\u0435 \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u043a \u0432\u0430\u0448\u0435\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0443.<br \/>\u0414\u043e\u0431\u0430\u0432\u0438\u043c extension \u0434\u043b\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"cs\">public static class EndpointsHelper {     public static IEndpointRouteBuilder Register&lt;T&gt;(this IEndpointRouteBuilder endpointsBuilder)        where T : IEndpoint, new()     {        var endpointsProvider = new T();        endpointsProvider.Register(endpointsBuilder);        return endpointsBuilder;     } }<\/code><\/pre>\n<p>\u0418, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b:<\/p>\n<pre><code class=\"cs\">public static class EndpointsProvider { public static void RegisterAppEndpoints(RouteGroupBuilder endpointsBuilder) { endpointsBuilder.Register&lt;GetUserCart&gt;(); } }<\/code><\/pre>\n<p>\u0425\u043e\u0442\u044f, \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438, \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u0435\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e Assembly \u0438 \u043d\u0430\u0439\u0442\u0438 \u0432\u0441\u0435 IEndpoint &#8212; \u043a\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445. \u041d\u043e \u044f \u0431\u044b \u043d\u0435 \u0441\u0442\u0430\u043b.<br \/>\u0418 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0433\u043e \u0432 Program.cs:<\/p>\n<pre><code class=\"cs\">\/\/ \u0412\u0441\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c\u0441\u044f \u0441 \/api var endpointsBuilder = app.MapGroup(\"\/api\"); EndpointsProvider.RegisterAppEndpoints(endpointsBuilder);<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c, \u0441\u0430\u043c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442:<\/p>\n<pre><code class=\"cs\">public class GetUserCart : IEndpoint {     public void Register(IEndpointRouteBuilder endpointsBuilder)     {         endpointsBuilder.MapGet(\"\/user\/cart\", HandleAsync)             \/\/ \u0410\u043d\u0430\u043b\u043e\u0433 \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u0430 [Authorize]             .RequireAuthorization()             \/\/ \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430 \u0434\u043b\u044f OpenAPI. \u0412 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445 \u043e\u0431\u044b\u0447\u043d\u043e \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 XML (\/\/\/ &lt;summary&gt;). \u0422\u0435\u043f\u0435\u0440\u044c \u044d\u0442\u043e \u0432 \u043a\u043e\u0434\u0435.             .WithSummary(\"Search all available platforms.\")             \/\/ \u0422\u044d\u0433 \u0434\u043b\u044f OpenAPI. \u041e\u0431\u044b\u0447\u043d\u043e \u044d\u0442\u043e \u0438\u043c\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430.             .WithTags(\"User\");     }      \/\/ OpenAPI \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0442\u0438\u043f\u0430.     private static async Task&lt;QueryableList&lt;UserCartItem&gt;&gt; HandleAsync(int skip, int take, UserContext userContext, ExampleDbContext db, CancellationToken ct)     {         var total = await db.CartItems.CountAsync(x =&gt; x.UserId == userContext.UserId, ct);         if (total == 0)             return QueryableList&lt;UserCartItem&gt;.Empty();                  var items = await db.CartItems.Where(x =&gt; x.UserId == userContext.UserId)             .Select(x =&gt; new UserCartItem             {                 Id = x.ItemId,                 Name = x.Item.Name,             })             .Skip(skip)             .Take(take)             .ToListAsync(ct);          return new QueryableList&lt;UserCartItem&gt;(items, total);     } }<\/code><\/pre>\n<p>(\u042f \u0443\u043f\u0443\u0449\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0411\u0414 \u0438 \u043f\u0440\u043e\u0447\u0438\u0445 \u0440\u0430\u0434\u043e\u0441\u0442\u0435\u0439 \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0440\u0430\u0437\u0434\u0443\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e) skip \u0438 take \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b \u0438\u0437 query string, \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0437\u0430\u0440\u0435\u0437\u043e\u043b\u0432\u0438\u0442 DI. <br \/>\u041c\u043d\u043e\u0433\u043e skip-take \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 \u043e\u0431\u0449\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f? \u041f\u043e\u043c\u043e\u0436\u0435\u0442 \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442 [AsParameters]:<\/p>\n<pre><code class=\"cs\">private static async Task&lt;QueryableList&lt;UserCartItem&gt;&gt; HandleAsync([AsParameters]PagingQuery paging, UserContext userContext, ExampleDbContext db, CancellationToken ct) ... public record PagingQuery { [FromQuery(Name = \"take\")]     public int Take { get; init; } = 10; [FromQuery(Name = \"skip\")]     public int Skip { get; init; } }<\/code><\/pre>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u0431\u0438\u043d\u0434\u0438\u043d\u0433\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/fundamentals\/minimal-apis\/parameter-binding?view=aspnetcore-9.0\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435 Microsoft<\/a>.<br \/>\u0414\u0432\u0438\u0436\u0435\u043c\u0441\u044f \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<h2>\u0417\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u044b<\/h2>\n<p>\u0412 Minimal API \u0435\u0441\u0442\u044c \u0432\u0430\u0436\u043d\u0430\u044f \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f &#8212; \u043c\u0435\u0442\u0430\u0434\u0430\u0442\u0430. \u042d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442 \u043d\u0430\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445: \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0443 \u043c\u0435\u0442\u0430\u0434\u0430\u0442\u0443 \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0435\u0435 \u0432 \u043d\u0430\u0448\u0438\u0445 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0445.<br \/>\u0417\u0430\u0431\u0435\u0433\u0430\u044f \u0432\u043f\u0435\u0440\u0435\u0434 &#8212; \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0442\u043e\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u0435\u0442\u0430\u0434\u0430\u0442\u0443!<br \/>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0445\u043e\u0442\u0438\u043c \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u0435. \u0414\u0435\u043b\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441:<\/p>\n<pre><code class=\"cs\">public class ProhibitInProductionMetadata;<\/code><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0432 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 (\u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430 &#8212; \u043c\u043e\u0436\u043d\u043e \u0434\u0430\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0435 extension):<\/p>\n<pre><code class=\"cs\">endpointsBuilder.MapGet(\"\/user\/cart\", HandleAsync) .WithMetadata(new ProhibitInProductionMetadata()))<\/code><\/pre>\n<p>\u0410, \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443, \u0441\u0440\u0430\u0437\u0443 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u043c<\/p>\n<h3>\u0424\u0438\u043b\u044c\u0442\u0440\u044b<\/h3>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u044b\u0448\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0444\u0438\u043b\u044c\u0442\u0440:<\/p>\n<pre><code class=\"cs\">public class ProhibitInProductionFilter(EnvironmentConfig envConfig) : IEndpointFilter { public async ValueTask&lt;object?&gt; InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next) { var endpoint = context.HttpContext.GetEndpoint(); if (endpoint == null || envConfig.Environment != EnvironmentType.Production) return await next(context);  \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u0442\u044b \u0443 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430 var metadata = endpoint.Metadata.GetMetadata&lt;ProhibitInProductionMetadata&gt;(); if (metadata == null) return await next(context);  \/\/ \u041c\u0435\u0442\u0430\u0434\u0430\u0442\u0430 \u0435\u0441\u0442\u044c, Production \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c 404         return Results.NotFound(); } }<\/code><\/pre>\n<p>\u0418 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u043b\u0441\u044f \u043a\u043e \u0432\u0441\u0435\u043c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430\u043c, \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0432 \u043a\u043e\u0434 \u0438\u0437 \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"cs\">var endpointsBuilder = app.MapGroup(\"\/api\")     .AddEndpointFilter&lt;ProhibitInProductionFilter&gt;(); EndpointsProvider.RegisterAppEndpoints(endpointsBuilder);<\/code><\/pre>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e. \u0412\u043e\u0442 \u0438 \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043b\u0438\u0441\u044c \u0441 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u043c\u0438 \u0432 Minimal API.<br \/>\u041f\u0440\u0430\u0432\u0434\u0430, \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043b\u0438\u0441\u044c. \u041d\u0430\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0432\u0441\u043f\u043e\u043c\u0438\u043d\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0432\u043e\u0442 \u044d\u0442\u0438 \u0432\u0441\u0435 IAuthorizationFilter\/IActionFilter\/IExceptionFilter \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u0412\u0435\u0441\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u044f \u043e\u0442 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430.<br \/>\u041f\u0430\u0440\u0430 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u043d\u044e\u0430\u043d\u0441\u043e\u0432:<\/p>\n<ul>\n<li>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u044b\u0448\u0435, AddEndpointFilter() \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u043a \u043e\u0434\u043d\u043e\u043c\u0443, \u0433\u0440\u0443\u043f\u043f\u0435, \u0438\u043b\u0438 \u043a\u043e \u0432\u0441\u0435\u043c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430\u043c &#8212; \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0430\u0448\u0438\u0445 \u043d\u0443\u0436\u0434<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u0435 \u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432? \u042d\u0442\u043e\u0442 \u0436\u0435 \u0444\u0438\u043b\u044c\u0442\u0440 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0438 \u043a \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u043c:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cs\">app.MapControllers()     .AddEndpointFilter(new ProhibitInProductionFilter());<\/code><\/pre>\n<p>\u0410, \u0437\u0430\u043c\u0435\u043d\u0438\u0432 \u043d\u0430\u0448 ProhibitInProductionMetadata \u043d\u0430 \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442, \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0435\u0433\u043e \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440, \u043e\u043d \u0443\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u0443 \u043d\u0430\u0441 \u0432 \u043c\u0435\u0442\u0430\u0434\u0430\u0442\u0435:<\/p>\n<pre><code class=\"cs\">var metadata = endpoint.Metadata.GetMetadata&lt;ProhibitInProductionMetadataAttribute&gt;();<\/code><\/pre>\n<p>\u041e\u0442\u0441\u044e\u0434\u0430 \u0432\u044b\u0432\u043e\u0434: \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u0430\u0432 \u0432\u0430\u0448\u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u043d\u0430 IEndpointFilter, \u043e\u043d\u0438 \u0441\u043c\u043e\u0433\u0443\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438 \u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u043c\u0438, \u0438 \u0441 Mini API \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e.<br \/>\u0411\u043e\u043b\u044c\u0448\u0435 \u0434\u0435\u0442\u0430\u043b\u0435\u0439 \u0432 <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/fundamentals\/minimal-apis\/min-api-filters?view=aspnetcore-9.0\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>.<\/p>\n<h2>Middleware<\/h2>\n<p>\u0422\u0443\u0442 \u0432\u0441\u0435 \u0435\u0449\u0435 \u043f\u0440\u043e\u0449\u0435 &#8212; \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f. \u0414\u043b\u044f \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0438\u043c\u0435\u0440 &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c Middleware \u0434\u043b\u044f \u043b\u043e\u0433\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<pre><code class=\"cs\">public class RequestLoggingMiddleware(RequestDelegate next, ILogger&lt;RequestLoggingMiddleware&gt; log) {     public async Task InvokeAsync(HttpContext context)     { var url = context.Request.GetDisplayUrl();         log.LogTrace(\"Started {RequestId} | Url: {Url}\", context.TraceIdentifier, url); await next(context);     } }  ... \/\/ \u0412 Program.cs app.UseMiddleware&lt;RequestLoggingMiddleware&gt;();<\/code><\/pre>\n<p>\u0412\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0441 <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/fundamentals\/middleware\/?view=aspnetcore-9.0\" rel=\"noopener noreferrer nofollow\">app.Use()<\/a> \u0438 IMiddleware \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e <\/p>\n<h3>\u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f<\/h3>\n<p>\u0410 \u0432\u043e\u0442 \u0442\u0443\u0442 \u043f\u043e\u0441\u043b\u043e\u0436\u043d\u0435\u0435: \u0412 Minimal API \u043d\u0435\u0442 ModelState, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0435\u043d\u043d\u043e \u043a\u043e\u0440\u043e\u0431\u043e\u0447\u043d\u0430\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0435\u0441\u044c \u043d\u0430 \u043d\u0435\u0435 &#8212; \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u043e\u043a\u0430 \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u044b\u0432\u0430\u0442\u044c. \u0415\u0441\u043b\u0438 \u0436\u0435 \u0443 \u0432\u0430\u0441 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0441\u0432\u043e\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0447\u0435\u0440\u0435\u0437 \u0444\u0438\u043b\u044c\u0442\u0440\u044b\/middleware \u0438\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0432 \u043a\u043e\u0434\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 &#8212; \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0435\u0433\u043e \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<p>\u0418\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0432 <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/release-notes\/aspnetcore-10.0?view=aspnetcore-9.0#minimal-apis\" rel=\"noopener noreferrer nofollow\">.Net 10<\/a>, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c Mini API \u0441\u0440\u0430\u0437\u0443 \u043d\u0430 .Net 10, \u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0435 \u043d\u0438\u0436\u0435 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e. \u0410 \u043f\u043e\u043a\u0430 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043a\u0430\u043a \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441:<br \/>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442:<\/p>\n<pre><code class=\"cs\">endpointsBuilder.MapPut(\"\/items\/create\", HandleAsync) .RequireAuthorization() .WithTags(\"Items\"); ... \/\/ .Net \u043f\u043e\u0439\u043c\u0435\u0442, \u0447\u0442\u043e CreateItemRequest - \u044d\u0442\u043e \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043d\u043e \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u044f\u0432\u043d\u043e \u043f\u043e\u043c\u0435\u0442\u0438\u0442\u044c \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c private async Task&lt;IResult&gt; HandleAsync(CreateItemRequest item) ... public record CreateItemRequest {     public required string Name { get; init; }     public required int Price { get; init; } }<\/code><\/pre>\n<p>\u041c\u043e\u0436\u043d\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u044f\u043c\u043e \u0432 HandleAsync()<\/p>\n<pre><code class=\"cs\">if (item.Name.Length &lt; 3) return Results.BadRequest(\"Item name must be at least 3 characters long.\");<\/code><\/pre>\n<p>\u0425\u043e\u0442\u044f \u0442\u0443\u0442 \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c null \u0432 &#171;Name&#187;, \u043f\u043e\u043b\u0443\u0447\u0438\u043c NullReferenceException \u0438 500 \u043e\u0448\u0438\u0431\u043a\u0443: \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0435 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 nullable reference types \u043d\u0435 \u0443\u0432\u0430\u0436\u0430\u0435\u043c, \u043d\u0435\u043f\u043e\u0440\u044f\u0434\u043e\u043a.<br \/>\u041d\u043e \u0445\u043e\u0440\u043e\u0448\u0430\u044f \u043d\u043e\u0432\u043e\u0441\u0442\u044c: <a href=\"https:\/\/github.com\/FluentValidation\/FluentValidation\" rel=\"noopener noreferrer nofollow\">FluentValidation<\/a>, \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435\u0441\u044c, \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u0441 Minimal API. \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430:<\/p>\n<pre><code class=\"cs\">public class CreateItemValidator : AbstractValidator&lt;CreateItemRequest&gt; {     public CreateItemValidator()     {         RuleFor(x =&gt; x.Name).NotEmpty().Length(3, 100);         RuleFor(x =&gt; x.Price).GreaterThan(0).LessThanOrEqualTo(1000);     } } ... \/\/ \u0412 Program.cs: builder.Services.AddScoped&lt;IValidator&lt;CreateItemRequest&gt;, CreateItemValidator&gt;(); ... private async Task&lt;IResult&gt; HandleAsync(IValidator&lt;CreateItemRequest&gt; validator, CreateItemRequest item) {     var validationResult = await validator.ValidateAsync(item);     if (!validationResult.IsValid)         return     Results.ValidationProblem(validationResult.ToDictionary()); ...<\/code><\/pre>\n<p>\u0425\u043e\u0442\u044f \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/csharp\/language-reference\/keywords\/required\" rel=\"noopener noreferrer nofollow\">required<\/a> \u043f\u0440\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u043f\u043e\u043b\u044f &#171;name&#187; \u0432 body \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u043a\u0438\u043d\u0435\u0442 \u0441\u0432\u043e\u044e 400 \u043e\u0448\u0438\u0431\u043a\u0443 \u0434\u043e \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043a\u043e\u0434 \u0434\u043e\u0439\u0434\u0435\u0442 \u0434\u043e \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438. \u041d\u0443 \u0434\u0430 \u043b\u0430\u0434\u043d\u043e, \u043a\u0435\u0439\u0441 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0439 \u0438 \u043d\u0435 \u0432\u0441\u0435\u043c \u043d\u0443\u0436\u0435\u043d, \u043e\u0441\u0442\u0430\u0432\u043b\u044e \u0442\u0430\u043a.<br \/>\u0414\u0440\u0443\u0433\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434: <a href=\"https:\/\/github.com\/DamianEdwards\/MiniValidation\" rel=\"noopener noreferrer nofollow\">MiniValidation<\/a>, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u043d\u0430 System.ComponentModel.DataAnnotations, \u043f\u0440\u044f\u043c\u043e \u043a\u0430\u043a \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438. \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c:<\/p>\n<pre><code class=\"cs\">public record CreateItemRequest {     [Required, MinLength(3)]     public required string Name { get; init; }     [Required, Range(1, 1000)]     public required int Price { get; init; } } ... private async Task&lt;IResult&gt; HandleAsync(CreateItemRequest item) {     var isValid = MiniValidator.TryValidate(item, out var errors);     if (!isValid)         return Results.ValidationProblem(errors);<\/code><\/pre>\n<p>\u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u043f\u043b\u044e\u0441 MiniValidation &#8212; \u043e\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 DataAnnotations, \u0430 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442:<\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u0441 \u0442\u0435\u043a\u0443\u0449\u0438\u043c\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u043c\u0438<\/p>\n<\/li>\n<li>\n<p>\u0412 .Net 10 \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u0431\u0440\u0430\u0442\u044c \u0438 \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u043a\u043e\u0440\u043e\u0431\u043e\u0447\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c.<\/p>\n<\/li>\n<\/ul>\n<h2>OpenAPI\/Swagger \u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u044b<\/h2>\n<p>\u0427\u0443\u0442\u044c \u0432\u044b\u0448\u0435 \u044f \u0443\u0436\u0435 \u0437\u0430\u0442\u0440\u043e\u043d\u0443\u043b \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f OpenAPI, \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043f\u043e\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435<\/p>\n<p>\u0412\u043e\u043e\u0431\u0449\u0435 \u0441 .Net 9 Microsoft \u043f\u0435\u0440\u0435\u0448\u043b\u0430 \u0441\u043e SwaggerGen \u043d\u0430 \u0441\u0432\u043e\u0439 \u043f\u0430\u043a\u0435\u0442 Microsoft.AspNetCore.OpenApi \u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u0443\u0442\u0430\u0435\u0442\u0435 Swagger(UI\/Gen) \u0438 OpenAPI (\u044d\u0442\u0438 \u043f\u043e\u043d\u044f\u0442\u0438\u044f \u0431\u044b\u043b\u0438 \u0442\u0435\u0441\u043d\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439, \u0438 \u043d\u0435\u0439\u043c\u0438\u043d\u0433 \u043d\u0435 \u043f\u043e\u043c\u043e\u0433\u0430\u043b), \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0433\u043b\u044f\u043d\u0443\u0442\u044c \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u0432 <a href=\"https:\/\/github.com\/dotnet\/aspnetcore\/issues\/54599\" rel=\"noopener noreferrer nofollow\">\u044d\u0442\u043e\u0439 issue<\/a> \u0438 <a href=\"https:\/\/codewithmukesh.com\/blog\/dotnet-swagger-alternatives-openapi\/\" rel=\"noopener noreferrer nofollow\">\u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a>.<\/p>\n<p>\u0412\u043a\u0440\u0430\u0442\u0446\u0435, \u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438:<\/p>\n<ul>\n<li>\n<p>SwaggerGen, \u043a\u0430\u043a \u0438 OpenApi \u043e\u0442 Microsoft, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0442 \u043d\u0430\u043c \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 .json \u0441 API \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. Swagger UI &#8212; \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u044d\u0442\u043e\u0442 JSON \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0442\u044b\u043a\u0430\u0442\u044c\u0441\u044f \u0440\u0443\u0447\u043a\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e SwaggerGen \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u043a\u043e\u043c\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Microsoft.AspNetCore.OpenApi. \u041d\u043e \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u0437\u0430\u043f\u0440\u0435\u0449\u0430\u0435\u0442 \u043e\u0441\u0442\u0430\u0442\u044c\u0441\u044f \u043d\u0430 SwaggerGen: \u043f\u043e\u0434\u0434\u0435\u0440\u043a\u0430 MinimalAPI \u0435\u0441\u0442\u044c. \u0417\u0430\u0447\u0435\u043c \u0442\u043e\u0433\u0434\u0430 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c? \u0412 \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0436\u0438\u0434\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043d\u043e\u0432\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 .Net \u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 OpenAPI. \u041a\u0430\u043a \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043e\u043f\u044b\u0442, \u0445\u043e\u0442\u044c \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0442\u0430\u043a \u0438 \u0431\u0443\u0434\u0435\u0442, \u043d\u043e \u044d\u0442\u043e \u043d\u0435 \u0442\u043e\u0447\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p>Swagger UI \u0432\u0441\u0435 \u0435\u0449\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u0436\u0435 \u0431\u0435\u0437 SwaggerGen<\/p>\n<\/li>\n<li>\n<p>\u0410\u043a\u0442\u0438\u0432\u043d\u043e \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u044b Swagger UI, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 Scalar. \u041d\u0430 \u0445\u0430\u0431\u0440\u0435 \u0443\u0436\u0435 <a href=\"https:\/\/habr.com\/ru\/articles\/892508\/\" rel=\"noopener noreferrer nofollow\">\u0431\u044b\u043b\u0430 \u0441\u0442\u0430\u0442\u044c\u044f<\/a> \u043e \u043d\u0435\u043c.<\/p>\n<\/li>\n<\/ul>\n<p>Scalar \u0438\u043d\u0442\u0440\u0438\u0433\u0443\u0435\u0442, \u043d\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c\u0441\u044f \u043d\u0430 \u043f\u043e\u043b \u043f\u0443\u0442\u0438: \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0443\u0434\u0443 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c SwaggerGen \u0438 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u0435\u0433\u043e \u043d\u0430 Microsoft OpenAPI + Swagger UI.<br \/>\u0412\u043e\u0437\u044c\u043c\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u0433\u043e\u043b\u043e\u0432\u044b: \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c OpenAPI \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u0445\u044d\u0434\u0435\u0440\u044b \u0443 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432. \u0413\u0434\u0435-\u0442\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043f\u043e\u0434\u043e\u0439\u0434\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0430 \u0441 \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c [FromHeaders], \u043d\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0443\u0434\u043e\u0431\u043d\u043e.<\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u043e\u0433\u043e &#171;SwaggerGen + \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b&#187; \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<br \/>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442:<\/p>\n<pre><code class=\"cs\">[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)] public class ApiShowHeadersAttribute(params string[] headers) : Attribute {     public string[] Headers =&gt; headers; }<\/code><\/pre>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0444\u0438\u043b\u044c\u0442\u0440:<\/p>\n<pre><code class=\"cs\">public class ShowHeadersFilter : IOperationFilter {     public void Apply(OpenApiOperation operation, OperationFilterContext context)     {         \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442 ShowHeadersAttribute \u0438\u0437 \u043c\u0435\u0442\u043e\u0434\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430         var headersData = context.MethodInfo.GetCustomAttribute&lt;ApiShowHeadersAttribute&gt;();         if (headersData == null)             return;  operation.Parameters ??= new List&lt;OpenApiParameter&gt;();         foreach (var header in headersData.Headers)         {             \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0445\u044d\u0434\u0435\u0440\u0430 \u0432 OpenAPI \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e             operation.Parameters.Add(new OpenApiParameter             {                 Name = header,                 In = ParameterLocation.Header,                 Required = false,                 Schema = new OpenApiSchema() \/\/ \u041c\u043e\u0436\u043d\u043e \u0435\u0449\u0435 \u043a\u0440\u0430\u0441\u0438\u0432\u0443\u044e \u0441\u0445\u0435\u043c\u0443 \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c             });         }     } }<\/code><\/pre>\n<p>\u0418 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u044d\u0442\u043e\u0442 \u0444\u0438\u043b\u044c\u0442\u0440 \u0432 \u043d\u0430\u0448 services.AddSwaggerGen(). \u0412 OpenAPI \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u044f\u0442\u0441\u044f \u043d\u0443\u0436\u043d\u044b\u0435 \u0445\u044d\u0434\u0435\u0440\u044b.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0434\u043b\u044f Mini API, \u043f\u0440\u0438\u0447\u0435\u043c \u043c\u044b \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0444\u0438\u043b\u044c\u0442\u0440: \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438 \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432, \u0438 \u0434\u043b\u044f Mini API<br \/>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0442\u0430\u043a\u0443\u044e \u0441\u0442\u0440\u043e\u0447\u043a\u0443 \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u044d\u043d\u043f\u043e\u0438\u043d\u0442\u0443:<\/p>\n<pre><code class=\"cs\">endpointsBuilder.MapGet(\"\/user\/cart\", HandleAsync) .WithMetadata(new ApiShowHeadersAttribute(\"X-Custom-Header\"))<\/code><\/pre>\n<p>\u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0432 \u0444\u0438\u043b\u044c\u0442\u0440\u0435 \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u0442\u044b:<\/p>\n<pre><code class=\"cs\">var headersData = context.ApiDescription.ActionDescriptor.EndpointMetadata     .OfType&lt;ApiShowHeadersAttribute&gt;()     .FirstOrDefault();<\/code><\/pre>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e! \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u0444\u0438\u043b\u044c\u0442\u0440 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u043c\u0438, \u0438 \u0441 Minimal API.<br \/>\u0422\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u043b\u044e\u0441 Minimal API: \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432, \u0432 \u043c\u0435\u0442\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u043d\u0430\u0448 \u043c\u0430\u0441\u0441\u0438\u0432 \u0445\u044d\u0434\u0435\u0440\u043e\u0432 \u0438\u0437 \u043a\u0430\u043a\u043e\u0433\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430 \u0438\u043b\u0438 \u0434\u0430\u0436\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0430 \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438: \u043c\u044b \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u044b \u044d\u0442\u0430\u043f\u043e\u043c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u0430\u0435\u043c \u0444\u0438\u043b\u044c\u0442\u0440 \u0441\u043e SwaggerGen \u043d\u0430 Microsoft OpenApi:<br \/>\u041d\u0430\u0448 \u0444\u0438\u043b\u044c\u0442\u0440 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043d\u0435 IOperationFilter, \u0430 IOpenApiOperationTransformer, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u0434\u0435 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b:<\/p>\n<pre><code class=\"cs\">\/\/ \u0411\u044b\u043b\u043e: public class ShowHeadersFilter : IOperationFilter ... public void Apply(OpenApiOperation operation, OperationFilterContext context) ... var headersData = context.ApiDescription.ActionDescriptor.EndpointMetadata.OfType&lt;ApiShowHeadersAttribute&gt;().FirstOrDefault();  \/\/ \u0421\u0442\u0430\u043b\u043e: public class OpenApiShowHeadersFilter : IOpenApiOperationTransformer ... public async Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransformerContext context, CancellationToken ct) ... var headersData = context.Description.ActionDescriptor.EndpointMetadata.OfType&lt;ApiShowHeadersAttribute&gt;().FirstOrDefault();<\/code><\/pre>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u0430\u0445 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/fundamentals\/openapi\/customize-openapi?view=aspnetcore-9.0\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0435<\/a>. \u0418 \u043f\u043e\u043c\u0435\u043d\u044f\u0435\u043c \u0432 Program.cs:<\/p>\n<pre><code class=\"cs\">\/\/ \u0411\u044b\u043b\u043e: builder.Services.AddSwaggerGen(c =&gt; c.OperationFilter&lt;ShowHeadersFilter&gt;()); ... app.UseSwagger(); app.UseSwaggerUI();  \/\/ \u0421\u0442\u0430\u043b\u043e: builder.Services.AddOpenApi(c =&gt; c.AddOperationTransformer&lt;ShowHeadersFilter&gt;()); ... app.UseSwaggerUI(options =&gt; options.SwaggerEndpoint(\"\/openapi\/v1.json\", \"Swagger\")); app.MapOpenApi();<\/code><\/pre>\n<p>Microsoft OpenApi \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u0440\u0438\u0446\u0435\u043b\u043e\u043c \u043d\u0430 Minimal API, \u043e\u0434\u043d\u0430\u043a\u043e \u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u043c\u0438 \u0442\u043e\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442: \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u043d\u0430 \u0432\u0430\u0448\u0438\u0445 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445 \u0435\u0441\u0442\u044c \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442 [ApiController] <br \/>\u0410 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u043e\u0432 \u043e\u0442\u0432\u0435\u0442\u0430 \u0432 Min API \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cs\">\/\/ \u0411\u044b\u043b\u043e: [HttpPut(\"items\/create\") [SwaggerResponse(StatusCodes.Status400BadRequest, Type = typeof(ErrorModel))]  \/\/ \u0421\u0442\u0430\u043b\u043e: endpointsBuilder.MapPut(\"\/items\/create\", HandleAsync) .Produces&lt;ErrorModel&gt;(400);<\/code><\/pre>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435, \u0447\u0442\u043e \u043d\u0430 \u0447\u0442\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u043b\u043e\u0441\u044c, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/fundamentals\/openapi\/include-metadata?view=aspnetcore-9.0&amp;tabs=minimal-apis\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>.<br \/>\u041f\u043e\u0447\u0435\u043c\u0443-\u0442\u043e .Produces \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d, \u0435\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u043d\u0430\u0432\u0435\u0441\u0438\u0442\u044c \u0435\u0433\u043e \u0441\u0440\u0430\u0437\u0443 \u043d\u0430 \u0433\u0440\u0443\u043f\u043f\u0443 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432. \u041d\u043e \u043d\u0435 \u0431\u0435\u0434\u0430: \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043c\u0435\u0442\u0430\u0434\u0430\u0442\u0430, \u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cs\">var endpointsBuilder = app.MapGroup(\"\/api\").WithMetadata(new ProducesResponseTypeMetadata(400, typeof(ErrorModel))) ...<\/code><\/pre>\n<p>\u041f\u043e\u043b\u0435\u0437\u043d\u043e, \u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439 (\u0430 \u043e\u043d, \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d)<\/p>\n<h2>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a<\/h2>\n<p>\u0412 Minimal API \u0435\u0441\u0442\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a (<a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/fundamentals\/minimal-apis\/handle-errors?view=aspnetcore-9.0\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>). \u041c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cs\">app.UseExceptionHandler(exceptionHandlerApp =&gt; {     exceptionHandlerApp.Run(async context =&gt;     {         var exceptionFeature = context.Features.Get&lt;IExceptionHandlerFeature&gt;();         if (exceptionFeature?.Error is ValidationException)             await Results.ValidationProblem([]).ExecuteAsync(context);         else             await Results.Problem().ExecuteAsync(context);     }); }); <\/code><\/pre>\n<p>\u0412\u043f\u0440\u043e\u0447\u0435\u043c, \u043b\u0438\u0447\u043d\u043e \u043c\u043d\u0435 \u044d\u0442\u043e \u043a\u043e\u0440\u043e\u0431\u043e\u0447\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u043b\u043e\u0441\u044c: \u043e\u043d\u043e \u043c\u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0433\u0438\u0431\u043a\u0438\u043c, \u0438 \u043e\u043d\u043e \u0431\u0435\u0437\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e \u0437\u0430\u043b\u043e\u0433\u0433\u0438\u0440\u0443\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443 \u0435\u0449\u0435 \u0434\u043e \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0434\u043e\u0439\u0434\u0435\u0442 \u0434\u043e \u0445\u044d\u043d\u0434\u043b\u0435\u0440\u0430 &#8212; \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0432\u044b \u0435\u0435 \u043a\u0430\u043a-\u0442\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435.<br \/>\u0410 \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0442\u0430\u043c &#8212; \u043e\u0431\u044b\u0447\u043d\u044b\u0439 Middleware \u0441 try catch, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a \u0438 \u0441\u0430\u043c\u0438\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c: <\/p>\n<pre><code class=\"cs\">public class ExceptionHandlingMiddleware(RequestDelegate next, ILogger&lt;ExceptionHandlingMiddleware&gt; log) { public async Task InvokeAsync(HttpContext context) { try { await next(context); } catch (Exception exception) { \/\/ \u0412\u0430\u0448\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0442\u0443\u0442 } } }<\/code><\/pre>\n<p>\u041d\u043e, \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0430\u0448\u0435\u0433\u043e \u0432\u044b\u0431\u043e\u0440\u0430, \u043e\u0431\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 (\u0442.\u043a. \u0438 \u0442\u0430\u043c \u0438 \u0442\u0430\u043c Middleware), \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438 \u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u043c\u0438<\/p>\n<h2>\u041a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h2>\n<p>ResponseCacheAttribute \u0434\u043b\u044f Minimal API \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 (\u0445\u043e\u0442\u044f, \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430: \u043d\u0438\u0447\u0442\u043e \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u043c\u0435\u0442\u0430\u0434\u0430\u0442\u0443 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0438\u043b\u044c\u0442\u0440 \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f HTTP \u0445\u044d\u0434\u0435\u0440\u043e\u0432 Cache-Control \u0432\u0440\u0443\u0447\u043d\u0443\u044e)<br \/>\u041d\u043e \u0443 \u043d\u0430\u0441 \u0442\u0435\u043f\u0435\u0440\u044c \u0435\u0441\u0442\u044c <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/performance\/caching\/output?view=aspnetcore-9.0\" rel=\"noopener noreferrer nofollow\">OutputCache<\/a>: \u0431\u0435\u0437 HTTP, \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c:<\/p>\n<pre><code class=\"cs\">\/\/ \u0412 Program.cs: builder.Services.AddOutputCache(); ... app.UseOutputCache();  \/\/ \u042d\u043d\u0434\u043f\u043e\u0438\u043d\u0442: endpointsBuilder.MapGet(\"\/items\", HandleAsync) .CacheOutput(builder =&gt; { builder.Expire(TimeSpan.FromSeconds(60)); builder.SetVaryByQuery(\"*\"); }); <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043f\u043e\u0441\u043b\u0435 1 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u043e\u0442\u0432\u0435\u0442 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d \u0443 \u043d\u0430\u0441 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043d\u0430 60 \u0441\u0435\u043a\u0443\u043d\u0434.<\/p>\n<p>\u042d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0441 \u0442\u0430\u043a\u0438\u043c \u043a\u044d\u0448\u043e\u043c \u0443\u043c\u0435\u0435\u0442 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u043a\u044d\u0448 \u0440\u0430\u043d\u044c\u0448\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 Redis \u0438 \u0434\u0430\u0436\u0435 \u0438\u043c\u0435\u0435\u0442 resource locking (1\u044b\u0439 \u0440\u0435\u043a\u0432\u0435\u0441\u0442 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f, \u0430 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0435 \u0436\u0434\u0430\u0442\u044c, \u043f\u043e\u043a\u0430 \u0442\u043e\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440)  &#8212; \u0432 \u043e\u0431\u0449\u0435\u043c, \u0448\u0442\u0443\u043a\u0430 \u0432\u0435\u0441\u044c\u043c\u0430 \u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f.<\/p>\n<h2>Results\/TypedResults<\/h2>\n<p>\u041a\u0430\u043a \u0438 \u0441 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 Ok(), BadRequest() \u0438 \u0442.\u043f., \u0443 \u043d\u0430\u0441 \u0442\u0435\u043f\u0435\u0440\u044c \u0435\u0441\u0442\u044c (Typed)Results.Ok()\/BadRequest().<br \/>\u0418, \u043a\u0430\u043a \u0438 \u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u043c\u0438, \u043c\u043e\u0436\u043d\u043e \u0438\u0445 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u0430 \u043c\u043e\u0436\u043d\u043e \u0438 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c:<\/p>\n<pre><code class=\"cs\">endpointsBuilder.MapGet(\"\/cart\/item-plain\", HandlePlain); endpointsBuilder.MapGet(\"\/cart\/item-results\", HandleResults); ... private static UserCartItem HandlePlain() =&gt; new UserCartItem(); private static Ok&lt;UserCartItem&gt; HandleResults() =&gt; TypedResults.Ok(new UserCartItem()); <\/code><\/pre>\n<p>\u0414\u0430\u043d\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u044b, \u0438 OpenAPI\/SwaggerGen \u0441\u0430\u043c \u043f\u043e\u0434\u0445\u0432\u0430\u0442\u0438\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043e\u0442\u0432\u0435\u0442\u0430.<br \/>\u041d\u043e \u0434\u043b\u044f Results \u043c\u043e\u0436\u043d\u043e \u0435\u0449\u0435, \u0432 \u0441\u0442\u0438\u043b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b \u0440\u0430\u0437\u043d\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0430:<\/p>\n<pre><code class=\"cs\">private static Results&lt;Ok&lt;UserCartItem&gt;, NotFound&gt; HandleResults() =&gt; TypedResults.Ok(new UserCartItem());<\/code><\/pre>\n<p>\u041d\u043e, \u043a\u0430\u043a \u044f \u043f\u0438\u0441\u0430\u043b \u0432\u044b\u0448\u0435 \u043f\u0440\u043e OpenApi, \u0443 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u0435\u0441\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 .Produces(), \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0435\u0435 \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0442\u043e\u0433\u043e \u0436\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430, \u043f\u0440\u0438\u0447\u0435\u043c, \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e <br \/>\u0418\u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0436\u0435 \u0432\u044b\u0431\u0440\u0430\u0442\u044c, Results.Ok() \u0438\u043b\u0438 &#171;\u0441\u044b\u0440\u044b\u0435&#187; \u0434\u0430\u043d\u043d\u044b\u0435? \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u043a\u043e\u043d\u0441\u0435\u043d\u0441\u0443\u0441 \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445 \u043d\u0430 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443 &#8212; \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u043a \u0435\u0441\u0442\u044c.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043e\u0442\u0432\u0435\u0442\u0430 \u0434\u043b\u044f \u0432\u0430\u0441 \u043f\u043e\u043a\u0430 \u043d\u0435\u0442, \u043b\u0438\u0447\u043d\u043e \u043c\u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u044b\u0440\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 + \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 Exceptions: \u0437\u0430\u0447\u0435\u043c \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u044e\u0437\u0435\u0440\u043e\u0432 \u043a \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 API, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u043e\u0441\u043e\u0431\u043e \u043d\u0435 \u0434\u0430\u0435\u0442 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432.<br \/>\u0425\u043e\u0442\u044f, \u044d\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u043a\u0443\u0441\u043e\u0432\u0449\u0438\u043d\u0430, \u041e\u041e\u041f \u043f\u0440\u043e\u0442\u0438\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0442\u0438\u043b\u044f.<\/p>\n<p>\u0412\u043f\u0440\u043e\u0447\u0435\u043c, \u0435\u0441\u043b\u0438 \u0432\u0430\u0448 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e json-\u043e\u0442\u0432\u0435\u0442, Results \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u044b \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435:<\/p>\n<pre><code class=\"cs\">return TypedResults.File(result, \"application\/x-gzip\", $\"sitemap-{page}.xml.gz\");<\/code><\/pre>\n<h2>\u0418\u0442\u043e\u0433\u0438<\/h2>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u043b, \u0438 \u0443\u0431\u0435\u0434\u0438\u043b \u0432\u0430\u0441, \u0447\u0442\u043e MinimalAPI &#8212; \u0433\u0438\u0431\u043a\u0430\u044f \u0438 \u043c\u043e\u0449\u043d\u0430\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u0430\u043a \u0432 \u043d\u0435\u0431\u043e\u0448\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445, \u0442\u0430\u043a \u0438 \u0432 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u044d\u043d\u0442\u0435\u0440\u043f\u0440\u0430\u0439\u0437\u0430\u0445 \u0443\u0436\u0435 \u0441\u0435\u0439\u0447\u0430\u0441.<\/p>\n<p>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u044f \u0437\u0430\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u0442 <a href=\"https:\/\/github.com\/FastEndpoints\/FastEndpoints\" rel=\"noopener noreferrer nofollow\">FastEndpoints<\/a> &#8212; \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u044f\u044f \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 MVC \u0438 Minimal API. \u041e\u0434\u043d\u0430\u043a\u043e, \u043a\u0430\u043a \u043c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0441 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435\u043c Minimal API \u0441\u043c\u044b\u0441\u043b\u0430 \u0432 \u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0432\u0441\u0435 \u043c\u0435\u043d\u044c\u0448\u0435<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/917378\/\"> https:\/\/habr.com\/ru\/articles\/917378\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u042f, \u0434\u0443\u043c\u0430\u044e, \u043c\u043d\u043e\u0433\u0438\u0435 \u0443\u0436\u0435 \u0441\u043b\u044b\u0448\u0430\u043b\u0438 \u043e \u043f\u043e\u044f\u0432\u0438\u0432\u0448\u0438\u0445\u0441\u044f \u0432 .NET 6 Minimal API &#8212; \u043b\u0435\u0433\u043a\u043e\u0432\u0435\u0441\u043d\u043e\u0439 \u0437\u0430\u043c\u0435\u043d\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432\/MVC. \u041a\u0442\u043e-\u0442\u043e \u0443\u0436\u0435 \u0443\u0441\u043f\u0435\u043b \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0438 \u0437\u0430\u0434\u0430\u043b\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c: &#171;\u0412\u0430\u0448\u0435 API \u0432 3 \u0441\u0442\u0440\u043e\u0447\u043a\u0438, \u044d\u0442\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0437\u0434\u043e\u0440\u043e\u0432\u043e, \u043d\u043e \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0441 \u0441\u043e\u0442\u043d\u044f\u043c\u0438 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432, \u043a\u0443\u0447\u0435\u0439 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432, \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432, \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438 OpenAPI\/Swagger \u0438 \u043f\u0440\u043e\u0447\u0438\u0445 \u0440\u0430\u0434\u043e\u0441\u0442\u044f\u0445?&#187;<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0447\u0443 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u044d\u0442\u043e\u0442 \u0432\u043e\u043f\u0440\u043e\u0441: \u043f\u0440\u043e\u0439\u0434\u0435\u043c\u0441\u044f \u043e\u0442 \u043e\u0441\u043d\u043e\u0432, \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432, \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u043e\u0432, \u0438 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043c \u043d\u044e\u0430\u043d\u0441\u0430\u043c\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442 \u043f\u0440\u0438 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u043d\u0430 Minimal API \u0432 \u043a\u0440\u0443\u043f\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<p>\u0410 \u0437\u0430\u0431\u0435\u0433\u0430\u044f \u0447\u0443\u0442\u044c \u0432\u043f\u0435\u0440\u0435\u0434: \u0435\u0441\u043b\u0438 \u0434\u0443\u043c\u0430\u0435\u0442\u0435, \u0441\u0442\u043e\u0438\u0442 \u043b\u0438 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 Mini API, \u0432\u043e\u0442 \u0432\u0430\u043c \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f: \u043e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0436\u0438\u0442\u044c \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0432\u043c\u0435\u0441\u0442\u0435, \u043f\u0440\u0438\u0447\u0435\u043c \u0434\u0430\u0436\u0435 \u0431\u0435\u0437 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b: \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u0432\u0441\u0435 \u0440\u0430\u0437\u043e\u043c &#8212; \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c.<\/p>\n<p>\u0411\u043e\u043d\u0443\u0441\u043e\u043c, \u0437\u0430\u043c\u0435\u043d\u0438\u043c SwaggerGen \u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e OpenAPI \u043e\u0442 Microsoft.<\/p>\n<h2>\u0417\u0430\u0447\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Minimal API?<\/h2>\n<p>\u041c\u044b \u0441 \u0432\u0430\u043c\u0438, (\u043d\u0430\u0434\u0435\u044e\u0441\u044c) \u043d\u0435 \u0433\u043e\u043d\u0438\u043c\u0441\u044f \u0437\u0430 \u043c\u043e\u0434\u043d\u044b\u043c\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u0430\u043c\u0438 &#171;\u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e&#187;, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f, \u0437\u0430\u0447\u0435\u043c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043d\u0430 Minimal API:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0418\u0437 \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/piyushdoorwar.medium.com\/how-to-use-minimal-apis-in-net-8-without-cluttering-program-cs-e6ea1d513137\" rel=\"noopener noreferrer nofollow\">https:\/\/piyushdoorwar.medium.com\/how-to-use-minimal-apis-in-net-8-without-cluttering-program-cs-e6ea1d513137<\/a>  <\/figcaption><\/div>\n<\/figure>\n<ul>\n<li>\n<p>\u041f\u0440\u043e\u0441\u0442\u043e\u0442\u0430 \u0438 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c.<br \/>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b \u043f\u043e\u0434 <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/mvc\/overview?view=aspnetcore-9.0\" rel=\"noopener noreferrer nofollow\">MVC<\/a>, Mini API \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434 API \/ <a href=\"https:\/\/deviq.com\/design-patterns\/repr-design-pattern\" rel=\"noopener noreferrer nofollow\">REPR<\/a> \u043f\u0430\u0442\u0442\u0435\u0440\u043d. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u043f\u043e\u0434 \u043d\u0443\u0436\u0434\u044b \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0438 \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 Microsoft<br \/>\u0420\u0435\u0444\u0435\u0440\u0435\u043d\u0441\u043d\u044b\u0439 <a href=\"https:\/\/github.com\/dotnet\/eShop\" rel=\"noopener noreferrer nofollow\">eShop<\/a> \u0443\u0436\u0435 \u043f\u0435\u0440\u0435\u0448\u0435\u043b \u043d\u0430 Mini API, \u0430 \u043f\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c <a href=\"http:\/\/ASP.NET\" rel=\"noopener noreferrer nofollow\">ASP.NET<\/a> Core <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/release-notes\/aspnetcore-9.0?view=aspnetcore-9.0#minimal-apis\" rel=\"noopener noreferrer nofollow\">9<\/a> \u0438 <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/release-notes\/aspnetcore-10.0?view=aspnetcore-9.0#minimal-apis\" rel=\"noopener noreferrer nofollow\">10<\/a> \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 Mini API \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442 \u043d\u043e\u0432\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 &#8212; \u043a\u0443\u0434\u0430 \u0430\u043a\u0442\u0438\u0432\u043d\u0435\u0435, \u0447\u0435\u043c \u0434\u043b\u044f MVC. \u0412\u043e \u043c\u043d\u043e\u0433\u043e\u043c, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u044d\u0442\u043e \u043e\u0431\u0443\u0441\u043b\u043e\u0432\u043b\u0435\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445, \u043d\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430. \u0421\u0443\u0431\u044a\u0435\u043a\u0442\u0438\u0432\u043d\u043e, \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0434\u0432\u0438\u0436\u0443\u0442\u0441\u044f \u0432 \u0441\u0442\u0430\u0442\u0443\u0441 \u043b\u0435\u0433\u0430\u0441\u0438. \u041e\u0447\u0435\u043d\u044c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0432\u0440\u044f\u0434 \u043b\u0438 \u043e\u043d\u0438 \u0441\u0442\u0430\u043d\u0443\u0442 deprecated \u0432 \u043a\u0430\u043a\u043e\u043c-\u043d\u0438\u0431\u0443\u0434\u044c .Net 11 (\u0441\u043a\u043e\u0440\u0435\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0432 .Net 15 &#8212; \u0434\u0430\u043c \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0433\u043d\u043e\u0437. \u0418 \u0442\u043e, \u044d\u0442\u043e \u0434\u043b\u044f \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u043b\u0435\u0433\u0430\u0441\u0438, \u0431\u0435\u0437 \u0432\u044b\u043f\u0438\u043b\u0438\u0432\u0430\u043d\u0438\u044f \u0438\u0437 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430). \u0418 \u044d\u0442\u043e \u043c\u043e\u0435 \u0441\u0443\u0431\u044a\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u043e\u0449\u0443\u0449\u0435\u043d\u0438\u0435: \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u0439 \u043e\u0442 Microsoft \u043d\u0430 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443 \u043d\u0435 \u0431\u044b\u043b\u043e, \u043b\u0438\u0448\u044c \u043a\u043e\u0441\u0432\u0435\u043d\u043d\u044b\u0435 \u043e \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0438 Mini API.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0445\u043e\u0436\u0435\u0441\u0442\u044c \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430\u043c\u0438<br \/>\u041d\u0430\u043c \u043d\u0435 \u043f\u0440\u0438\u0432\u044b\u043a\u0430\u0442\u044c \u043a \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u043c, \u043d\u043e \u0443 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u0440\u0443\u043f\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432 &#8212; JS (Fastify\/Express), Python (Flask, FastAPI), Go (Gin), \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435, \u0443\u0436\u0435 \u0434\u0430\u0432\u043d\u043e \u0435\u0441\u0442\u044c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u043f\u043e \u0441\u0445\u043e\u0436\u0435\u0439 \u0441\u0445\u0435\u043c\u0435 \u0441 MinimalAPI. \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u0441 \u044f\u0437\u044b\u043a\u0430 \u043d\u0430 \u044f\u0437\u044b\u043a \u043b\u0435\u0433\u0447\u0435, \u0430 \u0432\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u044d\u0442\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043d\u0430\u043c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0438 \u0431\u0435\u0437 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0436\u0438\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0438<br \/>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434\u044b, \u044f\u0432\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0432 \u0432\u0430\u0448\u0435\u043c \u043a\u043e\u0434\u0435, \u0430 \u043d\u0435 \u043f\u043e\u0438\u0441\u043a\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u043f\u043e \u0432\u0441\u0435\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044e \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u044b \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u043e (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b \u043d\u0435 \u0437\u0430\u043f\u0438\u0445\u043d\u0435\u0442\u0435 \u0432 \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442 \u043c\u0430\u0441\u0441\u0438\u0432, \u0438\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u043a\u043e\u043d\u0444\u0438\u0433\u0430), \u0430 \u0442\u0430\u043a\u0436\u0435 \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0435\u0442 \u0435\u0449\u0435 2 \u043f\u043b\u044e\u0441\u0430:<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/fundamentals\/native-aot?view=aspnetcore-9.0\" rel=\"noopener noreferrer nofollow\">NativeAOT<\/a> <br \/>NativeAOT &#8212; \u0441\u0435\u0439\u0447\u0430\u0441 \u0442\u0440\u0435\u043d\u0434 \u0432 \u043c\u0438\u0440\u0435 .Net, \u0438 \u0432\u0440\u044f\u0434 \u043b\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442 \u0435\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0438 \u043e\u0442 Mini API, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u043d\u0430 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c. \u0412\u043f\u0440\u043e\u0447\u0435\u043c, \u0431\u044d\u043a\u0435\u043d\u0434 &#8212; \u044d\u0442\u043e \u0442\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c, \u0433\u0434\u0435 NativeAOT \u043c\u043e\u0436\u0435\u0442 \u0443\u0445\u0443\u0434\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c. \u0412\u043e\u043e\u0431\u0449\u0435, \u044d\u0442\u043e \u0442\u0435\u043c\u0430 \u0434\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438, \u043d\u043e <a href=\"https:\/\/bitmiracle.com\/pdf-library\/howto\/native-aot-performance\" rel=\"noopener noreferrer nofollow\">\u0432\u043e\u0442<\/a> \u0432\u0430\u043c \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435, \u0438 <a href=\"https:\/\/www.reddit.com\/r\/dotnet\/comments\/zoxhkp\/comment\/j0pmo0t\/?utm_source=share&amp;utm_medium=web3x&amp;utm_name=web3xcss&amp;utm_term=1&amp;utm_content=share_button\" rel=\"noopener noreferrer nofollow\">\u0432\u043e\u0442<\/a> \u043a\u0440\u0430\u0442\u043a\u043e\u0435 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0435\u043c\u0443. \u041d\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c\u0441\u044f &#8212; .Net \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u043e.<\/p>\n<\/li>\n<li>\n<p>\u0423\u043b\u0443\u0447\u0448\u0435\u043d\u043d\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c<br \/><a href=\"https:\/\/dev.to\/stevsharp\/minimal-api-performance-benchmark-14ln\" rel=\"noopener noreferrer nofollow\">\u0412\u043e\u0442<\/a> \u0438 <a href=\"https:\/\/steven-giesel.com\/blogPost\/698c45c3-58c5-4157-b4da-2cde4e27862e\" rel=\"noopener noreferrer nofollow\">\u0432\u043e\u0442<\/a> \u0432\u0430\u043c \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0438. \u0421\u043f\u043e\u0439\u043b\u0435\u0440: \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043e\u0432 \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u043d\u0430 \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043e\u0432 \u043f\u043e \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438. \u0412 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0431\u041e\u043b\u044c\u0448\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0430\u0448 \u043a\u043e\u0434, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0436\u0434\u0430\u0442\u044c \u0441\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044f RPS \u043d\u0435 \u0441\u0442\u043e\u0438\u0442. \u041d\u043e \u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u0441 \u0434\u0435\u0441\u044f\u0442\u043a\u0430\u043c\u0438 \u0438 \u0441\u043e\u0442\u043d\u044f\u043c\u0438 \u0442\u044b\u0441\u044f\u0447 RPS, \u0433\u0434\u0435 \u0432\u044b \u043e\u0442\u0447\u0430\u044f\u043d\u043d\u043e \u0431\u043e\u0440\u0435\u0442\u0435\u0441\u044c \u0437\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 GC, \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u0438\u0445 \u043d\u0430 Mini API \u043c\u043e\u0436\u0435\u0442 \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043d\u0435\u043f\u043b\u043e\u0445\u043e\u0439 \u0438\u0434\u0435\u0435\u0439, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044f \u0442\u0440\u0435\u043d\u0434 \u043d\u0430 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 .Net.<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438:<\/p>\n<ul>\n<li>\n<p>\u041d\u0435 \u0432\u0435\u0441\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u043f\u043e\u043a\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d<br \/>\u0412 <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/fundamentals\/apis?view=aspnetcore-9.0\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435 Microsoft<\/a> \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0447\u0435\u0433\u043e \u043f\u043e\u043a\u0430 \u043d\u0435\u0442. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 &#8212; \u044d\u0442\u043e \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f (\u0440\u0435\u0448\u0430\u0435\u043c\u043e, \u043d\u0430\u043f\u0438\u0448\u0443 \u043f\u0440\u043e \u044d\u0442\u043e \u043d\u0438\u0436\u0435) \u0438 \u043d\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 View \u0438\u0437 MVC (\u043d\u043e Razor Pages \u0435\u0441\u0442\u044c) <\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u043d\u043e\u0441 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 &#8212; \u0434\u043d\u0438\/\u043d\u0435\u0434\u0435\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u044b<br \/>\u0414\u0430\u0436\u0435 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u043f\u0435\u0440\u0432\u044b\u0439 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043c\u043e\u0436\u0435\u0442 \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u043d\u0430 \u0434\u0435\u043d\u0435\u043a-\u0434\u0440\u0443\u0433\u043e\u0439: \u0438\u0437-\u0437\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0432\u0441\u0435 \u0432\u0430\u0448\u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u044b, \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0438 \u0442.\u043f. \u0414\u0430\u043b\u044c\u0448\u0435 \u043f\u043e\u0439\u0434\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u043d\u043e \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u0445\u0432\u0430\u0442\u0438\u0442. \u041c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c Cursor \u043d\u0430\u0442\u0440\u0430\u0432\u0438\u0442\u044c \u043d\u0430 \u044d\u0442\u043e \u0434\u0435\u043b\u043e &#8212; \u0435\u0441\u0442\u044c \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c \u0447\u0442\u043e \u043f\u0440\u043e\u043a\u0430\u0442\u0438\u0442.<\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0442\u043e\u0433\u043e, \u043c\u043e\u0435 \u043b\u0438\u0447\u043d\u043e\u0435 \u043c\u043d\u0435\u043d\u0438\u0435: \u0435\u0441\u043b\u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\/\u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0441 \u043f\u0440\u0438\u0446\u0435\u043b\u043e\u043c \u043d\u0430 .Net 10 (\u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u043d\u0430\u0434 \u043f\u043e\u043a\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c), \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u0441\u0442\u043e\u0438\u0442. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u044d\u043d\u0442\u0435\u0440\u043f\u0440\u0430\u0439\u0437 \u043f\u0440\u043e\u0435\u043a\u0442, \u0432\u0441\u0435 \u0438 \u0442\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0430 \u0432 \u0431\u044d\u043a\u043b\u043e\u0433\u0435 \u0438 \u0442\u0430\u043a \u043a\u0443\u0447\u0430 \u0437\u0430\u0434\u0430\u0447 \u043f\u043e \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0443, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u044b \u043d\u0435 \u0434\u0430\u044e\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043a\u0430 \u0438 \u043f\u043e\u0436\u0438\u0442\u044c \u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u043c\u0438. \u0415\u0441\u043b\u0438, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0438 NativeAOT \u043d\u0435 \u043d\u0443\u0436\u0435\u043d.<\/p>\n<h2>Hello World!<\/h2>\n<p>\u0414\u043b\u044f \u0442\u0435\u0445 \u043a\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u043a\u043e\u043c, \u0432 \u044d\u0442\u043e\u0439 \u0433\u043b\u0430\u0432\u0435 \u0432\u043a\u0440\u0430\u0442\u0446\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u0441 Mini API. \u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432  <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/tutorials\/min-web-api?view=aspnetcore-9.0&amp;tabs=visual-studio\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043e\u0442 Microsoft<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/habr.com\/ru\/companies\/otus\/articles\/666676\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0430 \u0445\u0430\u0431\u0440\u0435<\/a>. <\/p>\n<pre><code class=\"cs\">var app = WebApplication.CreateBuilder(args).Build();  app.MapGet(\"\/\", () =&gt; \"Hello World!\");  app.Run();<\/code><\/pre>\n<p>\u041a\u0440\u0430\u0441\u0438\u0432\u043e, \u043f\u0440\u0430\u0432\u0434\u0430? \u041d\u0443 \u043b\u0430\u0434\u043d\u043e, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u043c\u044b \u0432 Program.cs \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u043d\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0435\u043c. \u0414\u043e\u0431\u0430\u0432\u043b\u044e \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u0434 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u0438\u0437 \u0441\u0432\u043e\u0435\u0439 <a href=\"https:\/\/habr.com\/ru\/articles\/916704\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u0440\u043e VSA<\/a>. \u0412\u0432\u0435\u0434\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 IEndpoint \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432.<\/p>\n<pre><code class=\"cs\">public interface IEndpoint { void Register(IEndpointRouteBuilder endpointsBuilder); }<\/code><\/pre>\n<p>\u041d\u0430\u0448\u0438 \u043a\u043b\u0430\u0441\u0441\u044b \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441. \u0425\u043e\u0442\u0438\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435? \u041f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0439\u0442\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 IEndpoitns(Provider). Minimal API &#8212; \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0433\u0438\u0431\u043a\u0430\u044f \u0448\u0442\u0443\u043a\u0430, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0439\u0442\u0435 \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u043a \u0432\u0430\u0448\u0435\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0443.<br \/>\u0414\u043e\u0431\u0430\u0432\u0438\u043c extension \u0434\u043b\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"cs\">public static class EndpointsHelper {     public static IEndpointRouteBuilder Register&lt;T&gt;(this IEndpointRouteBuilder endpointsBuilder)        where T : IEndpoint, new()     {        var endpointsProvider = new T();        endpointsProvider.Register(endpointsBuilder);        return endpointsBuilder;     } }<\/code><\/pre>\n<p>\u0418, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b:<\/p>\n<pre><code class=\"cs\">public static class EndpointsProvider { public static void RegisterAppEndpoints(RouteGroupBuilder endpointsBuilder) { endpointsBuilder.Register&lt;GetUserCart&gt;(); } }<\/code><\/pre>\n<p>\u0425\u043e\u0442\u044f, \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438, \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u0435\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e Assembly \u0438 \u043d\u0430\u0439\u0442\u0438 \u0432\u0441\u0435 IEndpoint &#8212; \u043a\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445. \u041d\u043e \u044f \u0431\u044b \u043d\u0435 \u0441\u0442\u0430\u043b.<br \/>\u0418 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0433\u043e \u0432 Program.cs:<\/p>\n<pre><code class=\"cs\">\/\/ \u0412\u0441\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c\u0441\u044f \u0441 \/api var endpointsBuilder = app.MapGroup(\"\/api\"); EndpointsProvider.RegisterAppEndpoints(endpointsBuilder);<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c, \u0441\u0430\u043c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442:<\/p>\n<pre><code class=\"cs\">public class GetUserCart : IEndpoint {     public void Register(IEndpointRouteBuilder endpointsBuilder)     {         endpointsBuilder.MapGet(\"\/user\/cart\", HandleAsync)             \/\/ \u0410\u043d\u0430\u043b\u043e\u0433 \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u0430 [Authorize]             .RequireAuthorization()             \/\/ \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430 \u0434\u043b\u044f OpenAPI. \u0412 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445 \u043e\u0431\u044b\u0447\u043d\u043e \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 XML (\/\/\/ &lt;summary&gt;). \u0422\u0435\u043f\u0435\u0440\u044c \u044d\u0442\u043e \u0432 \u043a\u043e\u0434\u0435.             .WithSummary(\"Search all available platforms.\")             \/\/ \u0422\u044d\u0433 \u0434\u043b\u044f OpenAPI. \u041e\u0431\u044b\u0447\u043d\u043e \u044d\u0442\u043e \u0438\u043c\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430.             .WithTags(\"User\");     }      \/\/ OpenAPI \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0442\u0438\u043f\u0430.     private static async Task&lt;QueryableList&lt;UserCartItem&gt;&gt; HandleAsync(int skip, int take, UserContext userContext, ExampleDbContext db, CancellationToken ct)     {         var total = await db.CartItems.CountAsync(x =&gt; x.UserId == userContext.UserId, ct);         if (total == 0)             return QueryableList&lt;UserCartItem&gt;.Empty();                  var items = await db.CartItems.Where(x =&gt; x.UserId == userContext.UserId)             .Select(x =&gt; new UserCartItem             {                 Id = x.ItemId,                 Name = x.Item.Name,             })             .Skip(skip)             .Take(take)             .ToListAsync(ct);          return new QueryableList&lt;UserCartItem&gt;(items, total);     } }<\/code><\/pre>\n<p>(\u042f \u0443\u043f\u0443\u0449\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0411\u0414 \u0438 \u043f\u0440\u043e\u0447\u0438\u0445 \u0440\u0430\u0434\u043e\u0441\u0442\u0435\u0439 \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0440\u0430\u0437\u0434\u0443\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e) skip \u0438 take \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b \u0438\u0437 query string, \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0437\u0430\u0440\u0435\u0437\u043e\u043b\u0432\u0438\u0442 DI. <br \/>\u041c\u043d\u043e\u0433\u043e skip-take \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 \u043e\u0431\u0449\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f? \u041f\u043e\u043c\u043e\u0436\u0435\u0442 \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442 [AsParameters]:<\/p>\n<pre><code class=\"cs\">private static async Task&lt;QueryableList&lt;UserCartItem&gt;&gt; HandleAsync([AsParameters]PagingQuery paging, UserContext userContext, ExampleDbContext db, CancellationToken ct) ... public record PagingQuery { [FromQuery(Name = \"take\")]     public int Take { get; init; } = 10; [FromQuery(Name = \"skip\")]     public int Skip { get; init; } }<\/code><\/pre>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u0431\u0438\u043d\u0434\u0438\u043d\u0433\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/fundamentals\/minimal-apis\/parameter-binding?view=aspnetcore-9.0\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435 Microsoft<\/a>.<br \/>\u0414\u0432\u0438\u0436\u0435\u043c\u0441\u044f \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<h2>\u0417\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u044b<\/h2>\n<p>\u0412 Minimal API \u0435\u0441\u0442\u044c \u0432\u0430\u0436\u043d\u0430\u044f \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f &#8212; \u043c\u0435\u0442\u0430\u0434\u0430\u0442\u0430. \u042d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442 \u043d\u0430\u043c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445: \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0443 \u043c\u0435\u0442\u0430\u0434\u0430\u0442\u0443 \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0435\u0435 \u0432 \u043d\u0430\u0448\u0438\u0445 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0445.<br \/>\u0417\u0430\u0431\u0435\u0433\u0430\u044f \u0432\u043f\u0435\u0440\u0435\u0434 &#8212; \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0442\u043e\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u0435\u0442\u0430\u0434\u0430\u0442\u0443!<br \/>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0445\u043e\u0442\u0438\u043c \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u0435. \u0414\u0435\u043b\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441:<\/p>\n<pre><code class=\"cs\">public class ProhibitInProductionMetadata;<\/code><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0432 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 (\u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430 &#8212; \u043c\u043e\u0436\u043d\u043e \u0434\u0430\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0435 extension):<\/p>\n<pre><code class=\"cs\">endpointsBuilder.MapGet(\"\/user\/cart\", HandleAsync) .WithMetadata(new ProhibitInProductionMetadata()))<\/code><\/pre>\n<p>\u0410, \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443, \u0441\u0440\u0430\u0437\u0443 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u043c<\/p>\n<h3>\u0424\u0438\u043b\u044c\u0442\u0440\u044b<\/h3>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u044b\u0448\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0444\u0438\u043b\u044c\u0442\u0440:<\/p>\n<pre><code class=\"cs\">public class ProhibitInProductionFilter(EnvironmentConfig envConfig) : IEndpointFilter { public async ValueTask&lt;object?&gt; InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next) { var endpoint = context.HttpContext.GetEndpoint(); if (endpoint == null || envConfig.Environment != EnvironmentType.Production) return await next(context);  \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u0442\u044b \u0443 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430 var metadata = endpoint.Metadata.GetMetadata&lt;ProhibitInProductionMetadata&gt;(); if (metadata == null) return await next(context);  \/\/ \u041c\u0435\u0442\u0430\u0434\u0430\u0442\u0430 \u0435\u0441\u0442\u044c, Production \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c 404         return Results.NotFound(); } }<\/code><\/pre>\n<p>\u0418 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u043b\u0441\u044f \u043a\u043e \u0432\u0441\u0435\u043c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430\u043c, \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0432 \u043a\u043e\u0434 \u0438\u0437 \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"cs\">var endpointsBuilder = app.MapGroup(\"\/api\")     .AddEndpointFilter&lt;ProhibitInProductionFilter&gt;();<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-462832","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/462832","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=462832"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/462832\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=462832"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=462832"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=462832"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}