﻿
{"id":27431,"date":"2025-01-08T18:19:51","date_gmt":"2025-01-08T18:19:51","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=27431"},"modified":"2025-01-08T18:19:51","modified_gmt":"2025-01-08T18:19:51","slug":"reprrequest-endpoint-response-pattern-nedir-nasil-uygulanir-teferruatlica-inceleyelim","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/reprrequest-endpoint-response-pattern-nedir-nasil-uygulanir-teferruatlica-inceleyelim\/","title":{"rendered":"REPR(Request-Endpoint-Response) Pattern Nedir? Nas\u0131l Uygulan\u0131r? Teferruatl\u0131ca \u0130nceleyelim&#8230;"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Bu i\u00e7eri\u011fimizde, Asp.NET Core ile geli\u015ftirilen projelerin potansiyellerini daha farkl\u0131 bir \u015fekilde de\u011ferlendirmemizi sa\u011flayacak olan bir yakla\u015f\u0131m\u0131 inceliyor olaca\u011f\u0131z. REPR desenini&#8230; Bu desen, yaz\u0131l\u0131m geli\u015ftirme s\u00fcre\u00e7lerinde isteklerin(request) ve bu isteklere kar\u015f\u0131n verilen yan\u0131tlar\u0131n(response) yap\u0131land\u0131r\u0131lmas\u0131n\u0131 sa\u011flamakta ve genellikle API tasar\u0131mlar\u0131yla birlikte servis odakl\u0131 mimarilerde(SOA) tercih edilerek projenin tasar\u0131m\u0131na farkl\u0131 bir efektiflik kazand\u0131rmaktad\u0131r. \u015eimdi gelin, bu desenin geli\u015ftirme s\u00fcre\u00e7lerine dair olan kazan\u0131mlar\u0131na hem teorik hem de pratik olarak bak\u0131\u015f sergilemeye ba\u015flayal\u0131m&#8230;<\/p>\n<blockquote><p><em>REPR deseni<span style=\"font-size:12px;\">(telafuz &#8216;Reaper&#8217;)<\/span> ile Web API&#8217;ler de, controller s\u0131n\u0131flar\u0131 yerine endpoint ad\u0131 verilen \u00f6zel s\u0131n\u0131flar \u00f6n plana \u00e7\u0131kmakta ve request\/response s\u00fcre\u00e7leri bu s\u0131n\u0131flar \u00fczerinden i\u015flenerek, yap\u0131lacak i\u015fe g\u00f6re daha \u00f6znel ve yal\u0131t\u0131lm\u0131\u015f hale getirilmektedir.<\/em><\/p><\/blockquote>\n<h4>Neden REPR Pattern&#8217;\u0131 Kullanmal\u0131y\u0131z? Nedir Bu?<\/h4>\n<p>\u015eimdi bu soruyu cevapland\u0131rabilmenin en do\u011fru yolu bildi\u011fimiz bir pattern \u00fczerinden mukayesede bulunmakt\u0131r, yani MVC pattern&#8217;\u0131ndan. Malumunuz MVC pattern&#8217;\u0131, geleneksel olarak API endpoint&#8217;leri olu\u015fturmak i\u00e7in kulland\u0131\u011f\u0131m\u0131z bir davran\u0131\u015fsal modele sahiptir. Bu modelin \u00e7e\u015fitli faydalar\u0131 olsa da ister istemez dezavantajlar\u0131 da mevcuttur. Ki bana sorarsan\u0131z en b\u00fcy\u00fck dezavantaj\u0131 olarak de\u011ferlendirebilece\u011fimiz, nihai olarak projeyi \u015fi\u015firilmi\u015f controller(swollen controller) s\u0131n\u0131flar\u0131na bo\u011fmas\u0131d\u0131r. \u015ei\u015firilmi\u015f controller&#8217;dan kastedilen, controller&#8217;lar\u0131n \u00e7ok fazla sorumluluk almalar\u0131 ve haddinden fazla i\u015flev\/metot\/aksiyon bar\u0131nd\u0131rmalar\u0131d\u0131r. Tabi zamanla, controller&#8217;larda biriken ve birbirleriyle ili\u015fkili olmayan pek \u00e7ok metot, bu s\u0131n\u0131flar\u0131n karma\u015f\u0131k hale gelmelerine neden olacakt\u0131r ve bu karma\u015fa, uygulaman\u0131n RESTful ilkelerine ayk\u0131r\u0131 durumlar\u0131 bar\u0131nd\u0131rmas\u0131na ve bu ilkelerden istemsiz uzakla\u015fmas\u0131na ortam sa\u011flayacakt\u0131r. Bu durumlar\u0131n d\u0131\u015f\u0131nda ayr\u0131ca, controller&#8217;lar da haddinden fazla aksiyonun olmas\u0131 bak\u0131m zorlu\u011funa ve hangi metodun ne i\u015fe yarad\u0131\u011f\u0131n\u0131 anlaman\u0131n zorla\u015fmas\u0131na neden olacakt\u0131r.<\/p>\n<p>\u0130\u015fte bu durumlara kar\u015f\u0131n \u00e7\u00f6z\u00fcm aray\u0131\u015f\u0131na girildi\u011fi taktirde akla a\u015fa\u011f\u0131daki y\u00f6ntemler gelmektedir;<\/p>\n<ul>\n<li>\n<strong>Servis Katman\u0131 Kullan\u0131m\u0131<\/strong><br \/>\nBusiness logic, controller&#8217;lardan ayr\u0131larak daha k\u00fc\u00e7\u00fck ve sadece i\u015fe odaklanm\u0131\u015f servis s\u0131n\u0131flar\u0131nda olu\u015fturulmal\u0131d\u0131r. Ama bu y\u00f6ntem bir d\u00fczen getiriyor olsa da yukar\u0131daki sat\u0131rlarda ifade edilen swollen controller durumu i\u00e7in pekte \u00e7\u00f6z\u00fcm sa\u011flamamaktad\u0131r. D\u00fc\u015f\u00fcn\u00fcrsek e\u011fer bu halde bile y\u00fczlerce aksiyon bar\u0131nd\u0131ran bir controller s\u0131n\u0131f\u0131n\u0131n anla\u015f\u0131labilir olmas\u0131 yine ciddi emek gerektirecektir.\n<\/li>\n<li>\n<strong>\u00d6zelle\u015ftirilmi\u015f Controller Tasarlamak<\/strong><br \/>\n\u0130\u015fte, i\u015fe odakl\u0131 servis s\u0131n\u0131flar\u0131n\u0131n tasarlan\u0131p ayn\u0131 controller&#8217;da farkl\u0131 aksiyonlar i\u00e7in kullanmak yerine her bir aksiyona\/amaca kar\u015f\u0131l\u0131k tek bir controller&#8217;\u0131n hizmet etmesini sa\u011flamak en do\u011fru \u00e7\u00f6z\u00fcm olacakt\u0131r diyebiliriz. B\u00f6ylece kodun daha d\u00fczenli, okunabilir ve s\u00fcrd\u00fcr\u00fclebilir olmas\u0131 m\u00fcmk\u00fcn olacakt\u0131r. Ancak bu sefer de ciddi manada kod tekrar\u0131 durumunun s\u00f6z konusu olaca\u011f\u0131n\u0131 itiraf etmemiz gerekecektir.<\/p>\n<p>REPR deseni ise t\u0131pk\u0131 buradaki mant\u0131kta oldu\u011fu gibi uygulamadaki her bir endpoint&#8217;i ayr\u0131 bir s\u0131n\u0131f olarak tan\u0131mlamam\u0131z\u0131 ve her s\u0131n\u0131f\u0131n gelen istekleri i\u015flemek i\u00e7in tek bir metodu olmas\u0131 gerekti\u011fini \u00f6nermektedir.\n<\/li>\n<\/ul>\n<p>B\u00f6ylece REPR deseni ile bir controller&#8217;daki birden fazla aksiyonu bar\u0131nd\u0131rma ihtiyac\u0131 ortadan kald\u0131r\u0131larak swollen controller durumu \u00e7\u00f6z\u00fclebilmekte ve bir yandan da tek sorumluluk ilkesine de<span style=\"font-size:12px;\">(bknz: <a href=\"https:\/\/www.gencayyildiz.com\/blog\/tek-sorumluluk-prensibisingle-responsibility-principle-srp\/\" target=\"_blank\">Single Responsibility Principle \u2013 SRP<\/a>)<\/span> ba\u011fl\u0131 kal\u0131narak aksiyon ba\u015f\u0131na controller desteklenmektedir. Evet, bu tarz bir tasar\u0131m neticesinde proje b\u00fcnyesinde dosya karma\u015f\u0131kl\u0131\u011f\u0131n\u0131n artmas\u0131yla birlikte \u00f6nceki sat\u0131rlarda ifade etti\u011fimiz gibi istemsizce kod tekrarlar\u0131 da mevzu bahis olmaktad\u0131r.<\/p>\n<h4>REPR Pattern&#8217;\u0131n\u0131n Bile\u015fenleri Nelerdir?<\/h4>\n<p>REPR pattern&#8217;\u0131, \u00fc\u00e7 temel a\u015famadan olu\u015fmaktad\u0131r;<\/p>\n<ul>\n<li><strong>Request<\/strong>\n<ul>\n<li>Kullan\u0131c\u0131 veya client&#8217;lardna gelen istekleri ifade etmektedir.<\/li>\n<li>Genellikle bir API \u00e7a\u011fr\u0131s\u0131 ya da HTTP iste\u011fi \u015feklindedir.<\/li>\n<li>JSON, XML vs. gibi belirli bir formattad\u0131r.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Endpoint<\/strong>\n<ul>\n<li>Gelen request&#8217;in y\u00f6lendirildi\u011fi servisi ifade etmektedir.<\/li>\n<li>Request bu servis taraf\u0131ndan al\u0131n\u0131 ve gerekli i\u015f mant\u0131\u011f\u0131 i\u015flenerek, \u00e7al\u0131\u015ft\u0131r\u0131l\u0131r.<\/li>\n<li>Ve \u00e7al\u0131\u015fma neticesinde bir result(sonu\u00e7) elde edilir.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Response<\/strong><\/li>\n<ul>\n<li>Request neticesinde endpoint&#8217;te olu\u015fturulan result&#8217;\u0131 tekrar kullan\u0131c\u0131 ya da client&#8217;a d\u00f6nd\u00fcren yap\u0131y\u0131 ifade etmektedir.<\/li>\n<li>\u00c7o\u011funlukla HTTP durum kodlar\u0131(200, 404, 500 vb.) ile birlikte d\u00f6nen result i\u00e7ermektedir.<\/li>\n<\/ul>\n<\/ul>\n<h4>REPR Pattern Nas\u0131l Uygulan\u0131r?<\/h4>\n<p>REPR pattern, manuel uygulanabilece\u011fi gibi <a href=\"https:\/\/github.com\/FastEndpoints\/FastEndpoints\" target=\"_blank\">FastEndpoints<\/a> ya da <a href=\"https:\/\/github.com\/ardalis\/ApiEndpoints\" target=\"_blank\">ApiEndpoints<\/a> gibi k\u00fct\u00fcphaneler arac\u0131l\u0131\u011f\u0131yla da uygulanabilmektedir. \u015eimdi gelin her \u00fc\u00e7 y\u00f6ntemle de ilgili pattern&#8217;\u0131 pratiksel olarak uygulamay\u0131 ele alal\u0131m;<\/p>\n<h5>Manuel Uygulama (Controller-Based)<\/h5>\n<p>Misal olarak, bir kullan\u0131c\u0131n\u0131n i\u015f bilgilerinin g\u00fcncellenmesini \u00fcstlenecek olan bir endpoint&#8217;in REPR pattern ile manuel olarak tasar\u0131m\u0131 a\u015fa\u011f\u0131daki gibi olabilir;<\/p>\n<ol>\n<li>Kullan\u0131c\u0131n\u0131n yeni i\u015f bilgilerini bar\u0131nd\u0131racak olan bir request s\u0131n\u0131f\u0131 olu\u015fturulmal\u0131d\u0131r;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class UpdateUserJobRequest\r\n    {\r\n        public int UserId { get; set; }\r\n        public string NewJob { get; set; }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li>Ayn\u0131 \u015fekilde yap\u0131lacak g\u00fcncelleme i\u015flemi neticesinde geriye durum bilgisini d\u00f6nd\u00fcrecek olan response s\u0131n\u0131f\u0131 da olu\u015fturulmal\u0131d\u0131r;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class UpdateUserJobResponse\r\n    {\r\n        public int UserId { get; set; }\r\n        public string Message { get; set; }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li>Ve nihai olarak i\u015f mant\u0131\u011f\u0131n\u0131 uygulayabilmek i\u00e7in de bu i\u015fleme \u00f6zel bir controller s\u0131n\u0131f\u0131 olu\u015fturulmal\u0131 ve i\u00e7eri\u011fi de a\u015fa\u011f\u0131daki gibi operatif tasarlanmal\u0131d\u0131r;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Route(&quot;api\/users\/update-job&quot;)]\r\n    &#x5B;ApiController]\r\n    public class UpdateUserJobController : ControllerBase\r\n    {\r\n        &#x5B;HttpPut]\r\n        public IActionResult UpdateUserJobAsync(&#x5B;FromBody] UpdateUserJobRequest updateUserJobRequest)\r\n        {\r\n            \/\/Process...\r\n\r\n            var response = new UpdateUserJobResponse()\r\n            {\r\n                UserId = updateUserJobRequest.UserId,\r\n                Message = &quot;Job information has been successfully updated...&quot;\r\n            };\r\n            return Ok(response);\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<\/ol>\n<p>Evet, g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere REPR pattern e\u015fli\u011finde bir aksiyona kar\u015f\u0131l\u0131k sadece o aksiyona \u00f6zel geli\u015ftirilmi\u015f olan bir controller s\u0131n\u0131f\u0131 tasarlam\u0131\u015f ve gerekli \u00e7\u00f6z\u00fcm getirilmi\u015ftir. Benzer mant\u0131kla, bir kullan\u0131c\u0131n\u0131n eklenmesini de yine ayn\u0131 \u015fekilde ger\u00e7ekle\u015ftirebiliriz;<\/p>\n<ol>\n<li>Eklenecek kullan\u0131c\u0131 bilgilerini bar\u0131nd\u0131ran request olu\u015fturulmal\u0131;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class CreateUserRequest\r\n    {\r\n        public string Name { get; set; }\r\n        public string Surname { get; set; }\r\n        public int Age { get; set; }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li>Kullan\u0131c\u0131 olu\u015fturma neticesinde durum bilgisini d\u00f6nd\u00fcrecek response olu\u015fturulmal\u0131;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class CreateUserResponse\r\n    {\r\n        public int UserId { get; set; }\r\n        public string Message { get; set; }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li>Ve kullan\u0131c\u0131 ekleme i\u015flemi bu aksiyona \u00f6zel controller&#8217;da ger\u00e7ekle\u015ftirilmeli;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Route(&quot;api\/users\/create&quot;)]\r\n    &#x5B;ApiController]\r\n    public class CreateUserController : ControllerBase\r\n    {\r\n        &#x5B;HttpPost]\r\n        public IActionResult CreateUserAsync(&#x5B;FromBody] CreateUserRequest createUserRequest)\r\n        {\r\n            \/\/Process...\r\n\r\n            var response = new CreateUserResponse()\r\n            {\r\n                UserId = ...,\r\n                Message = &quot;The user has been successfully created...&quot;\r\n            };\r\n            return Ok(response);\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<\/ol>\n<p><div id=\"attachment_27439\" style=\"width: 244px\" class=\"wp-caption alignleft\"><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2025\/01\/REPRRequest-Endpoint-Response-Pattern-Nedir-Nasil-Uygulanir-Teferruatlica-Inceleyelim.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-27439\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2025\/01\/REPRRequest-Endpoint-Response-Pattern-Nedir-Nasil-Uygulanir-Teferruatlica-Inceleyelim.png\" alt=\"REPR(Request-Endpoint-Response) Pattern Nedir? Nas\u0131l Uygulan\u0131r? Teferruatl\u0131ca \u0130nceleyelim...\" width=\"234\" height=\"190\" class=\"size-full wp-image-27439\" \/><\/a><p id=\"caption-attachment-27439\" class=\"wp-caption-text\">Controller tabanl\u0131 REPR tasar\u0131m\u0131<\/p><\/div>Nas\u0131l&#8230; \u00c7ok sa\u00e7ma de\u011fil mi \ud83d\ude00 Projeyi \u015fi\u015firilmi\u015f controller s\u0131n\u0131flar\u0131ndan ar\u0131nd\u0131raca\u011f\u0131z derken her bir aksiyona kar\u015f\u0131l\u0131k b\u00f6yle tek tek controller s\u0131n\u0131f\u0131 olu\u015fturman\u0131n ilk bak\u0131\u015fta pek cazip gelmemesi kadar do\u011fal bir \u015fey olamaz san\u0131r\u0131m. Ben bile burada \u00f6rneklendirece\u011fim diye olu\u015fturdu\u011fum controller s\u0131n\u0131flar\u0131n\u0131n ya &#8216;Route&#8217; de\u011ferlerini g\u00fcncellemeyi unutuyorum ya action isimlendirmesinde nas\u0131l bir standart uyguluyordum diye di\u011ferlerine bakmadan bi sat\u0131r yazam\u0131yorum ya da action t\u00fcr\u00fcn\u00fc her seferinde yanl\u0131\u015f giriyorum. Evet, bu \u015fekilde manuel bir kullan\u0131m olduk\u00e7a zorluyor.<\/p>\n<p>Ki zaten REPR pattern&#8217;\u0131 uygularken b\u00f6yle controller s\u0131n\u0131flar\u0131yla cebelle\u015fmeyece\u011finizi s\u00f6ylemekte fayda var. Evet, bu pattern&#8217;\u0131n uyguland\u0131\u011f\u0131 projeler y\u00fcksek ihtimalle controller s\u0131n\u0131flar\u0131ndan ba\u011f\u0131ms\u0131z cereyan etmektedirler. Misal olarak, minimal api&#8217;ler akl\u0131n\u0131za gelebilir. Evet, art\u0131k Asp.NET Core deyince akla gelen minimal api&#8217;ler ile k\u0131smen swollen controller durumuna \u00e7\u00f6z\u00fcm getiriliyor olsa dahi, bir de REPR pattern ile bu yap\u0131lanmaya temas edildi\u011finde ap ayr\u0131 bir dinamizm s\u00f6z konusu olmaktad\u0131r diyebiliriz. \u015eimdi gelin manuel uygulama s\u00fcrecini bir de minimal api&#8217;ler \u00fczerinden tecr\u00fcbe edelim&#8230;<\/p>\n<h5>Manuel Uygulama (Minimal API-Based)<\/h5>\n<p>Tabi, minimal api&#8217;ler \u00fczerinden REPR pattern&#8217;\u0131 uygulayabilmenin en g\u00f6zde yolu <code><a href=\"https:\/\/www.gencayyildiz.com\/blog\/cqrs-pattern-nedir-mediatr-kutuphanesi-ile-nasil-uygulanir\/\" target=\"_blank\">MediatR<\/a><\/code> k\u00fct\u00fcphanesinden istifade etmektir. CQRS mant\u0131\u011f\u0131nda gelen istekleri hem command-query mahiyetinde ay\u0131rt edebilece\u011fiz hem de REPR pattern davran\u0131\u015f\u0131n\u0131 da rahatl\u0131kla uygulayabildi\u011fimizi g\u00f6rece\u011fiz. \u015eimdi bir \u00f6nceki controller-based \u00f6rnek senaryolar\u0131n\u0131 gelin minimal api&#8217;lerle de ger\u00e7ekle\u015ftirelim;<\/p>\n<p>\u00d6ncelikle <code><a href=\"https:\/\/www.nuget.org\/packages\/Mediator.SourceGenerator\/\" target=\"_blank\">Mediator.SourceGenerator<\/a><\/code> ve <code><a href=\"https:\/\/www.nuget.org\/packages\/Mediator.Abstractions\/\" target=\"_blank\">Mediator.Abstractions<\/a><\/code> k\u00fct\u00fcphanelerinin projeye y\u00fcklenmesi gerekmektedir. Bu k\u00fct\u00fcphaneler Mediator framework&#8217;\u00fcn\u00fcn birer par\u00e7as\u0131d\u0131rlar ve \u00f6zellikle davran\u0131\u015fsal olarak Mediator pattern&#8217;\u0131n\u0131n performans\u0131n\u0131 art\u0131rmak ve runtime yerine compile-time&#8217;da i\u015flemleri ger\u00e7ekle\u015ftirmek i\u00e7in kullan\u0131lmaktad\u0131rlar. <code>Mediator.SourceGenerator<\/code>, <code>MediatR<\/code> k\u00fct\u00fcphanesine nazaran gelen istekleri runtime&#8217;da dependency injection ve reflection ile \u00e7\u00f6zmeye yeltenmeksizin direkt compile-time&#8217;da yap\u0131lan kodsal in\u015faya uygun olarak otomatik \u00fcretilen kodlarla kar\u015f\u0131lamay\u0131 ve b\u00f6ylece istek s\u00fcre\u00e7lerindeki performans ve maliyet a\u00e7\u0131s\u0131ndan verimlilikleri ciddi art\u0131rmay\u0131 sa\u011flamaktad\u0131r. \u0130\u015fte bu y\u00fczden CQRS ya da REPR pattern davran\u0131\u015flar\u0131n\u0131 uygularken <code>MediatR<\/code> yerine <code>Mediator.SourceGenerator<\/code> k\u00fct\u00fcphanesini tercih edebiliriz, edece\u011fiz de&#8230;<\/p>\n<p>\u0130\u015fte bu zemin \u00fczerine kullan\u0131c\u0131n\u0131n i\u015f bilgilerinin g\u00fcncellenmesini \u00fcstlenecek olan endpoint&#8217;i a\u015fa\u011f\u0131daki gibi tasarlayabiliriz;<\/p>\n<ol>\n<li>Kullan\u0131c\u0131n\u0131n yeni i\u015f bilgilerini bar\u0131nd\u0131racak request s\u0131n\u0131f\u0131 tan\u0131mlanmal\u0131;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class UpdateUserJobCommandRequest : IRequest&lt;UpdateUserJobCommandResponse&gt;\r\n    {\r\n        public int UserId { get; set; }\r\n        public string NewJob { get; set; }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li>G\u00fcncelleme i\u015flemi neticesinde geriye durum bilgisini d\u00f6nd\u00fcrecek response s\u0131n\u0131f\u0131 tan\u0131mlanmal\u0131;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class UpdateUserJobCommandResponse\r\n    {\r\n        public int UserId { get; set; }\r\n        public string Message { get; set; }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li>Ve nihai olarak g\u00fcncelleme i\u015flemini yapacak operatif handler s\u0131n\u0131f\u0131 tasarlanmal\u0131d\u0131r;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class UpdateUserJobCommandHandler : IRequestHandler&lt;UpdateUserJobCommandRequest, UpdateUserJobCommandResponse&gt;\r\n    {\r\n        public ValueTask&lt;UpdateUserJobCommandResponse&gt; Handle(UpdateUserJobCommandRequest request, CancellationToken cancellationToken)\r\n        {\r\n            \/\/Process...\r\n\r\n            var response = new UpdateUserJobCommandResponse()\r\n            {\r\n                UserId = request.UserId,\r\n                Message = &quot;Job information has been successfully updated...&quot;\r\n            };\r\n\r\n            return ValueTask.FromResult(response);\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li>Bu noktaya kadar her \u015fey yolunda&#8230; \u015eimdi bu i\u015flemin iste\u011fini kar\u015f\u0131layacak olan endpoint tasarlanmal\u0131d\u0131r. Bunun i\u00e7in a\u015fa\u011f\u0131daki \u00e7al\u0131\u015fmaya g\u00f6z atabilirsiniz;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public static class UpdateUserJobCommandEndpoint\r\n    {\r\n        public static RouteGroupBuilder UpdateUserJobEndpoint(this RouteGroupBuilder routeGroupBuilder)\r\n        {\r\n            routeGroupBuilder.MapPut(pattern: &quot;\/update-job&quot;, async (UpdateUserJobCommandRequest updateUserJobCommandRequest, IMediator mediator) =&gt;\r\n            {\r\n                var result = await mediator.Send(updateUserJobCommandRequest);\r\n\r\n                return new ObjectResult(result)\r\n                {\r\n                    StatusCode = (int)HttpStatusCode.Created\r\n                };\r\n            });\r\n\r\n            return routeGroupBuilder;\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere sadece kullan\u0131c\u0131n\u0131n i\u015f bilgilerini g\u00fcncelleme iste\u011fini kar\u015f\u0131layacak bir endpoint&#8217;i bar\u0131nd\u0131ran static s\u0131n\u0131f olu\u015fturmu\u015f bulunuyoruz. Ayn\u0131 minvalde di\u011fer aksiyonlar i\u00e7in de benzer yakla\u015f\u0131m\u0131 sergileyecek ve her birine \u00f6zel endpoint tasar\u0131m\u0131nda bulunaca\u011f\u0131z. Burada yap\u0131lan i\u015fleme dikkat edilirse e\u011fer ismi taraf\u0131m\u0131zca opsiyonel bir \u015fekilde belirlenmi\u015f<span style=\"font-size:12px;\">(<code>UpdateUserJobEndpoint<\/code>)<\/span> ve <code>RouteGroupBuilder<\/code> referans\u0131 \u00fczerinden eri\u015filebilir olan bir extension metot tan\u0131mlanm\u0131\u015ft\u0131r ve metot i\u00e7erisinde GET, POST, PUT vs. gibi endpoint&#8217;ler aksiyona \u00f6zel tasarlanmaktad\u0131r. \u015eimdi bu ve buna benzer \u015fekilde tasarlanm\u0131\u015f olan endpoint(ler)&#8217;i bir sonraki ad\u0131mda merkezi bir noktada toplayacak ve ard\u0131ndan uygulamaya dahil ediyor olaca\u011f\u0131z.\n<\/li>\n<li>\nArt\u0131k endpoint&#8217;i tasarlanm\u0131\u015f olan aksiyonu sisteme tam dahil edebilmek i\u00e7in bunun ve bunun gibi di\u011ferlerinin merkezi bir noktada a\u015fa\u011f\u0131daki gibi toplanmas\u0131 gerekmektedir;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public static class UserEndpoints\r\n    {\r\n        public static void RegisterUsersEndpoints(this WebApplication application)\r\n        {\r\n            application.MapGroup(prefix: &quot;api2\/users&quot;)\r\n                .UpdateUserJobEndpoint();\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Evet, g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere kullan\u0131c\u0131larla ilgili yap\u0131lan t\u00fcm i\u015flemler yukar\u0131da tasarlanm\u0131\u015f olan <code>UserEndpoints<\/code> static s\u0131n\u0131f\u0131 \u00fczerinde <code style=\"color:purple;\">api2\/users<\/code> yolunda maplenmektedirler. Ayr\u0131ca <code>MapGroup<\/code> metodu geriye <code>RouteGroupBuilder<\/code> d\u00f6nd\u00fcrd\u00fc\u011f\u00fcnden dolay\u0131 bir \u00f6nceki ad\u0131mda olu\u015fturdu\u011fumuz <code>UpdateUserJobEndpoint<\/code> extension metodumuza da direkt eri\u015fim sa\u011flanm\u0131\u015ft\u0131r ve b\u00f6ylece bu merkeze ilgili aksiyona dair endpoint dahil edilmi\u015ftir. Tabi bu i\u015flem neticesinde <code style=\"color:purple;\">api2\/users<span style=\"color:green;\">\/update-job<\/span><\/code> yoluyla ilgili endpoint&#8217;e eri\u015fim\/istek sa\u011flanabilecektir.\n<\/li>\n<li>\nSon olarak art\u0131k <code>UserEndpoints<\/code>&#8216;te ki maplenmi\u015f t\u00fcm endpoint&#8217;lerin uygulamaya dahil edilmesi gerekmektedir. Bunun i\u00e7in de <code>UserEndpoints<\/code> gibi t\u00fcm aksiyonlara kar\u015f\u0131n olu\u015fturulan merkezi endpoint gruplar\u0131n\u0131 tek elden uygulamaya dahil etmeyi sa\u011flayacak a\u015fa\u011f\u0131daki gibi bir mapping&#8217;in olu\u015fturulmas\u0131 gerekmektedir;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public static class RegisterRequestMapping\r\n    {\r\n        public static void RegisterMappings(this WebApplication application)\r\n        {\r\n            UserEndpoints.RegisterUsersEndpoints(application);\r\n            .\r\n            . Di\u011ferleri...\r\n            .\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Evet, b\u00f6ylece art\u0131k <code>RegisterRequestMapping<\/code> static s\u0131n\u0131f\u0131 i\u00e7erisindeki <code>RegisterMappings<\/code> extension metodunu a\u015fa\u011f\u0131daki gibi <em>Program.cs<\/em>&#8216;de \u00e7a\u011f\u0131r\u0131p, uygulamadaki t\u00fcm endpoint yap\u0131land\u0131rmalar\u0131n\u0131 sisteme entegre edebilir ve minimal api&#8217;ler de REPR pattern e\u015fli\u011finde bir tasar\u0131ma sahip olunabilir.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nusing REPR.Pattern.Example.Manuel_Implementation.Minimal_API_Based.Endpoints;\r\n\r\nvar builder = WebApplication.CreateBuilder(args);\r\nbuilder.Services.AddMediator(options =&gt;\r\n{\r\n    options.ServiceLifetime = ServiceLifetime.Scoped;\r\n});\r\n\r\nvar app = builder.Build();\r\n\r\napp.RegisterMappings();\r\n\r\napp.Run();\r\n<\/pre>\n<\/div>\n<\/li>\n<\/ol>\n<p>\u0130\u015fte bu kadar&#8230; Evet, minimal api&#8217;ler de olay biraz zor(mu\u015f) gibi g\u00f6z\u00fck\u00fcyor olabilir ancak esas\u0131nda \u00f6yle de\u011fil. \u015eimdi gelin ikinci \u00f6rnek olarak bir kullan\u0131c\u0131 eklemeyi de sim\u00fcle edelim. \u0130nan\u0131yorum ki daha iyi anla\u015f\u0131lacakt\u0131r;<\/p>\n<ol>\n<li>Eklenecek kullan\u0131c\u0131 bilgilerini bar\u0131nd\u0131ran request s\u0131n\u0131f\u0131 tan\u0131mlanmal\u0131;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class CreateUserCommandRequest : IRequest&lt;CreateUserCommandResponse&gt;\r\n    {\r\n        public string Name { get; set; }\r\n        public string Surname { get; set; }\r\n        public int Age { get; set; }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li>Response tan\u0131mlanmal\u0131;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class CreateUserCommandResponse\r\n    {\r\n        public int UserId { get; set; }\r\n        public string Message { get; set; }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li>Ve istek handle edilmelidir;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class CreateUserCommandHandler : IRequestHandler&lt;CreateUserCommandRequest, CreateUserCommandResponse&gt;\r\n    {\r\n        public ValueTask&lt;CreateUserCommandResponse&gt; Handle(CreateUserCommandRequest request, CancellationToken cancellationToken)\r\n        {\r\n            \/\/Process...\r\n\r\n            var response = new CreateUserCommandResponse()\r\n            {\r\n                UserId = 0,\r\n                Message = $&quot;The user has been successfully created... | {request.Name}, {request.Surname}, {request.Age}&quot;\r\n            };\r\n\r\n            return ValueTask.FromResult(response);\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li>Devam\u0131nda ise bu aksiyon i\u00e7in bir endpoint olu\u015fturulmal\u0131;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public static class CreateUserCommandEndpoint\r\n    {\r\n        public static RouteGroupBuilder CreateUserEndpoint(this RouteGroupBuilder routeGroupBuilder)\r\n        {\r\n            routeGroupBuilder.MapPost(pattern: &quot;\/create&quot;, async (CreateUserCommandRequest createUserCommandRequest, IMediator mediator) =&gt;\r\n            {\r\n                var result = await mediator.Send(createUserCommandRequest);\r\n\r\n                return new ObjectResult(result)\r\n                {\r\n                    StatusCode = (int)HttpStatusCode.Created\r\n                };\r\n            });\r\n\r\n            return routeGroupBuilder;\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li>Ve bu endpoint&#8217;te <code>UserEndpoints<\/code> static s\u0131n\u0131f\u0131na eklenerek sisteme dahil edilmelidir;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public static class UserEndpoints\r\n    {\r\n        public static void RegisterUsersEndpoints(this WebApplication application)\r\n        {\r\n            application.MapGroup(prefix: &quot;api2\/users&quot;)\r\n                .UpdateUserJobEndpoint()\r\n                .CreateUserEndpoint();\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<\/ol>\n<p><div id=\"attachment_27441\" style=\"width: 316px\" class=\"wp-caption alignleft\"><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2025\/01\/REPRRequest-Endpoint-Response-Pattern-Nedir-Nasil-Uygulanir-Teferruatlica-Inceleyelim-1.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-27441\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2025\/01\/REPRRequest-Endpoint-Response-Pattern-Nedir-Nasil-Uygulanir-Teferruatlica-Inceleyelim-1.png\" alt=\"REPR(Request-Endpoint-Response) Pattern Nedir? Nas\u0131l Uygulan\u0131r? Teferruatl\u0131ca \u0130nceleyelim...\" width=\"306\" height=\"301\" class=\"size-full wp-image-27441\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2025\/01\/REPRRequest-Endpoint-Response-Pattern-Nedir-Nasil-Uygulanir-Teferruatlica-Inceleyelim-1.png 306w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2025\/01\/REPRRequest-Endpoint-Response-Pattern-Nedir-Nasil-Uygulanir-Teferruatlica-Inceleyelim-1-300x295.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2025\/01\/REPRRequest-Endpoint-Response-Pattern-Nedir-Nasil-Uygulanir-Teferruatlica-Inceleyelim-1-80x80.png 80w\" sizes=\"auto, (max-width: 306px) 100vw, 306px\" \/><\/a><p id=\"caption-attachment-27441\" class=\"wp-caption-text\">Minimal API tabanl\u0131 REPR tasar\u0131m\u0131<\/p><\/div>\u0130\u015fte bu kadar \ud83d\ude42 Asl\u0131nda, \u00f6zellikle minimal api&#8217;ler arac\u0131l\u0131\u011f\u0131yla yapt\u0131\u011f\u0131m\u0131z bu davran\u0131\u015f ile dikey bir mimari zeminini olabildi\u011fince en verimli \u015fekilde in\u015fa etti\u011fimizi s\u00f6yleyebiliriz.<\/p>\n<p>Evet, art\u0131k olay\u0131 manuel deneyimledi\u011fimize g\u00f6re davran\u0131\u015fsal mant\u0131\u011f\u0131n yeterince anla\u015f\u0131ld\u0131\u011f\u0131n\u0131 d\u00fc\u015f\u00fcn\u00fcyorum. \u015eimdi s\u0131ra, tercihen haz\u0131r k\u00fct\u00fcphanelerle bu davran\u0131\u015f\u0131 \u015fekillendirmeye \u00e7al\u0131\u015ft\u0131\u011f\u0131m\u0131zda nas\u0131l bir yap\u0131land\u0131rman\u0131n olabilece\u011fini incelemeye gelmi\u015ftir. Bunun i\u00e7in \u00f6ncelikle FastEndpoints k\u00fct\u00fcphanesi \u00fczerinden incelemede bulunaca\u011f\u0131z. Ard\u0131ndan ApiEndpoints k\u00fct\u00fcphanesine g\u00f6z ataca\u011f\u0131z.<\/p>\n<h5>FastEndpoints \u0130le REPR Pattern&#8217;i Uygulama<\/h5>\n<p>FastEndpoints, geleneksel Asp.NET Core controller ya da minimal api yap\u0131lanmalar\u0131na kar\u015f\u0131n daha ak\u0131c\u0131 bir \u015fekilde REPR pattern&#8217;\u0131n\u0131 uygulamam\u0131z\u0131 sa\u011flayan bir k\u00fct\u00fcphanedir. \u015eimdi bu k\u00fct\u00fcphane ile ilgili davran\u0131\u015f\u0131 sergileyebilmek i\u00e7in her \u015feyden \u00f6nce <a href=\"https:\/\/www.nuget.org\/packages\/FastEndpoints\" target=\"_blank\">FastEndpoints<\/a> k\u00fct\u00fcphanesinin uygulamaya y\u00fcklenmesi gerekmektedir. Ard\u0131ndan uygulaman\u0131n <em>Program.cs<\/em> dosyas\u0131nda a\u015fa\u011f\u0131daki yap\u0131land\u0131rma ger\u00e7ekle\u015ftirilip, ilk elden sistemsel entegrasyon sa\u011flanmal\u0131d\u0131r.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nusing FastEndpoints;\r\n\r\nvar builder = WebApplication.CreateBuilder(args);\r\nbuilder.Services.AddFastEndpoints();\r\n\r\nvar app = builder.Build();\r\n\r\napp.UseFastEndpoints();\r\n\r\napp.Run();\r\n<\/pre>\n<\/div>\n<p>Bu a\u015famadan sonras\u0131 klasik request, response ve endpoint handler \u00e7al\u0131\u015fmas\u0131 olacakt\u0131r. \u015eimdi gelin, yukar\u0131daki sat\u0131rlarda yapt\u0131\u011f\u0131m\u0131z \u00f6rnek senaryolar\u0131 FastEndpoints \u00fczerinden ger\u00e7ekle\u015ftirmeye ba\u015flayal\u0131m;<\/p>\n<p>\u0130lk olarak kullan\u0131c\u0131n\u0131n i\u015f bilgilerini g\u00fcncellemeye bakal\u0131m;<\/p>\n<ol>\n<li>Kullan\u0131c\u0131n\u0131n yeni i\u015f bilgilerini bar\u0131nd\u0131racak olan request s\u0131n\u0131f\u0131;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public record UpdateUserJobRequest(int UserId, string NewJob)\r\n    {\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li>\nResponse s\u0131n\u0131f\u0131;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public record UpdateUserJobResponse(int UserId, string Message)\r\n    {\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li>Ve iste\u011fe kar\u015f\u0131n i\u015f mant\u0131\u011f\u0131n\u0131n y\u00fcr\u00fct\u00fclece\u011fi operatif endpoint s\u0131n\u0131f\u0131;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class UpdateUserJobEndpoint : Endpoint&lt;UpdateUserJobRequest, UpdateUserJobResponse&gt;\r\n    {\r\n        public override void Configure()\r\n        {\r\n            Put(&quot;\/api3\/users\/update-job&quot;);\r\n            AllowAnonymous();\r\n        }\r\n\r\n        public override async Task HandleAsync(UpdateUserJobRequest req, CancellationToken ct)\r\n        {\r\n            \/\/Process...\r\n\r\n            var response = new UpdateUserJobResponse(req.UserId, &quot;Job information has been successfully updated...&quot;);\r\n\r\n            await SendAsync(response);\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Burada dikkat edilirse e\u011fer endpoint s\u0131n\u0131f\u0131 i\u00e7erisinde route ve eri\u015fim gibi temel yap\u0131land\u0131rmalar override edilmi\u015f olan <code>Configure<\/code> metodu i\u00e7erisinde ger\u00e7ekle\u015ftirilmektedir. Geri kalan istekle ilgili t\u00fcm operasyonlar yine override edilmi\u015f olan <code>HandleAsync<\/code> metodu i\u00e7erisinde y\u00fcr\u00fct\u00fclmekte ve varsa istek neticesinde bir response bu da <code>SendAsync<\/code> ile geriye d\u00f6nd\u00fcr\u00fclmektedir.\n<\/li>\n<\/ol>\n<p>Benzer mant\u0131kla kullan\u0131c\u0131 ekleme senaryosunu da FastEndpoints ile \u00f6rneklendirirsek e\u011fer;<\/p>\n<ol>\n<li>Eklenecek kullan\u0131c\u0131 bilgilerini bar\u0131nd\u0131ran request s\u0131n\u0131f\u0131;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public record CreateUserRequest(string Name, string Surname, int Age)\r\n    {\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li>\nResponse s\u0131n\u0131f\u0131;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public record CreateUserResponse(int UserId, string Message)\r\n    {\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li>\nVe i\u015f mant\u0131\u011f\u0131n\u0131n y\u00fcr\u00fct\u00fcld\u00fc\u011f\u00fc endpoint s\u0131n\u0131f\u0131;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class CreateUserEndpoint : Endpoint&lt;CreateUserRequest, CreateUserResponse&gt;\r\n    {\r\n        public override void Configure()\r\n        {\r\n            Post(&quot;\/api3\/users\/create&quot;);\r\n            AllowAnonymous();\r\n        }\r\n\r\n        public override async Task HandleAsync(CreateUserRequest req, CancellationToken ct)\r\n        {\r\n            \/\/Process...\r\n\r\n            var response = new CreateUserResponse(0, $&quot;The user has been successfully created... | {req.Name}, {req.Surname}, {req.Age}&quot;);\r\n\r\n            await SendAsync(response);\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<\/ol>\n<p><div id=\"attachment_27445\" style=\"width: 245px\" class=\"wp-caption alignleft\"><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2025\/01\/REPRRequest-Endpoint-Response-Pattern-Nedir-Nasil-Uygulanir-Teferruatlica-Inceleyelim-2.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-27445\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2025\/01\/REPRRequest-Endpoint-Response-Pattern-Nedir-Nasil-Uygulanir-Teferruatlica-Inceleyelim-2.png\" alt=\"REPR(Request-Endpoint-Response) Pattern Nedir Nas\u0131l Uygulan\u0131r Teferruatl\u0131ca \u0130nceleyelim...\" width=\"235\" height=\"189\" class=\"size-full wp-image-27445\" \/><\/a><p id=\"caption-attachment-27445\" class=\"wp-caption-text\">FastEndpoins REPR tasar\u0131m\u0131<\/p><\/div>Evet, g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere FastEndpoints k\u00fct\u00fcphanesiyle REPR pattern&#8217;\u0131 olduk\u00e7a kolay ve sade bir \u015fekilde uygulayabilmekte ve \u00f6zellikle projenin yap\u0131s\u0131n\u0131 da karma\u015f\u0131kla\u015ft\u0131rmaks\u0131z\u0131n daha az dosya bar\u0131nd\u0131racak \u015fekilde bir \u00e7al\u0131\u015fma y\u00fcr\u00fct\u00fclebilmektedir.<\/p>\n<p>Tabi bunun d\u0131\u015f\u0131nda FastEndpoints k\u00fct\u00fcphanesi ile di\u011fer istek t\u00fcrlerinin yan\u0131nda, farkl\u0131 \u015fekillerde model binding yakla\u015f\u0131mlar\u0131 sergilenebilmekte ve bunlar\u0131n haricinde de validation, dependency injection, authorization, authentication, token generation vs. gibi \u00fcst d\u00fczey bir\u00e7ok yetenekte beraberinde gelmektedir. Bunlar\u0131 incelemek ve tecr\u00fcbe edebilmek i\u00e7in <a href=\"https:\/\/fast-endpoints.com\/docs\/get-started#create-project-install-package\" target=\"_blank\">\u015furadaki<\/a> dok\u00fcmantasyondan istifade edebilirsiniz.<\/p>\n<h5>ApiEndpoints \u0130le REPR Pattern\u2019i Uygulama<\/h5>\n<p>\u015eu ana kadar yapm\u0131\u015f oldu\u011fumuz davran\u0131\u015f\u0131 birebir ayn\u0131 \u015fekilde ApiEndpoints k\u00fct\u00fcphanesiyle de sergileyebiliriz. Bunun i\u00e7in tabi ki de \u00f6ncelikle ilgili projeye <a href=\"https:\/\/www.nuget.org\/packages\/Ardalis.ApiEndpoints\/\" target=\"_blank\">Ardalis.ApiEndpoints<\/a> k\u00fct\u00fcphanesinin y\u00fcklenmesi gerekmektedir.<\/p>\n<p>Ard\u0131ndan <em>Program.cs<\/em> dosyas\u0131nda a\u015fa\u011f\u0131daki gibi controller yap\u0131land\u0131rmas\u0131n\u0131n sa\u011flanmas\u0131 gerekmektedir;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar builder = WebApplication.CreateBuilder(args);\r\nbuilder.Services.AddControllers();\r\nvar app = builder.Build();\r\n\r\napp.MapControllers();\r\n\r\napp.Run();\r\n<\/pre>\n<\/div>\n<p>Bu a\u015famadan sonra yap\u0131lacak i\u015fleme uygun request, response ve endpoint s\u0131n\u0131flar\u0131n\u0131n tasarlanmas\u0131 kafidir. \u015e\u00f6yle ki, bizler yukar\u0131daki sat\u0131rlarda yapt\u0131\u011f\u0131m\u0131z senaryolar\u0131, art\u0131k i\u00e7eri\u011fi haddinden fazla \u015fi\u015firmemek ve yersiz tekrara u\u011fratmamak i\u00e7in request ve response s\u0131n\u0131flar\u0131na de\u011finmeksizin direkt endpoint s\u0131n\u0131flar\u0131na odaklanarak \u00f6rneklendirelim;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class UpdateUserJobEndpoint : EndpointBaseAsync.WithRequest&lt;UpdateUserJobRequest&gt;.WithActionResult&lt;UpdateUserJobResponse&gt;\r\n    {\r\n        &#x5B;HttpPut(&quot;api4\/users\/update-job&quot;)]\r\n        public override async Task&lt;ActionResult&lt;UpdateUserJobResponse&gt;&gt; HandleAsync(UpdateUserJobRequest request, CancellationToken cancellationToken = default)\r\n        {\r\n            \/\/Process...\r\n\r\n            var response = new UpdateUserJobResponse(request.UserId, &quot;Job information has been successfully updated...&quot;);\r\n\r\n            return response;\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class CreateUserEndpoint : EndpointBaseAsync.WithRequest&lt;CreateUserRequest&gt;.WithActionResult&lt;CreateUserResponse&gt;\r\n    {\r\n        &#x5B;HttpPost(&quot;api4\/users\/create&quot;)]\r\n        public override async Task&lt;ActionResult&lt;CreateUserResponse&gt;&gt; HandleAsync(CreateUserRequest request, CancellationToken cancellationToken = default)\r\n        {\r\n            \/\/Process...\r\n\r\n            var response = new CreateUserResponse(0, $&quot;The user has been successfully created... | {request.Name}, {request.Surname}, {request.Age}&quot;);\r\n\r\n            return response;\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>San\u0131r\u0131m kod maliyeti a\u00e7\u0131s\u0131ndan en uygunu ApiEndpoints k\u00fct\u00fcphanesiyle yap\u0131lan \u00e7al\u0131\u015fma oldu\u011fu a\u015fikar olsa gerek.<\/p>\n<p>Dikkat ederseniz belirli bir mimari stili olu\u015fturmak i\u00e7in REPR pattern&#8217;\u0131 kullanmak mecburiyetinde de\u011filiz. Yani bu pattern&#8217;\u0131 kullanarak uygulaman\u0131n gereksinimlerine g\u00f6re RESTful kaynaklar\u0131 ve hatta RPC tarz\u0131 endpoint&#8217;leri tan\u0131mlayabiliriz. En nihayetinde REPR pattern ile yapt\u0131\u011f\u0131m\u0131z \u00e7al\u0131\u015fmalarda g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere hangi tarzda bir endpoint yap\u0131s\u0131 kullan\u0131yorsak kullanal\u0131m uygulamadaki katmanlar\u0131 birbirlerinden izole ederek kod seviyesinde okunabilirlik, s\u00fcrd\u00fcr\u00fclebilirlik ve \u00f6l\u00e7eklenebilirlik sa\u011flayabildi\u011fimiz a\u015fikard\u0131r. <\/p>\n<p>T\u00fcm bunlar\u0131n d\u0131\u015f\u0131nda unutulmamas\u0131 gereken bir husus da vard\u0131r ki, o da;<\/p>\n<blockquote><p><em>REPR deseni, bir REST deseni de\u011fildir!<\/em><\/p><\/blockquote>\n<p>Haliyle kaynaklar\u0131 tan\u0131mlamak i\u00e7in de\u011fil, bir ka\u00e7 sat\u0131r \u00f6nce bahsetti\u011fim gibi RESTful ya da RPC gibi API endpoint&#8217;lerini daha efektif tan\u0131mlayabilmek i\u00e7in kullan\u0131lan bir desendir.<\/p>\n<p>\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle&#8230;<br \/>\nSonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<p>Not : \u00d6rnek \u00e7al\u0131\u015fmaya a\u015fa\u011f\u0131daki github adresinden eri\u015febilirsiniz.<br \/>\n<a href=\"https:\/\/github.com\/gncyyldz\/REPR.Pattern.Example\" target=\"_blank\">https:\/\/github.com\/gncyyldz\/REPR.Pattern.Example<\/a><\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, Bu i\u00e7eri\u011fimizde, Asp.NET Core ile geli\u015ftirilen projelerin potansiyellerini daha farkl\u0131 bir \u015fekilde de\u011ferlendirmemizi sa\u011flayacak olan bir yakla\u015f\u0131m\u0131 inceliyor olaca\u011f\u0131z. REPR desenini&#8230; Bu desen, yaz\u0131l\u0131m geli\u015ftirme s\u00fcre\u00e7lerinde isteklerin(request) ve bu isteklere kar\u015f\u0131n verilen yan\u0131tlar\u0131n(response)&#46;&#46;&#46;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":3014,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2739,3102,153],"tags":[5201,5203,5202,4153,5199,5200,5198],"class_list":["post-27431","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net-core","category-asp-net-core","category-design-pattern","tag-fastendpoints","tag-mediator-abstractions","tag-mediator-sourcegenerator","tag-mediatr","tag-repr","tag-repr-pattern","tag-swollen-controller"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/27431","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/comments?post=27431"}],"version-history":[{"count":11,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/27431\/revisions"}],"predecessor-version":[{"id":27446,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/27431\/revisions\/27446"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/3014"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=27431"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=27431"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=27431"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}