﻿
{"id":16618,"date":"2020-07-21T20:38:55","date_gmt":"2020-07-21T20:38:55","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=16618"},"modified":"2020-07-21T20:38:55","modified_gmt":"2020-07-21T20:38:55","slug":"net-core-refit-kutuphanesi-nedir-nasil-kullanilir","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/net-core-refit-kutuphanesi-nedir-nasil-kullanilir\/","title":{"rendered":".NET Core &#8211; Refit K\u00fct\u00fcphanesi Nedir? Nas\u0131l Kullan\u0131l\u0131r?"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Bu i\u00e7eri\u011fimizde, uygulamalar\u0131m\u0131zda HttpClient yerine basit interface tan\u0131mlamalar\u0131 sayesinde Rest API&#8217;lar ile kolay ve h\u0131zl\u0131 bir \u015fekilde i\u015flemler yapmam\u0131z\u0131 sa\u011flayan olduk\u00e7a g\u00fc\u00e7l\u00fc Refit k\u00fct\u00fcphanesi \u00fczerine konu\u015fuyor olaca\u011f\u0131z. Makalemizde i\u00e7eriksel ak\u0131\u015f olarak Console Application \u00fczerinde temellendirmeler yap\u0131lmas\u0131n\u0131n ard\u0131ndan Asp.NET Core uygulamas\u0131 \u00fczerinde de entegrasyonun nas\u0131l ger\u00e7ekle\u015ftirildi\u011fini inceleyece\u011fiz. O halde hi\u00e7 vakit kaybetmeden Refit tan\u0131m\u0131yla ba\u015flayal\u0131m&#8230;<\/p>\n<p>\u0130\u00e7indekiler;<\/p>\n<ul>\n<li><a href=\"#baslik1\">Refit K\u00fct\u00fcphanesi Nedir?<\/a><\/li>\n<li><a href=\"#baslik2\">Nas\u0131l Kullan\u0131l\u0131r?<\/a><\/li>\n<li><a href=\"#baslik3\">API Attributes<\/a><\/li>\n<li><a href=\"#baslik4\">Dynamic Querystring Parameters<\/a><\/li>\n<li><a href=\"#baslik5\">Collections as Querystring parameters<\/a><\/li>\n<li><a href=\"#baslik6\">Unescape Querystring Parameters<\/a><\/li>\n<li><a href=\"#baslik7\">Headers Ekleme<\/a><\/li>\n<li><a href=\"#baslik8\">Dynamic Headers Ekleme<\/a><\/li>\n<li><a href=\"#baslik9\">Authorization (Dynamic Headers Redux)<\/a><\/li>\n<li><a href=\"#baslik10\">Header\u2019lar\u0131n Yeniden Tan\u0131mlanmas\u0131<\/a><\/li>\n<li><a href=\"#baslik11\">Header\u2019lar\u0131n Silinmesi<\/a><\/li>\n<li><a href=\"#baslik12\">Asp.NET Core Uygulamalar\u0131nda Refit Kullan\u0131m\u0131<\/a><\/li>\n<\/ul>\n<h3 style=\"color:#e83e8c;\" id=\"baslik1\">Refit K\u00fct\u00fcphanesi Nedir?<\/h3>\n<p>Temel anlamda Rest API&#8217;lar\u0131 uygulamada bir aray\u00fcze d\u00f6n\u00fc\u015ft\u00fcrerek ileti\u015fim kurulacak ba\u011f\u0131ml\u0131l\u0131klar\u0131 daha kolay bir \u015fekilde y\u00f6netmemizi sa\u011flayan ve Android taraf\u0131nda geli\u015ftirilmi\u015f olan Retrofit isimli k\u00fct\u00fcphaneden esinlenerek olu\u015fturulmu\u015f olan .NET tabanl\u0131 bir k\u00fct\u00fcphanedir.<\/p>\n<p>Refit k\u00fct\u00fcphanesinin i\u015flevsel a\u00e7\u0131dan bir\u00e7ok avantaj\u0131 mevcuttur;<\/p>\n<ul>\n<li>GET, POST, PUT ve DELETE gibi her t\u00fcrl\u00fc HTTP fonksiyonuna kar\u015f\u0131l\u0131k gelen metotlar olu\u015fturulabilmektedir,<\/li>\n<li>QueryString, Dynamic URL Parameter vs. gibi bir\u00e7ok farkl\u0131 \u015fekilde parametreler bar\u0131nd\u0131ran istekler olu\u015fturulabilmektedir,<\/li>\n<li>Datalar birden fazla serialization y\u00f6ntemi ile harmanlanarak POST edilebilmektedir,<\/li>\n<li>Multipart Upload&#8217;lar ile byte dizisi, string, Stream yahut FileInfo t\u00fcrlerinde dosya transferleri ger\u00e7ekle\u015ftirilebilmektedir,<\/li>\n<li>Yap\u0131lacak isteklere static yahut dynamic olmak \u00fczere kolayca headerlar eklenebilmektedir.<\/li>\n<\/ul>\n<h3 style=\"color:#e83e8c;\" id=\"baslik2\">Nas\u0131l Kullan\u0131l\u0131r?<\/h3>\n<blockquote><p><em>Temel kullan\u0131m \u00f6rneklendirmesi Console Application \u00fczerinden anlat\u0131lmaktad\u0131r.<\/em><\/p><\/blockquote>\n<p><a href=\"https:\/\/www.nuget.org\/packages\/Refit\/\" rel=\"noopener noreferrer\" target=\"_blank\">Refit<\/a> k\u00fct\u00fcphanesini kullanabilmek i\u00e7in \u00f6ncelikle a\u015fa\u011f\u0131daki kod ile projeye y\u00fcklenmesi gerekmektedir.<br \/>\n<code style=\"color:red;\"><strong>dotnet add package refit<\/strong><\/code><\/p>\n<p>Ard\u0131ndan hedef API&#8217;lar\u0131n bir interface \u00fczerinden modellenmesi gerekmektedir. Bizler burada \u00f6rneklendirme i\u00e7in <a href=\"http:\/\/jsonplaceholder.typicode.com\/todos\" rel=\"noopener noreferrer\" target=\"_blank\">http:\/\/jsonplaceholder.typicode.com\/todos<\/a> adresini hedef API olarak kullanacak ve t\u00fcm sistemi buradaki datalara g\u00f6re in\u015fa edece\u011fiz.<\/p>\n<p>Tabi \u00f6ncelikle ilgili adresteki dataya uygun bir entity olu\u015fturarak i\u015fe ba\u015flayal\u0131m.<br \/>\n<div id=\"attachment_16630\" style=\"width: 403px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/07\/NET-Core-Refit-K\u00fct\u00fcphanesi-Nedir-Nas\u0131l-Kullan\u0131l\u0131r..jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-16630\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/07\/NET-Core-Refit-K\u00fct\u00fcphanesi-Nedir-Nas\u0131l-Kullan\u0131l\u0131r..jpg\" alt=\".NET Core - Refit K\u00fct\u00fcphanesi Nedir? Nas\u0131l Kullan\u0131l\u0131r?\" width=\"393\" height=\"223\" class=\"size-full wp-image-16630\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/07\/NET-Core-Refit-K\u00fct\u00fcphanesi-Nedir-Nas\u0131l-Kullan\u0131l\u0131r..jpg 393w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/07\/NET-Core-Refit-K\u00fct\u00fcphanesi-Nedir-Nas\u0131l-Kullan\u0131l\u0131r.-300x170.jpg 300w\" sizes=\"auto, (max-width: 393px) 100vw, 393px\" \/><\/a><p id=\"caption-attachment-16630\" class=\"wp-caption-text\">Makalenin kaleme al\u0131nd\u0131\u011f\u0131 tarihte http:\/\/jsonplaceholder.typicode.com\/todos adresindeki \u00f6rnek data modeli&#8230;<\/p><\/div><\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n   public class Todo\r\n   {\r\n      public int userId { get; set; }\r\n      public int id { get; set; }\r\n      public string title { get; set; }\r\n      public bool completed { get; set; }\r\n   }\r\n<\/pre>\n<p>Ard\u0131ndan ilgili API&#8217;a a\u015fa\u011f\u0131daki aray\u00fcz\u00fc tasarlayal\u0131m.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodos();\r\n    }\r\n<\/pre>\n<p>Buradaki interface&#8217;e odaklan\u0131rsak e\u011fer kendisi hedef API&#8217;\u0131n base url&#8217;ine<span style=\"font-size:11px;color:blue;\">(http:\/\/jsonplaceholder.typicode.com)<\/span> kar\u015f\u0131l\u0131k gelmektedir. \u0130\u00e7erisinde tan\u0131mlanan imzalar ise ilgili base url&#8217;lerin tetiklenece\u011fi metotlar\u0131n\u0131 temsil etmektedir. \u00d6rne\u011fin; &#8216;Get&#8217; attribute&#8217;u ile i\u015faretlenmi\u015f &#8216;GetTodos&#8217; imzas\u0131 base url&#8217;in devam\u0131ndaki metodu\/yolu<span style=\"font-size:11px;color:blue;\">(\/todos)<\/span> temsil etmektedir. <\/p>\n<p>\u015eimdi bu aray\u00fcz \u00fczerinden hedef API&#8217;a bir istek g\u00f6nderelim;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n        static async Task Main(string&#x5B;] args)\r\n        {\r\n            ITodoAPI todoAPI = RestService.For&lt;ITodoAPI&gt;(&quot;http:\/\/jsonplaceholder.typicode.com&quot;);\r\n            List&lt;Todo&gt; todos = await todoAPI.GetTodos();\r\n            foreach (var todo in todos)\r\n                Console.WriteLine(todo.title);\r\n        }\r\n<\/pre>\n<p>Yukar\u0131daki kod blo\u011funu incelersek e\u011fer &#8216;RestService.For&#8217; komutu arac\u0131l\u0131\u011f\u0131yla base url&#8217;imizi belirlemekte ve d\u00f6n\u00fclen nesne \u00fczerinden interface&#8217;de tan\u0131mlanan imzalar vas\u0131tas\u0131yla ilgili metotlara istekler yapmaktay\u0131z.<br \/>\n<div id=\"attachment_16644\" style=\"width: 407px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/07\/NET-Core-Refit-K\u00fct\u00fcphanesi-Nedir-Nas\u0131l-Kullan\u0131l\u0131r.-1.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-16644\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/07\/NET-Core-Refit-K\u00fct\u00fcphanesi-Nedir-Nas\u0131l-Kullan\u0131l\u0131r.-1.jpg\" alt=\".NET Core - Refit K\u00fct\u00fcphanesi Nedir? Nas\u0131l Kullan\u0131l\u0131r?\" width=\"397\" height=\"124\" class=\"size-full wp-image-16644\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/07\/NET-Core-Refit-K\u00fct\u00fcphanesi-Nedir-Nas\u0131l-Kullan\u0131l\u0131r.-1.jpg 397w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/07\/NET-Core-Refit-K\u00fct\u00fcphanesi-Nedir-Nas\u0131l-Kullan\u0131l\u0131r.-1-300x94.jpg 300w\" sizes=\"auto, (max-width: 397px) 100vw, 397px\" \/><\/a><p id=\"caption-attachment-16644\" class=\"wp-caption-text\">\u00c7\u0131kt\u0131<\/p><\/div><\/p>\n<h3 style=\"color:#e83e8c;\" id=\"baslik3\">API Attributes<\/h3>\n<p>Refit \u00fczerinden attribute&#8217;lar ile birbirinden farkl\u0131 bir\u00e7ok annotations tan\u0131mlamas\u0131 yap\u0131labilmektedir. Bu tan\u0131mlamalar\u0131 incelersek e\u011fer;<\/p>\n<ul>\n<li><strong style=\"color:orange;\">[Get(&#8220;\/todos&#8221;)]<\/strong><br \/>\n\u015euana kadar yapt\u0131\u011f\u0131m\u0131z \u00f6rneklendirmelerde kulland\u0131\u011f\u0131m\u0131z t\u00fcrd\u00fcr.\n<\/li>\n<li><strong style=\"color:orange;\">[Get(&#8220;\/todos\/{id}&#8221;)]<\/strong><br \/>\nUrl&#8217;de parametreler belirtilebilmektedir.<br \/>\nTan\u0131mlanma;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos\/{id}&quot;)]\r\n        Task&lt;Todo&gt; GetTodo(int id);\r\n    }\r\n<\/pre>\n<p>Kullan\u0131m;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            ITodoAPI todoAPI = RestService.For&lt;ITodoAPI&gt;(&quot;http:\/\/jsonplaceholder.typicode.com&quot;);\r\n            Todo todo = await todoAPI.GetTodo(5);\r\n            Console.WriteLine(todo.title);\r\n<\/pre>\n<p>Ayr\u0131ca parametre ad\u0131n\u0131n url&#8217;dekiyle e\u015fle\u015fmedi\u011fi durumlarda a\u015fa\u011f\u0131daki gibi <span style=\"color:blue;\">&#8216;AliasAs&#8217;<\/span> attribute&#8217;u kullan\u0131labilir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos\/{id}&quot;)]\r\n        Task&lt;Todo&gt; GetTodo(&#x5B;AliasAs(&quot;id&quot;)]int todoid);\r\n    }\r\n<\/pre>\n<\/li>\n<li><strong style=\"color:orange;\">[Get(&#8220;\/todos?id={id}&#8221;)]<\/strong><br \/>\nBu \u015fekilde QueryString olacak \u015fekilde sorgu parametreleri de verilebilmektedir.<br \/>\nTan\u0131mlanma;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos?id={id}&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodosId(int id);\r\n    }\r\n<\/pre>\n<p>Kullan\u0131m;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            ITodoAPI todoAPI = RestService.For&lt;ITodoAPI&gt;(&quot;http:\/\/jsonplaceholder.typicode.com&quot;);\r\n            List&lt;Todo&gt; todos = await todoAPI.GetTodosId(5);\r\n            foreach (var todo in todos)\r\n                Console.WriteLine(todo.title);\r\n<\/pre>\n<\/li>\n<li><strong style=\"color:orange;\">[Get(&#8220;\/todos?id={request.Id}&#038;UserId={request.UserId}&#8221;)]<\/strong><br \/>\nURL parametreleri \u00f6zel bir nesneye ba\u011flanarak bu \u015fekilde kullan\u0131labilmektedirler.<br \/>\nCustom Object;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class TodoRequest\r\n    {\r\n        public int Id { get; set; }\r\n        public int UserId { get; set; }\r\n    }\r\n<\/pre>\n<p>Tan\u0131mlama;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos?id={request.Id}&amp;UserId={request.UserId}&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetByIdAndUserId(TodoRequest request);\r\n    }\r\n<\/pre>\n<p>Kullan\u0131m;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            ITodoAPI todoAPI = RestService.For&lt;ITodoAPI&gt;(&quot;http:\/\/jsonplaceholder.typicode.com&quot;);\r\n            List&lt;Todo&gt; todos = await todoAPI.GetByIdAndUserId(new TodoRequest { Id = 1, UserId = 1 });\r\n            foreach (var todo in todos)\r\n                Console.WriteLine(todo.title);\r\n<\/pre>\n<\/li>\n<li><strong style=\"color:orange;\">Tan\u0131mlanmayan Parametreler<\/strong><br \/>\nA\u015fa\u011f\u0131daki gibi tan\u0131mlanmayan parametreler QueryString parametresi olarak kullan\u0131lmaktad\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodo(int id);\r\n    }\r\n<\/pre>\n<p>\/todos?id=&#8230;\n<\/li>\n<li><strong style=\"color:orange;\">{**name} Parametresi<\/strong><br \/>\n{**name} parametresi ile tan\u0131mlanan ifadeler b\u00fct\u00fcnsel olarak kendisinden sonraki t\u00fcm tan\u0131mlamalar\u0131 kapsayabilmektedirler.<br \/>\nTan\u0131mlama;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/{**page}&quot;)]\r\n        Task&lt;Todo&gt; Get(string page);\r\n    }\r\n<\/pre>\n<p>Kullan\u0131m;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            ITodoAPI todoAPI = RestService.For&lt;ITodoAPI&gt;(&quot;http:\/\/jsonplaceholder.typicode.com&quot;);\r\n            Todo todo = await todoAPI.Get(&quot;todos\/5&quot;);\r\n            Console.WriteLine(todo.title);\r\n<\/pre>\n<\/li>\n<\/ul>\n<h3 style=\"color:#e83e8c;\" id=\"baslik4\">Dynamic Querystring Parameters<\/h3>\n<p>Bir nesne a\u015fa\u011f\u0131daki gibi dinamik olarak sorgu parametresi \u015feklinde belirtilebilmektedir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class TodoQueryParam\r\n    {\r\n        &#x5B;AliasAs(&quot;order&quot;)]\r\n        public string SortOrder { get; set; }\r\n        public int Limit { get; set; }\r\n    }\r\n<\/pre>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodos(TodoQueryParam todoQueryParam);\r\n    }\r\n<\/pre>\n<p>E\u011fer ki, API \u00fczerinde bir \u00f6nek tan\u0131mlanmas\u0131 gerekiyorsa Query attribute&#8217;unun kullan\u0131lmas\u0131 yeterli olacakt\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodosQuery(&#x5B;Query(&quot;search&quot;)]TodoQueryParam todoQueryParam);\r\n    }\r\n<\/pre>\n<p>B\u00f6ylece ilgili aray\u00fcz \u00fczerinden imzalar\u0131 kullan\u0131rken a\u015fa\u011f\u0131daki gibi API&#8217;lara istekler g\u00f6nderilmi\u015f olacakt\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            ITodoAPI todoAPI = RestService.For&lt;ITodoAPI&gt;(&quot;http:\/\/jsonplaceholder.typicode.com&quot;);\r\n            await todoAPI.GetTodos(new TodoQueryParam { Limit = 5, SortOrder = &quot;desc&quot; });\r\n            await todoAPI.GetTodosQuery(new TodoQueryParam { Limit = 5, SortOrder = &quot;desc&quot; });\r\n<\/pre>\n<p>&#8220;\/todos\/?order=desc&#038;Limit=5&#8221;<br \/>\n&#8220;\/todos\/?search.order=desc&#038;search.Limit=10&#8221;<\/p>\n<h3 style=\"color:#e83e8c;\" id=\"baslik5\">Collections as Querystring parameters<\/h3>\n<p>A\u015fa\u011f\u0131daki gibi interface i\u00e7erisindeki imzada tan\u0131mlanan koleksiyonel de\u011ferler direkt olarak query string de\u011ferleri olarak kullan\u0131lacakt\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodosMulti(&#x5B;Query(CollectionFormat.Multi)] int&#x5B;] ids);\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodosCsv(&#x5B;Query(CollectionFormat.Csv)] int&#x5B;] ids);\r\n    }\r\n<\/pre>\n<p>Her iki imza aras\u0131ndaki kullan\u0131m fark\u0131;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            ITodoAPI todoAPI = RestService.For&lt;ITodoAPI&gt;(&quot;http:\/\/jsonplaceholder.typicode.com&quot;);\r\n            await todoAPI.GetTodosMulti(new&#x5B;] { 3, 5, 7 });\r\n            await todoAPI.GetTodosCsv(new&#x5B;] { 3, 5, 7 });\r\n<\/pre>\n<p>\/todos?ids=3&#038;ids=5&#038;ids=7<br \/>\n\/todos?ids=3%2C5%2C7<\/p>\n<p>\u015feklinde olacakt\u0131r.<\/p>\n<p>Ayr\u0131ca a\u015fa\u011f\u0131daki gibi koleksiyonel parametrelerin &#8216;Query&#8217; attribute&#8217;u ile i\u015faretlenmeksizin &#8216;CollectionFormat&#8217; tan\u0131mlamas\u0131 yap\u0131lmad\u0131\u011f\u0131 durumlar olabilir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodosMulti(int&#x5B;] ids);\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodosCsv(int&#x5B;] ids);\r\n    }\r\n<\/pre>\n<p>\u0130\u015fte b\u00f6yle bir durumda &#8216;RestService&#8217; \u00fczerinden bir &#8216;RefitSettings&#8217; nesnesiyle genel konfig\u00fcrasyon sa\u011flanabilir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            ITodoAPI todoAPI = RestService.For&lt;ITodoAPI&gt;(&quot;http:\/\/jsonplaceholder.typicode.com&quot;, new RefitSettings { CollectionFormat = CollectionFormat.Csv });\r\n            await todoAPI.GetTodosMulti(new&#x5B;] { 3, 5, 7 });\r\n            await todoAPI.GetTodosCsv(new&#x5B;] { 3, 5, 7 });\r\n<\/pre>\n<h3 style=\"color:#e83e8c;\" id=\"baslik6\">Unescape Querystring Parameters<\/h3>\n<p>\u0130mza parametrelerine verilen de\u011ferler URL yap\u0131s\u0131na uygun olmayan karakterleri bar\u0131nd\u0131r\u0131yorsa e\u011fer taray\u0131c\u0131lar taraf\u0131ndan otomatik escape karakterlerine d\u00f6n\u00fc\u015ft\u00fcr\u00fcl\u00fcrler. \u00d6rne\u011fin;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodos(string q);\r\n    }\r\n<\/pre>\n<p>bu aray\u00fcze uygun \u015f\u00f6yle bir istek g\u00f6nderilirse e\u011fer<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            ITodoAPI todoAPI = RestService.For&lt;ITodoAPI&gt;(&quot;http:\/\/jsonplaceholder.typicode.com&quot;);\r\n            await todoAPI.GetTodos(&quot;sebepsiz+bo\u015f+yere.ayr\u0131lacaksan!&quot;);\r\n<\/pre>\n<p>\/todos?q=sebepsiz%2Bbo%C5%9F%2Byere.ayr%C4%B1lacaksan%21<br \/>\n\u015feklinde query string de\u011feri olu\u015fturulacakt\u0131r.<\/p>\n<p>Lakin bu \u015fekilde \u00f6zel karakterlerin query string de\u011ferine oldu\u011fu gibi eklenmesini istiyorsak e\u011fer ilgili imzay\u0131 a\u015fa\u011f\u0131daki gibi &#8216;QueryUriFormat&#8217; attribute&#8217;u ile i\u015faretleyerek &#8216;UriFormat.Unescaped&#8217; de\u011ferinin verilmesi yeterli olacakt\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        &#x5B;QueryUriFormat(UriFormat.Unescaped)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodos(string q);\r\n    }\r\n<\/pre>\n<p>\/todos?q=sebepsiz+bo%C5%9F+yere.ayr%C4%B1lacaksan!<\/p>\n<h3 style=\"color:#e83e8c;\" id=\"baslik7\">Headers Ekleme<\/h3>\n<p>Yap\u0131lacak isteklere metot seviyesinde ve interface seviyesinde olmak \u00fczere iki t\u00fcrl\u00fc header eklenebilmektedir.<\/p>\n<p><em>Metot seviyesinde header ekleme;<\/em><\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Headers(&quot;name:gencay yildiz&quot;)]\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodos();\r\n    }\r\n<\/pre>\n<p><em>Interface seviyesinde header ekleme;<\/em><\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Headers(&quot;name:gencay yildiz&quot;)]\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodos();\r\n    }\r\n<\/pre>\n<h3 style=\"color:#e83e8c;\" id=\"baslik8\">Dynamic Headers Ekleme<\/h3>\n<p>A\u015fa\u011f\u0131daki gibi dinamik bir \u015fekilde header eklenebilmektedir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        Task&lt;Todo&gt; GetTodos(&#x5B;Header(&quot;authorization&quot;)] string authorization);\r\n    }\r\n<\/pre>\n<h3 style=\"color:#e83e8c;\" id=\"baslik9\">Authorization (Dynamic Headers Redux)<\/h3>\n<p>Genellikle header authorization i\u015flemlerinde token ta\u015f\u0131mak amac\u0131yla kullan\u0131lan bir yap\u0131d\u0131r. Dolay\u0131s\u0131yla bu yap\u0131ya dinamik bir s\u00fcre\u00e7 neticesinde a\u015fa\u011f\u0131daki gibi token de\u011feri set edilebilir ve talep \u00f6ylece g\u00f6nderilebilir.<\/p>\n<p>Tabi bu dinamik s\u00fcreci in\u015fa edebilmek i\u00e7in a\u015fa\u011f\u0131daki ad\u0131mlar\u0131n s\u0131ras\u0131yla uygulanmas\u0131 gerekmektedir;<\/p>\n<ul>\n<li><strong>Ad\u0131m 1<\/strong><br \/>\n\u00d6ncelikle <em>&#8216;HttpClientHandler&#8217;<\/em> s\u0131n\u0131f\u0131ndan t\u00fcreyen ve &#8216;SendAsync&#8217; metodunu override eden a\u015fa\u011f\u0131daki nesne olu\u015fturulur.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    class AuthenticatedHttpClientHandler : HttpClientHandler\r\n    {\r\n        private readonly Func&lt;Task&lt;string&gt;&gt; getToken;\r\n        public AuthenticatedHttpClientHandler(Func&lt;Task&lt;string&gt;&gt; getToken)\r\n        {\r\n            if (getToken == null) throw new ArgumentNullException(nameof(getToken));\r\n            this.getToken = getToken;\r\n        }\r\n\r\n        async protected override Task&lt;HttpResponseMessage&gt; SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n        {\r\n            var auth = request.Headers.Authorization;\r\n            if (auth != null)\r\n            {\r\n                var token = await getToken().ConfigureAwait(false);\r\n                request.Headers.Authorization = new AuthenticationHeaderValue(auth.Scheme, token);\r\n            }\r\n            return await base.SendAsync(request, cancellationToken);\r\n        }\r\n    }\r\n<\/pre>\n<p>Yukar\u0131daki &#8216;<em>AuthenticatedHttpClientHandler<\/em>&#8216; s\u0131n\u0131f\u0131na g\u00f6z atarsak e\u011fer biraz \u00f6nce bahsedildi\u011fi gibi &#8216;HttpClientHandler&#8217; s\u0131n\u0131f\u0131ndan t\u00fcremekte ve &#8216;SendAsync&#8217; metodunu override etmektedir. Constructor&#8217;\u0131na bakarsan\u0131z e\u011fer &#8216;Func&lt;Task&lt;string&gt;&gt;&#8217; t\u00fcr\u00fcnden &#8216;getToken&#8217; isimli bir delegate almaktad\u0131r. Bu Func yap\u0131lanmas\u0131, ilgili s\u0131n\u0131ftan nesne \u00fcretilirken kendisine verilen metot i\u00e7erisinde server&#8217;dan token&#8217;\u0131 talep edecek ve geriye d\u00f6nd\u00fcrecektir. <em><strong>15.<\/strong><\/em> sat\u0131rda ilgili Func referans\u0131na verilen metot \u00e7a\u011fr\u0131larak token elde edilmekte ve <em><strong>16.<\/strong><\/em> sat\u0131rda request&#8217;in headerlar\u0131ndan Authorization&#8217;a yerle\u015ftirilmekte ve b\u00f6ylece request yenilenmi\u015f olmaktad\u0131r. Ard\u0131ndan ilgili request base class&#8217;ta ki &#8216;SendAsync&#8217; metoduna g\u00f6nderilmektedir.\n<\/li>\n<li><strong>Ad\u0131m 2<\/strong><br \/>\nRefit&#8217;in istekleri g\u00f6rselle\u015ftirebilmesi i\u00e7in aray\u00fcz tasarlanmal\u0131d\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos\/login&quot;)]\r\n        &#x5B;Headers(&quot;Authorization: Bearer&quot;)]\r\n        Task&lt;string&gt; Login();\r\n    }\r\n<\/pre>\n<\/li>\n<li><strong>Ad\u0131m 3<\/strong><br \/>\nArd\u0131ndan istek a\u015fa\u011f\u0131daki gibi tasarlan\u0131p, g\u00f6nderilmelidir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            var api = RestService.For&lt;ITodoAPI&gt;(new HttpClient(new AuthenticatedHttpClientHandler(() =&gt;\r\n            {\r\n                \/\/Sunucudan token talep edilebilir...\r\n                return Task.FromResult(&quot;elde edilen token degeri&quot;);\r\n            }))\r\n            {\r\n                BaseAddress = new Uri(&quot;https:\/\/localhost:5001&quot;)\r\n            });\r\n            await api.Login();\r\n<\/pre>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere &#8216;RestService.For&#8217; komutuyla iste\u011fin g\u00f6nderilebilmesi i\u00e7in bir &#8216;HttpClient&#8217; nesnesi kullan\u0131lmakta ve i\u00e7erisine olu\u015fturdu\u011fumuz &#8216;AuthenticatedHttpClientHandler&#8217; nesnesi verilmektedir. Bu nesnenin tasar\u0131m\u0131 icab\u0131 constructor&#8217;\u0131ndan istedi\u011fi Func de\u011ferine kar\u015f\u0131l\u0131k tan\u0131mlanan lambda fonksiyonu i\u00e7erisinde token talep edilmekte ve elde edildi\u011fi taktirde geriye d\u00f6nd\u00fcr\u00fclmektedir. Ayr\u0131ca &#8216;HttpClient&#8217; nesnesinin initializer&#8217;\u0131nda &#8216;BaseAddress&#8217; propertysine base url verilmektedir.\n<\/li>\n<\/ul>\n<h3 style=\"color:#e83e8c;\" id=\"baslik10\">Header&#8217;lar\u0131n Yeniden Tan\u0131mlanmas\u0131<\/h3>\n<p>A\u015fa\u011f\u0131daki \u00f6ncelik s\u0131ras\u0131na g\u00f6re header&#8217;lar yeniden tan\u0131mlan\u0131rlar.<\/p>\n<ul>\n<li><em>Interfaceler&#8217;de ki header tan\u0131mlamas\u0131(en d\u00fc\u015f\u00fck \u00f6ncelik),<\/em><\/li>\n<li><em>Metotlarda ki header tan\u0131mlamas\u0131,<\/em><\/li>\n<li><em>Parametrelerde ki header tan\u0131mlamas\u0131(en y\u00fcksek \u00f6ncelik)<\/em><\/li>\n<\/ul>\n<p>\u00d6rne\u011fin;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Headers(&quot;position:interface&quot;)]\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodos();\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        &#x5B;Headers(&quot;position:metot&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodos(int id);\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        &#x5B;Headers(&quot;position:metot&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodos(int id, int userId, &#x5B;Header(&quot;position&quot;)] string headerparam);\r\n    }\r\n<\/pre>\n<p>aray\u00fcz\u00fcn\u00fc ele al\u0131rsak e\u011fer a\u015fa\u011f\u0131daki gibi yap\u0131lan isteklerde s\u0131ras\u0131yla<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            ITodoAPI todoAPI = RestService.For&lt;ITodoAPI&gt;(&quot;http:\/\/jsonplaceholder.typicode.com&quot;);\r\n            await todoAPI.GetTodos();\r\n            await todoAPI.GetTodos(5);\r\n            await todoAPI.GetTodos(5, 2, &quot;parametre&quot;);\r\n<\/pre>\n<p>{[position, {interface}]}<br \/>\n{[position, {metot}]}<br \/>\n{[position, {parametre}]}<br \/>\nheaderlar\u0131n\u0131 alacakt\u0131r.<\/p>\n<blockquote><p>Header&#8217;lar\u0131n yeniden tan\u0131mlanma davran\u0131\u015f\u0131 sadece ayn\u0131 isimdeki headerlar i\u00e7in ge\u00e7erlidir.<\/p><\/blockquote>\n<h3 style=\"color:#e83e8c;\" id=\"baslik11\">Header&#8217;lar\u0131n Silinmesi<\/h3>\n<p>Tan\u0131mlanm\u0131\u015f herhangi bir header, bo\u015f de\u011fere sahip olacak \u015fekilde tekrardan tan\u0131mlanarak ezilebilir ve b\u00f6ylece temizlenebilir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Headers(&quot;position:interface&quot;)]\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        &#x5B;Headers(&quot;position&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodos();\r\n    }\r\n<\/pre>\n<p>Ayr\u0131ca a\u015fa\u011f\u0131daki gibi bir tan\u0131mlama yap\u0131larak da header&#8217;a silinmeksizin empty de\u011fer at\u0131l\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Headers(&quot;position:interface&quot;)]\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        &#x5B;Headers(&quot;position:&quot;)]\r\n        Task&lt;List&lt;Todo&gt;&gt; GetTodos();\r\n    }\r\n<\/pre>\n<h3 style=\"color:#e83e8c;\" id=\"baslik12\">Asp.NET Core Uygulamalar\u0131nda Refit Kullan\u0131m\u0131<\/h3>\n<p>Bir Asp.NET Core uygulamas\u0131nda Refit&#8217;i kullanabilmek i\u00e7in \u00f6ncelikle projeye <a href=\"https:\/\/www.nuget.org\/packages\/refit\/\" rel=\"noopener noreferrer\" target=\"_blank\">Refit<\/a> k\u00fct\u00fcphanesiyle birlikte <a href=\"https:\/\/www.nuget.org\/packages\/Refit.HttpClientFactory\/\" rel=\"noopener noreferrer\" target=\"_blank\">Refit.HttpClientFactory<\/a> k\u00fct\u00fcphanesinin y\u00fcklenmesi gerekmektedir.<\/p>\n<p>Ard\u0131ndan &#8216;Startup.cs&#8217; dosyas\u0131ndaki &#8216;ConfigureServices&#8217; metodu i\u00e7erisinde a\u015fa\u011f\u0131daki gibi &#8216;AddRefitClient&#8217; servisinin eklenmesi gerekmektedir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITodoAPI\r\n    {\r\n        &#x5B;Get(&quot;\/todos&quot;)]\r\n        public Task&lt;List&lt;Todo&gt;&gt; GetTodos();\r\n    }\r\n<\/pre>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            services.AddRefitClient&lt;ITodoAPI&gt;()\r\n                .ConfigureHttpClient(c =&gt; c.BaseAddress = new Uri(&quot;http:\/\/jsonplaceholder.typicode.com&quot;));\r\n            services.AddControllers();\r\n        }\r\n<\/pre>\n<p>Tabi istek do\u011frultusunda bir &#8216;RefitSettings&#8217; objeside eklenebilmektedir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            services.AddRefitClient&lt;ITodoAPI&gt;(new RefitSettings { CollectionFormat = CollectionFormat.Csv })\r\n                .ConfigureHttpClient(c =&gt; c.BaseAddress = new Uri(&quot;http:\/\/jsonplaceholder.typicode.com&quot;));\r\n            services.AddControllers();\r\n        }\r\n<\/pre>\n<p>T\u00fcm bu d\u00fczenlemeler neticesinde tasarlanan Refit aray\u00fcz\u00fc a\u015fa\u011f\u0131daki gibi dependency injection&#8217;dan talep edilerek, kullan\u0131labilir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Route(&quot;api\/&#x5B;controller]&quot;)]\r\n    &#x5B;ApiController]\r\n    public class TodosController : ControllerBase\r\n    {\r\n        readonly ITodoAPI _todoAPI;\r\n        public TodosController(ITodoAPI todoAPI)\r\n        {\r\n            _todoAPI = todoAPI;\r\n        }\r\n\r\n        public async Task&lt;IActionResult&gt; GetTodos()\r\n        {\r\n            return Ok(await _todoAPI.GetTodos());\r\n        }\r\n    }\r\n<\/pre>\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<!-- 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, uygulamalar\u0131m\u0131zda HttpClient yerine basit interface tan\u0131mlamalar\u0131 sayesinde Rest API&#8217;lar ile kolay ve h\u0131zl\u0131 bir \u015fekilde i\u015flemler yapmam\u0131z\u0131 sa\u011flayan olduk\u00e7a g\u00fc\u00e7l\u00fc Refit k\u00fct\u00fcphanesi \u00fczerine konu\u015fuyor olaca\u011f\u0131z. Makalemizde i\u00e7eriksel ak\u0131\u015f olarak Console Application&#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":16681,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2739,3102,12,3573],"tags":[3601,3603,3602,3599,3600,3598],"class_list":["post-16618","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net-core","category-asp-net-core","category-c-sharp-c","category-microservices","tag-net-core-refit","tag-asp-net-core-refit","tag-httpclienthandler","tag-refit","tag-refit-framework","tag-refit-kutuphanesi"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/16618","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=16618"}],"version-history":[{"count":69,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/16618\/revisions"}],"predecessor-version":[{"id":16694,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/16618\/revisions\/16694"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/16681"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=16618"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=16618"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=16618"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}