Web API'si uygulaması
Dikkatlice tasarlanmış bir RESTful web API'si, istemci uygulamaları tarafından erişilebilen kaynakları, ilişkileri ve gezinti düzenlerini tanımlar. Bir web API’sini uygulayıp dağıttığınızda, verilerin mantıksal yapısı yerine web API’sini barındıran ortamın fiziksel gereksinimlerini ve web API'sinin hangi şekilde oluşturulduğunu göz önünde bulundurmanız gerekir. Bu kılavuz, bir web API'sini uygulamaya ve istemci uygulamalarının kullanımına açmak için yayımlamaya yönelik en iyi yöntemlere odaklanır. Web API'si tasarımı hakkında ayrıntılı bilgi için bkz . Web API'si tasarımı.
İstekleri işleme
İstekleri işlemek üzere kod uygularken aşağıdaki noktaları göz önünde bulundurun.
GET, PUT, DELETE, HEAD ve PATCH eylemleri bir kez etkili olmalıdır
Bu istekleri uygulayan kod herhangi yan etki oluşturmamalıdır. Aynı kaynak üzerinde yinelenen aynı istek, aynı durumla sonuçlanmalıdır. Örneğin, yanıt iletilerindeki HTTP durum kodu farklı olsa da, aynı URI'ye birden çok DELETE isteği göndermek aynı etkiye sahip olmalıdır. İlk DELETE isteği 204 (İçerik Yok) durum kodunu, sonraki bir DELETE isteği ise 404 (Bulunamadı) durum kodunu döndürebilir.
Not
Jonathan Oliver'ın blogundaki Idempotency Patterns (Tek Etkililik Desenleri) makalesi, tek etkililiğe ve bunun veri yönetimi işlemleriyle ilişkisine genel bir bakış sağlar.
Yeni kaynaklar oluşturan POST eylemlerinin ilişkisiz yan etkileri olmamalıdır
POST isteğinin yeni bir kaynak oluşturması amaçlanıyorsa, isteğin etkileri yeni kaynakla (ve bir tür bağlantı söz konusuysa muhtemelen doğrudan ilgili tüm kaynaklarda) sınırlandırılmalıdır. Örneğin, bir e-ticaret sisteminde, müşteri için yeni bir sipariş oluşturan bir POST isteği de envanter düzeylerini değiştirebilir ve fatura bilgileri oluşturabilir, ancak siparişle doğrudan ilgili olmayan bilgileri değiştirmemeli veya sistemin genel durumu üzerinde başka bir yan etkisi olmamalıdır.
Sık iletişim kuran POST, PUT ve DELETE işlemlerini uygulamaktan kaçının
API'nizi geveveleme işlemlerine göre tasarlamaktan kaçının. Her istek protokol, ağ ve işlem yüküyle birlikte gelir. Örneğin, daha büyük bir toplu iş isteği yerine 100 daha küçük istek yürütmek, istemcide, ağda ve kaynak sunucusunda ek yüke neden olur. Mümkün olduğunda, yalnızca tek tek kaynaklar yerine kaynak koleksiyonları için HTTP fiili desteği sağlayın.
- Bir koleksiyona get isteği aynı anda birden çok kaynak alabilir.
- POST isteği birden çok yeni kaynağın ayrıntılarını içerebilir ve bunların tümünü aynı koleksiyona ekleyebilir.
- PUT isteği, bir koleksiyondaki tüm kaynak kümesinin yerini alabilir.
- DELETE isteği koleksiyonun tamamını kaldırabilir.
ASP.NET Web API 2'de bulunan Açık Veri Protokolü (OData) desteği, istekleri toplu olarak oluşturma olanağı sağlar. bir istemci uygulaması birkaç web API'si isteği paketleyebilir ve bunları tek bir HTTP isteğinde sunucuya gönderebilir ve her isteğin yanıtlarını içeren tek bir HTTP yanıtı alabilir. Daha fazla bilgi için bkz . Web API'sinde Batch'i Etkinleştirme OData Hizmeti.
Yanıt gönderirken HTTP belirtimini takip edin
Bir web API’si, istemcinin sonucu nasıl işleyeceğini belirlemesi için doğru HTTP durum kodunu, istemcinin sonucun niteliğini anlayabilmesi için uygun HTTP üst bilgilerini ve istemcinin sonucu ayrıştırması için uygun şekilde biçimlendirilmiş bir gövdeyi içeren iletiler döndürmelidir.
Örneğin, bir POST işlemi 201 (Oluşturuldu) durum kodunu döndürmeli ve yanıt iletisi, yanıt iletisinin Konum üst bilgisinde yeni oluşturulan kaynağa ait URI’yi içermelidir.
İçerik anlaşmasını destekler
Bir yanıt iletisinin gövdesi, çeşitli biçimlerde veriler içerebilir. Örneğin, bir HTTP GET isteği JSON veya XML biçiminde veri döndürebilir. İstemciler bir istek gönderdiğinde, işleyebileceği veri biçimlerini belirten bir Accept üst bilgisi içerebilir. Bu biçimler medya türleri olarak belirtilir. Örneğin, bir görüntüyü alan bir GET isteği veren bir istemci, istemcinin işleyebileceği medya türlerini listeleyen accept üst bilgisini (gibi) image/jpeg, image/gif, image/png
belirtebilir. Web API'si sonucu döndürdüğünde bu medya türlerinden birini kullanarak verileri biçimlendirmeli ve biçimi yanıtın Content-Type üst bilgisinde belirtmelidir.
İstemci bir Accept üst bilgisi belirtmezse, yanıt gövdesi için duyarlı bir varsayılan biçim kullanın. Örnek olarak ASP.NET Web API çerçevesi, metin tabanlı veriler için varsayılan olarak JSON biçimindedir.
HATEOAS stili gezintiyi ve kaynakların bulunmasını desteklemek için bağlantılar sağlar
HATEOAS yaklaşımı, istemcinin bir başlangıç noktasından itibaren gezinip kaynakları bulmasını sağlar. Bu işlem, URI'ler içeren bağlantılar kullanılarak yapılır; istemci bir kaynağı almak için HTTP GET isteği gönderdiğinde, yanıt bir istemci uygulamanın dolaylı olarak ilgili tüm kaynakları hızlıca bulmasını sağlayan URI’ler içermelidir. Örneğin, e-ticaret çözümünü destekleyen bir web API’de müşteri çok sayıda sipariş vermiş olabilir. Bir istemci uygulama bir müşterinin ayrıntılarını aldığında yanıt, istemci uygulamanın bu siparişleri alabilmesi için HTTP GET istekleri göndermesini sağlayan bağlantılar içermelidir. Ayrıca, HATEOAS stili bağlantılar her bağlantılı kaynağın her bir isteği gerçekleştirmek üzere karşılık gelen URI ile birlikte desteklediği diğer işlemleri (POST, PUT, DELETE vb.) açıklamalıdır. Bu yaklaşım API tasarımında daha ayrıntılı olarak açıklanmıştır.
Şu anda HATEOAS uygulamasını yöneten bir standart bulunmamasına karşın aşağıdaki örnekte olası bir yaklaşım gösterilmektedir. Bu örnekte, müşterinin ayrıntılarını bulan bir HTTP GET isteği, söz konusu müşterinin siparişlerine başvuran HATEOAS bağlantılarını içeren bir yanıt döndürür:
GET https://adventure-works.com/customers/2 HTTP/1.1
Accept: text/json
...
HTTP/1.1 200 OK
...
Content-Type: application/json; charset=utf-8
...
Content-Length: ...
{"CustomerID":2,"CustomerName":"Bert","Links":[
{"rel":"self",
"href":"https://adventure-works.com/customers/2",
"action":"GET",
"types":["text/xml","application/json"]},
{"rel":"self",
"href":"https://adventure-works.com/customers/2",
"action":"PUT",
"types":["application/x-www-form-urlencoded"]},
{"rel":"self",
"href":"https://adventure-works.com/customers/2",
"action":"DELETE",
"types":[]},
{"rel":"orders",
"href":"https://adventure-works.com/customers/2/orders",
"action":"GET",
"types":["text/xml","application/json"]},
{"rel":"orders",
"href":"https://adventure-works.com/customers/2/orders",
"action":"POST",
"types":["application/x-www-form-urlencoded"]}
]}
Bu örnekte müşteri verilerini, aşağıdaki kod parçacığında gösterilen Customer
sınıfı temsil eder. HATEOAS bağlantıları Links
koleksiyon özelliğinde tutulur:
public class Customer
{
public int CustomerID { get; set; }
public string CustomerName { get; set; }
public List<Link> Links { get; set; }
...
}
public class Link
{
public string Rel { get; set; }
public string Href { get; set; }
public string Action { get; set; }
public string [] Types { get; set; }
}
HTTP GET işlemi, depolama alanından müşteri verilerini alıp bir Customer
nesnesi oluşturur ve sonra Links
koleksiyonunu doldurur. Sonuç bir JSON yanıt iletisi olarak biçimlendirilir. Her bağlantı aşağıdaki alanları içerir:
- Döndürülen nesne ile bağlantı tarafından açıklanan nesne arasındaki ilişki (
Rel
). Bu durumdaself
, bağlantının nesnenin kendisine bir başvuru olduğunu (nesne odaklı birçok dildeki işaretçiyethis
benzer) veorders
ilgili sipariş bilgilerini içeren bir koleksiyonun adı olduğunu gösterir. - Bağlantı tarafından tanımlanan nesnenin URI biçimindeki köprü bağlantısı (
Href
). - Bu URI’ya gönderilebilen HTTP isteğinin türü (
Action
). - İstek türüne bağlı olarak, HTTP isteğinde belirtilmesi gereken veya yanıtta döndürülebilecek her türlü verinin biçimi (
Types
).
Örnek HTTP yanıtında gösterilen HATEOAS bağlantıları, bir istemci uygulamanın aşağıdaki işlemleri gerçekleştirebileceğini ifade eder:
- Müşterinin ayrıntılarını getirmek için (tekrar)
https://adventure-works.com/customers/2
URI’ya gönderilen HTTP GET isteği. Veriler, XML veya JSON olarak döndürülebilir. - Müşterinin ayrıntılarını değiştirmek için
https://adventure-works.com/customers/2
URI’ya gönderilen HTTP PUT isteği. Yeni veriler, yanıt iletisinde x-www-form-urlencoded biçiminde belirtilmelidir. - Müşteri silmek için
https://adventure-works.com/customers/2
URI’ya gönderilen HTTP DELETE isteği. İstek başka bir ek bilgi beklemez veya yanıt iletisi gövdesinde veri döndürmez. - Müşteriye ait tüm siparişleri bulmak için
https://adventure-works.com/customers/2/orders
URI’ya gönderilen HTTP GET isteği. Veriler, XML veya JSON olarak döndürülebilir. - Bu müşteri için yeni bir sipariş oluşturmak için URI'ye
https://adventure-works.com/customers/2/orders
bir HTTP POST isteği. Veriler, yanıt iletisinde x-www-form-urlencoded biçiminde belirtilmelidir.
Özel durum işleme
Bir işlem yakalanmayan bir özel durum oluşturursa aşağıdaki noktaları göz önünde bulundurun.
Özel durumları yakalama ve istemcilere anlamlı bir yanıt döndürme
Bir HTTP işlemi uygulayan kod, yakalanmayan özel durumların çerçeveye yayılmasına izin vermek yerine kapsamlı özel durum işleme sağlamalıdır. Bir özel durum nedeniyle işlemi tamamlamak mümkün değilse, özel durum yanıt iletisine geri gönderilebilir ancak özel durum nedeninin anlamlı bir açıklamasını içermelidir. Ayrıca özel durum, her durum için yalnızca 500 durum kodunu döndürmek yerine uygun HTTP durum kodunu da içermelidir. Örneğin, bir kullanıcı isteği sonucunda kısıtlamayı ihlal eden bir veritabanı güncelleştirmesi yapılırsa (bekleyen siparişleri olan bir müşteriyi silmeye çalışmak gibi), 409 (Çakışma) durum kodunu ve çakışma nedenini belirten bir ileti gövdesini döndürmeniz gerekir. Başka bir koşul isteği gerçekleştirilemez hale getirirse, 400 (Hatalı İstek) durum kodunu döndürebilirsiniz. HTTP durum kodlarının tam listesini W3C web sitesindeki Durum kodu tanımları sayfasında bulabilirsiniz.
Kod örneği farklı koşulları yakalar ve uygun bir yanıt döndürür.
[HttpDelete]
[Route("customers/{id:int}")]
public IHttpActionResult DeleteCustomer(int id)
{
try
{
// Find the customer to be deleted in the repository
var customerToDelete = repository.GetCustomer(id);
// If there is no such customer, return an error response
// with status code 404 (Not Found)
if (customerToDelete == null)
{
return NotFound();
}
// Remove the customer from the repository
// The DeleteCustomer method returns true if the customer
// was successfully deleted
if (repository.DeleteCustomer(id))
{
// Return a response message with status code 204 (No Content)
// To indicate that the operation was successful
return StatusCode(HttpStatusCode.NoContent);
}
else
{
// Otherwise return a 400 (Bad Request) error response
return BadRequest(Strings.CustomerNotDeleted);
}
}
catch
{
// If an uncaught exception occurs, return an error response
// with status code 500 (Internal Server Error)
return InternalServerError();
}
}
İpucu
API'nize sızmaya çalışan bir saldırgan için yararlı olabilecek bilgiler eklemeyin.
Birçok web sunucusu, web API’sine ulaşmadan önce hata koşullarını kendi başına yakalar. Örneğin, bir web sitesi için kimlik doğrulamasını yapılandırırsanız ve kullanıcı doğru kimlik doğrulama bilgilerini sağlayamazsa, web sunucusunun 401 (Yetkisiz) durum koduyla yanıt vermesi gerekir. Bir istemcinin kimliği doğrulandıktan sonra kodunuz, istemcinin istenen kaynağa erişebildiğini doğrulamak üzere kendi denetimlerini gerçekleştirebilir. Bu yetkilendirme başarısız olursa, 403 (Yasak) durum kodunu döndürmeniz gerekir.
Özel durumları tutarlı bir şekilde işleme ve hata bilgilerini günlüğe kaydetme
Özel durumları tutarlı bir şekilde işlemek için web API'sinin tamamında genel bir hata işleme stratejisi uygulayın. Ayrıca, her bir özel durumun tam ayrıntılarını yakalayan hata günlüğünü eklemeniz gerekir; bu hata günlüğü, web üzerinden istemcilerin erişimine açılmadığı sürece ayrıntılı bilgiler içerebilir.
İstemci tarafı hataları ile sunucu tarafı hatalarını birbirinden ayırt etme
HTTP protokolü, istemci uygulamadan kaynaklanan hataları (HTTP 4xx durum kodları) sunucu üzerindeki bir sorundan kaynaklanan hatalardan (HTTP 5xx durum kodları) ayırt eder. Tüm hata yanıt iletilerinde bu kurala uyduğunuzdan emin olun.
İstemci tarafı veri erişimini en iyi duruma getirme
Web sunucusu ile istemci uygulamalar içerenler gibi dağıtılmış bir ortamda en önemli kaynaklardan birisi ağdır. Özellikle bir istemci uygulama sıklıkla istek gönderiyor veya veri alıyorsa bu durum önemli bir performans sorunu oluşturabilir. Bu nedenle, ağ üzerinden akan trafiği en aza indirmeyi amaçlamanız gerekir. Veri alıp sürdürmek üzere kod uygularken aşağıdaki noktaları göz önünde bulundurun:
İstemci tarafı önbelleğe alma desteği
HTTP 1.1 protokolü, istemcilerde ve Cache-Control üst bilgisi kullanılarak bir isteğin yönlendirildiği ara sunucularda önbelleğe almayı destekler. Bir istemci uygulama tarafından web API’sine HTTP GET isteği gönderildiğinde yanıt, yanıt gövdesindeki verilerin istemci tarafından veya isteğin yönlendirildiği bir ara sunucu tarafından güvenli bir şekilde önbelleğe alınıp alınamayacağını ve süresi dolmadan ve eski kabul edilmeden önce ne kadar süre kaldığını gösteren bir Cache-Control üst bilgisi içerebilir.
Aşağıdaki örnekte bir HTTP GET isteği ve Cache-Control üst bilgisi içeren ilgili yanıt gösterilmektedir:
GET https://adventure-works.com/orders/2 HTTP/1.1
HTTP/1.1 200 OK
...
Cache-Control: max-age=600, private
Content-Type: text/json; charset=utf-8
Content-Length: ...
{"orderID":2,"productID":4,"quantity":2,"orderValue":10.00}
Bu örnekte Cache-Control üst bilgisi, döndürülen verilerin süresinin 600 saniye sonra dolması gerektiğini ve yalnızca tek bir istemci için uygun olup diğer istemciler tarafından kullanılan ortak bir önbellekte depolanmaması gerektiğini (private olduğunu) belirtir. Cache-Control üst bilgisinin private yerine public seçeneğini belirttiğinde veriler ortak bir önbellekte depolanabilir veya no-store seçeneğini belirttiğinde verilerin istemci tarafından önbelleğe alınmaması gerekir. Aşağıdaki kod örneğinde, bir yanıt iletisinde Cache-Control üst bilgisinin nasıl oluşturulacağı gösterilmektedir:
public class OrdersController : ApiController
{
...
[Route("api/orders/{id:int:min(0)}")]
[HttpGet]
public IHttpActionResult FindOrderByID(int id)
{
// Find the matching order
Order order = ...;
...
// Create a Cache-Control header for the response
var cacheControlHeader = new CacheControlHeaderValue();
cacheControlHeader.Private = true;
cacheControlHeader.MaxAge = new TimeSpan(0, 10, 0);
...
// Return a response message containing the order and the cache control header
OkResultWithCaching<Order> response = new OkResultWithCaching<Order>(order, this)
{
CacheControlHeader = cacheControlHeader
};
return response;
}
...
}
Bu kod adlı OkResultWithCaching
özel IHttpActionResult
bir sınıf kullanır. Bu sınıf, denetleyicinin önbellek üst bilgisi içeriklerini ayarlamasını sağlar:
public class OkResultWithCaching<T> : OkNegotiatedContentResult<T>
{
public OkResultWithCaching(T content, ApiController controller)
: base(content, controller) { }
public OkResultWithCaching(T content, IContentNegotiator contentNegotiator, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
: base(content, contentNegotiator, request, formatters) { }
public CacheControlHeaderValue CacheControlHeader { get; set; }
public EntityTagHeaderValue ETag { get; set; }
public override async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response;
try
{
response = await base.ExecuteAsync(cancellationToken);
response.Headers.CacheControl = this.CacheControlHeader;
response.Headers.ETag = ETag;
}
catch (OperationCanceledException)
{
response = new HttpResponseMessage(HttpStatusCode.Conflict) {ReasonPhrase = "Operation was cancelled"};
}
return response;
}
}
Not
HTTP protokolü ayrıca Cache-Control üst bilgisi için no-cache yönergesini tanımlar. Kafa karıştırıcı bir şekilde, bu yönerge "önbelleğe almama" yerine "önbelleğe alınan bilgileri döndürmeden önce sunucu ile yeniden doğrulama" anlamına gelir; veriler yine de önbelleğe alınabilir ancak her kullanıldığında hala güncel olup olmadığı denetlenir.
Önbellek yönetimi, istemci uygulamasının veya ara sunucunun sorumluluğundadır; ancak doğru şekilde uygulanırsa, yakın zamanda zaten alınmış verileri getirme gereksinimini ortadan kaldırarak bant genişliği kazandırabilir ve performansı artırabilir.
Cache-Control üst bilgisindeki max-age değeri yalnızca kılavuz niteliğindedir ve belirtilen süre boyunca ilgili verilerin değişmeyeceğini garanti etmez. Web API’si, verilerin beklenen geçiciliğine bağlı olarak max-age parametresini uygun bir değere ayarlamalıdır. Bu süre sona erdiğinde istemci, nesneyi önbellekten atmalıdır.
Not
Birçok modern web tarayıcısı, isteklere uygun cache-control üst bilgilerini ekleyerek ve sonuçların üst bilgilerini anlatılan şekilde inceleyerek istemci tarafı önbelleğe alma özelliğini destekler. Ancak, bazı eski tarayıcılar sorgu dizesi içeren bir URL’den döndürülen değerleri önbelleğe almaz. Bu sorun genellikle burada tartışılan protokolü temel alarak kendi önbellek yönetim stratejisini uygulayan özel istemci uygulamaları için geçerli değildir.
Bazı eski proxy'ler aynı davranışı sergiler ve sorgu dizeleriyle URL’lere göre istekleri önbelleğe almayabilir. Bu sorun, bu tür bir proxy üzerinden bir web sunucusuna bağlanan özel istemci uygulamaları için geçerli olabilir.
Sorgu işlemeyi iyileştirmek için Etag'ler sağlama
İstemci uygulaması bir nesne aldığında, yanıt iletisi bir varlık etiketi (ETag) de içerebilir. ETag, kaynağın sürümünü gösteren opak bir dizedir; Bir kaynak her değiştiğinde ETag de değiştirilir. Bu ETag, istemci uygulama tarafından verilerin bir parçası olarak önbelleğe alınmalıdır. Aşağıdaki kod örneğinde bir HTTP GET isteğine yanıtın parçası olarak ETag ekleme işlemi gösterilmektedir. Bu kod, nesneyi tanımlayan sayısal bir değer oluşturmak üzere bir nesnenin GetHashCode
yöntemini kullanır (gerekirse bu yöntemi geçersiz kılabilir ve MD5 gibi bir algoritma kullanarak kendi karmanızı oluşturabilirsiniz):
public class OrdersController : ApiController
{
...
public IHttpActionResult FindOrderByID(int id)
{
// Find the matching order
Order order = ...;
...
var hashedOrder = order.GetHashCode();
string hashedOrderEtag = $"\"{hashedOrder}\"";
var eTag = new EntityTagHeaderValue(hashedOrderEtag);
// Return a response message containing the order and the cache control header
OkResultWithCaching<Order> response = new OkResultWithCaching<Order>(order, this)
{
...,
ETag = eTag
};
return response;
}
...
}
Web API’si tarafından gönderilen yanıt iletisi şuna benzer:
HTTP/1.1 200 OK
...
Cache-Control: max-age=600, private
Content-Type: text/json; charset=utf-8
ETag: "2147483648"
Content-Length: ...
{"orderID":2,"productID":4,"quantity":2,"orderValue":10.00}
İpucu
Güvenlik nedeniyle, kimliği doğrulanmış (HTTPS) bağlantı üzerinden döndürülen hassas verilerin veya verilerin önbelleğe alınmasına izin verme.
Bir istemci uygulama herhangi bir zamanda aynı kaynağı almak için sonraki bir GET isteği düzenleyebilir ve kaynak değiştiyse (farklı ETag’e sahipse), önbelleğe alınan sürüm atılmalı ve yeni sürüm önbelleğe eklenmelidir. Bir kaynak büyükse ve istemciye geri iletmek için önemli miktarda bant genişliği gerektiriyorsa, aynı verileri getirmek için tekrarlanan istekleri verimsiz olabilir. Bu sorunla başa çıkmak için HTTP protokolü bir web API’sinde desteklemeniz gereken GET isteklerini iyileştirmeye yönelik aşağıdaki işlemi tanımlar:
İstemci, bir If-None-Match HTTP üst bilgisinde başvurulan kaynağın o anda önbelleğe alınan sürümü için ETag içeren bir GET isteği oluşturur:
GET https://adventure-works.com/orders/2 HTTP/1.1 If-None-Match: "2147483648"
Web API’sindeki GET işlemi, istenen veriler için geçerli ETag’i alır (yukarıdaki örnekte sipariş 2) ve If-None-Match üst bilgisindeki değerle karşılaştırır.
İstenen veriler için geçerli ETag, istek tarafından sağlanan ETag ile eşleşiyorsa kaynak değişmemiştir ve web API’si boş bir ileti ve 304 (Değiştirilmedi) durum kodu ile bir HTTP yanıtı döndürmelidir.
İstenen veriler için geçerli ETag, istek tarafından sağlanan ETag ile eşleşmiyorsa veriler değişmiştir ve web API’si, ileti gövdesinde yeni verilerle birlikte bir HTTP yanıtı ve 200 (Tamam) durum kodu döndürmelidir.
İstenen veriler artık mevcut değilse web API'si, 404 (Bulunamadı) durum kodu ile bir HTTP yanıtı döndürmelidir.
İstemci, önbelleği korumak için durum kodunu kullanır. Veriler değişmemişse (304 durum kodu), nesne önbelleğe alınmış olarak kalır ve istemci uygulama nesnenin bu sürümünü kullanmaya devam etmelidir. Veriler değişmişse (200 durum kodu), önbelleğe alınmış nesne atılmalı ve yeni bir nesne eklenmelidir. Veriler artık mevcut değilse (404 durum kodu) nesne önbellekten kaldırılmalıdır.
Not
Yanıt üst bilgisi Cache-Control üst bilgisi no-store değerini içeriyorsa, HTTP durum koduna bakılmaksızın nesne her zaman önbellekten kaldırılmalıdır.
Aşağıdaki kod, FindOrderByID
If-None-Match üst bilgisini destekleyecek şekilde genişletilmiş yöntemini gösterir. If-None-Match üst bilgisi çıkarılırsa belirtilen sıranın her zaman alındığına dikkat edin:
public class OrdersController : ApiController
{
[Route("api/orders/{id:int:min(0)}")]
[HttpGet]
public IHttpActionResult FindOrderByID(int id)
{
try
{
// Find the matching order
Order order = ...;
// If there is no such order then return NotFound
if (order == null)
{
return NotFound();
}
// Generate the ETag for the order
var hashedOrder = order.GetHashCode();
string hashedOrderEtag = $"\"{hashedOrder}\"";
// Create the Cache-Control and ETag headers for the response
IHttpActionResult response;
var cacheControlHeader = new CacheControlHeaderValue();
cacheControlHeader.Public = true;
cacheControlHeader.MaxAge = new TimeSpan(0, 10, 0);
var eTag = new EntityTagHeaderValue(hashedOrderEtag);
// Retrieve the If-None-Match header from the request (if it exists)
var nonMatchEtags = Request.Headers.IfNoneMatch;
// If there is an ETag in the If-None-Match header and
// this ETag matches that of the order just retrieved,
// then create a Not Modified response message
if (nonMatchEtags.Count > 0 &&
String.CompareOrdinal(nonMatchEtags.First().Tag, hashedOrderEtag) == 0)
{
response = new EmptyResultWithCaching()
{
StatusCode = HttpStatusCode.NotModified,
CacheControlHeader = cacheControlHeader,
ETag = eTag
};
}
// Otherwise create a response message that contains the order details
else
{
response = new OkResultWithCaching<Order>(order, this)
{
CacheControlHeader = cacheControlHeader,
ETag = eTag
};
}
return response;
}
catch
{
return InternalServerError();
}
}
...
}
Bu örnek EmptyResultWithCaching
adlı ek bir özel IHttpActionResult
sınıfını içerir. Bu sınıf, yanıt gövdesi içermeyen bir HttpResponseMessage
nesnesinin çevresinde sarmalayıcı olarak görev yapar:
public class EmptyResultWithCaching : IHttpActionResult
{
public CacheControlHeaderValue CacheControlHeader { get; set; }
public EntityTagHeaderValue ETag { get; set; }
public HttpStatusCode StatusCode { get; set; }
public Uri Location { get; set; }
public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response = new HttpResponseMessage(StatusCode);
response.Headers.CacheControl = this.CacheControlHeader;
response.Headers.ETag = this.ETag;
response.Headers.Location = this.Location;
return response;
}
}
İpucu
Bu örnekte veriler için ETag değeri, temel alınan veri kaynağından alınan verilerin karması oluşturularak üretilir. ETag başka bir şekilde hesaplanabiliyorsa, işlem daha fazla iyileştirilebilir ve verilerin yalnızca değişmişse veri kaynağından getirilmesi gerekir. Bu yaklaşım özellikle veriler büyükse veya veri kaynağına erişim önemli bir gecikme süresine neden oluyorsa (örneğin, veri kaynağı bir uzak veritabanı ise) yararlıdır.
İyimser Eşzamanlılığı Desteklemek için ETag’ler Kullanma
HTTP protokolü daha önce önbelleğe alınmış verileri etkinleştirmek için bir iyimser eşzamanlılık stratejisini destekler. Bir kaynağı getirip önbelleğe aldıktan sonra istemci uygulaması kaynağı değiştirmek veya kaldırmak için bir PUT veya DELETE isteği gönderirse, ETag'e başvuran bir If-Match üst bilgisi içermelidir. Web API’si daha sonra bu bilgileri kullanarak kaynağın alındıktan sonra başka bir kullanıcı tarafından değiştirilip değiştirilmediğini belirleyebilir ve istemci uygulamaya aşağıdaki gibi uygun bir yanıt gönderebilir:
İstemci, bir If-Match HTTP üst bilgisinde başvurulan kaynağın o anda önbelleğe alınan sürümü için kaynağın yeni ayrıntılarını ve ETag içeren bir PUT isteği oluşturur. Aşağıdaki örnekte bir siparişi güncelleştiren PUT isteği gösterilmektedir:
PUT https://adventure-works.com/orders/1 HTTP/1.1 If-Match: "2282343857" Content-Type: application/x-www-form-urlencoded Content-Length: ... productID=3&quantity=5&orderValue=250
Web API’sindeki PUT işlemi, istenen veriler için geçerli ETag’i alır (yukarıdaki örnekte sipariş 1) ve If-Match üst bilgisindeki değerle karşılaştırır.
İstenen veriler için geçerli ETag, istek tarafından sağlanan ETag ile eşleşiyorsa kaynak değişmemiştir ve web API’si 204 (İçerik Yok) HTTP durum kodu ile bir ileti döndürerek güncelleştirmeyi gerçekleştirmelidir. Yanıt, kaynağın güncelleştirilmiş sürümü için Cache-Control ve ETag üst bilgilerini içerebilir. Yanıt her zaman yeni güncelleştirilmiş kaynağın URI'sine başvuran Location üst bilgisini içermelidir.
İstenen veriler için geçerli ETag, istek tarafından sağlanan ETag ile eşleşmiyorsa veriler getirildikten sonra başka bir kullanıcı tarafından değiştirilmiştir ve web API’si, boş bir ileti gövdesi ile bir HTTP yanıtı ve 412 (Önkoşul Başarısız) durum kodu döndürmelidir.
Güncelleştirilecek kaynak artık mevcut değilse web API'si, 404 (Bulunamadı) durum kodu ile bir HTTP yanıtı döndürmelidir.
İstemci, önbelleği korumak için durum kodunu ve yanıt üst bilgilerini kullanır. Veriler güncelleştirilmişse (204 durum kodu), nesne önbelleğe alınmış olarak kalır (Cache-Control üstbilgisi no-store değerini belirtmediği sürece) ancak ETag değerinin güncelleştirilmesi gerekir. Veriler başka bir kullanıcı tarafından değiştirildiyse (durum kodu 412) veya bulunamazsa (durum kodu 404) önbelleğe alınan nesne atılmalıdır.
Sonraki kod örneğinde Orders denetleyicisinin PUT işlemine ait uygulama gösterilmektedir:
public class OrdersController : ApiController
{
[HttpPut]
[Route("api/orders/{id:int}")]
public IHttpActionResult UpdateExistingOrder(int id, DTOOrder order)
{
try
{
var baseUri = Constants.GetUriFromConfig();
var orderToUpdate = this.ordersRepository.GetOrder(id);
if (orderToUpdate == null)
{
return NotFound();
}
var hashedOrder = orderToUpdate.GetHashCode();
string hashedOrderEtag = $"\"{hashedOrder}\"";
// Retrieve the If-Match header from the request (if it exists)
var matchEtags = Request.Headers.IfMatch;
// If there is an ETag in the If-Match header and
// this ETag matches that of the order just retrieved,
// or if there is no ETag, then update the Order
if (((matchEtags.Count > 0 &&
String.CompareOrdinal(matchEtags.First().Tag, hashedOrderEtag) == 0)) ||
matchEtags.Count == 0)
{
// Modify the order
orderToUpdate.OrderValue = order.OrderValue;
orderToUpdate.ProductID = order.ProductID;
orderToUpdate.Quantity = order.Quantity;
// Save the order back to the data store
// ...
// Create the No Content response with Cache-Control, ETag, and Location headers
var cacheControlHeader = new CacheControlHeaderValue();
cacheControlHeader.Private = true;
cacheControlHeader.MaxAge = new TimeSpan(0, 10, 0);
hashedOrder = order.GetHashCode();
hashedOrderEtag = $"\"{hashedOrder}\"";
var eTag = new EntityTagHeaderValue(hashedOrderEtag);
var location = new Uri($"{baseUri}/{Constants.ORDERS}/{id}");
var response = new EmptyResultWithCaching()
{
StatusCode = HttpStatusCode.NoContent,
CacheControlHeader = cacheControlHeader,
ETag = eTag,
Location = location
};
return response;
}
// Otherwise return a Precondition Failed response
return StatusCode(HttpStatusCode.PreconditionFailed);
}
catch
{
return InternalServerError();
}
}
...
}
İpucu
If-Match üst bilgisinin kullanılması tamamen isteğe bağlı ise ve kullanılmazsa, web API’si her zaman belirtilen siparişi güncelleştirmeyi dener ve muhtemelen farkında olmadan başka bir kullanıcı tarafından yapılan güncelleştirmenin üzerine yazar. Kayıp güncelleştirmelerden kaynaklanan sorunları önlemek için her zaman bir If-Match üst bilgisi sağlayın.
Büyük istekleri ve yanıtları işleme
bir istemci uygulamasının boyutu birkaç megabayt (veya daha büyük) olabilecek verileri gönderen veya alan istekler göndermesi gereken durumlar olabilir. Bu miktarda verilerin aktarılmasını beklemek, istemci uygulamanın yanıt vermemesine neden olabilir. Büyük miktarda veriler içeren istekleri işlemeniz gerektiğinde aşağıdaki noktaları göz önünde bulundurun:
Büyük nesneler içeren istek ve yanıtları en iyi duruma getirme
Bazı kaynaklar büyük nesneler olabilir veya grafik görüntüleri veya diğer ikili veri türleri gibi büyük alanlar içerebilir. Bu kaynakların en iyi şekilde karşıya yüklenmesini ve indirilmesini sağlamak üzere web API’si akışı desteklemelidir.
HTTP protokolü, büyük veri nesnelerini istemciye akışla geri aktarmak için öbekli aktarım kodlama mekanizması sağlar. İstemci büyük bir nesne için bir HTTP GET isteği gönderdiğinde, web API’si yanıtı bir HTTP bağlantısı üzerinden öbek parçaları halinde geri gönderebilir. Yanıttaki verilerin uzunluğu başlangıçta bilinmiyor olabilir (oluşturulabilir), bu nedenle web API'sini barındıran sunucu, Content-Length üst bilgisi yerine üst bilgiyi belirten Transfer-Encoding: Chunked
her öbekle bir yanıt iletisi göndermelidir. İstemci uygulama her bir öbeği sırasıyla alıp tam yanıtı oluşturabilir. Sunucu sıfır boyuta sahip bir son öbeği geri gönderdiğinde veri aktarımı tamamlanır.
Tek bir istek, önemli miktarda kaynak tüketen çok büyük bir nesne ile sonuçlanabilir. Akış işlemi sırasında web API'si bir istekteki veri miktarının kabul edilebilir bazı sınırları aştığını belirlerse, işlemi durdurabilir ve durum kodu 413 (İstek Varlığı Çok Büyük) olan bir yanıt iletisi döndürebilir.
HTTP sıkıştırmasını kullanarak, ağ üzerinden aktarılan büyük nesnelerin boyutunu en aza indirebilirsiniz. Bu yaklaşım, ağ trafiği miktarını ve ilişkili ağ gecikmesini azaltmaya yardımcı olur ancak istemcide ve web API’sini barındıran sunucuda ek işleme gerektirir. Örneğin, sıkıştırılmış verileri almayı bekleyen bir istemci uygulaması bir Accept-Encoding: gzip
istek üst bilgisi içerebilir (diğer veri sıkıştırma algoritmaları da belirtilebilir). Sunucu sıkıştırmayı destekliyorsa, ileti gövdesinde ve Content-Encoding: gzip
yanıt üst bilgisinde gzip biçiminde tutulan içerikle yanıt vermelidir.
Kodlanmış sıkıştırmayı akışla birleştirebilirsiniz; verileri akışla aktarmadan önce sıkıştırabilir ve ileti üst bilgilerinde gzip içerik kodlaması ile öbekli aktarım kodlamasını belirtebilirsiniz. Ayrıca bazı web sunucularının (örneğin, Internet Information Server), web API’sinin verileri sıkıştırıp sıkıştırmadığına bakılmaksızın HTTP yanıtlarını otomatik olarak sıkıştıracak şekilde yapılandırılabileceğini unutmayın.
Zaman uyumsuz işlemleri desteklemeyen istemciler için kısmi yanıtlar uygulama
Bir istemci uygulama, zaman uyumsuz akışa alternatif olarak büyük nesneler için öbekler halinde açıkça veri isteyebilir. Bu duruma kısmi yanıt adı verilir. İstemci uygulama, nesne hakkında bilgi almak için bir HTTP HEAD isteği gönderir. Web API'si kısmi yanıtları destekliyorsa HEAD isteğine üst bilgi ve nesnenin toplam boyutunu gösteren bir üst bilgi içeren bir Accept-Ranges
Content-Length
yanıt iletisiyle yanıt vermelidir, ancak iletinin gövdesi boş olmalıdır. İstemci uygulama, alınacak bayt aralığını belirtmek üzere bir dizi GET isteği oluşturmak için bu bilgileri kullanabilir. Web API'sinin HTTP durumu 206 (Kısmi İçerik) olan bir yanıt iletisi, yanıt iletisinin gövdesinde yer alan gerçek veri miktarını belirten content-length üst bilgisi ve bu verilerin temsil ettiği nesnenin hangi bölümünü (bayt sayısı gibi 4000
8000
) gösteren bir İçerik Aralığı üst bilgisi döndürmesi gerekir.
HTTP HEAD istekleri ve kısmi yanıtlar API tasarımında daha ayrıntılı olarak açıklanmıştır.
İstemci uygulamalarda gereksiz 100-Continue durum iletileri göndermekten kaçınma
Bir sunucuya büyük miktarda veri göndermek üzere olan bir istemci uygulama, ilk olarak sunucunun isteği kabul etmek için gerçekten istekli olup olmadığını belirleyebilir. İstemci uygulama, verileri göndermeden önce Expect: 100-Continue üst bilgisi, verilerin boyutunu belirten bir Content-Length üst bilgisi ve boş bir ileti gövdesi ile HTTP isteği gönderebilir. Sunucu isteği işlemek için istekliyse, 100 (Devam) HTTP durumunu belirten bir ileti ile yanıt vermelidir. İstemci uygulama daha sonra devam edip ileti gövdesine verileri ekleyerek tam isteği gönderebilir.
Bir hizmeti Internet Information Services (IIS) kullanarak barındırıyorsanız, HTTP.sys sürücüsü istekleri web uygulamanıza geçirmeden önce Expect: 100-Continue üst bilgilerini otomatik olarak algılar ve işler. Bu durum, bu üst bilgileri uygulama kodunuzda görme olasılığınızın düşük olduğu anlamına gelir ve IIS’nin uygunsuz ya da çok büyük olarak kabul ettiği tüm iletileri filtrelediğini varsayabilirsiniz.
.NET Framework kullanarak istemci uygulamaları oluşturursanız, tüm POST ve PUT iletileri ilk olarak Varsayılan olarak Expect: 100-Continue üst bilgilerine sahip iletiler gönderir. Sunucu tarafında olduğu gibi işlem, .NET Framework tarafından şeffaf bir şekilde ele alınır. Ancak, bu işlem her bir POST ve PUT isteğinin küçük istekler için bile sunucuya iki gidiş dönüş oluşturması ile sonuçlanır. Uygulamanız büyük miktarda veriler içeren istekler göndermiyorsa, istemci uygulamada ServicePoint
nesneleri oluşturmak için ServicePointManager
sınıfını kullanarak bu özelliği devre dışı bırakabilirsiniz. Bir ServicePoint
nesnesi, istemcinin bir düzene göre sunucu ile kurduğu bağlantıları ve sunucu üzerindeki kaynakları tanımlayan URI’lerin konak parçalarını işler. Bundan sonra Expect100Continue
nesnesinin ServicePoint
özelliğini false olarak ayarlayabilirsiniz. İstemci tarafından ServicePoint
nesnesine ait düzen ve konak parçaları ile eşleşen bir URI aracılığıyla daha sonra yapılan tüm POST ve PUT istekleri, Expect: 100-Continue üst bilgileri olmadan gönderilir. Aşağıdaki kod, bir http
düzeni ve bir www.contoso.com
konağı ile URI’lere gönderilen tüm istekleri yapılandıran bir ServicePoint
nesnesini yapılandırma işlemini göstermektedir.
Uri uri = new Uri("https://www.contoso.com/");
ServicePoint sp = ServicePointManager.FindServicePoint(uri);
sp.Expect100Continue = false;
Sınıfın statik Expect100Continue
özelliğini ServicePointManager
, daha sonra oluşturulan tüm ServicePoint nesneleri için bu özelliğin varsayılan değerini belirtmek üzere de ayarlayabilirsiniz.
Çok sayıda nesne döndürebilen istekler için sayfalandırmayı destekleme
Bir koleksiyon çok sayıda kaynak içeriyorsa, karşılık gelen URI’ye bir GET isteğinin düzenlenmesi web API’sini barındıran sunucuda performansı etkileyerek önemli işlem yüküyle sonuçlanabilir ve gecikme süresini artıran önemli miktarda ağ trafiği oluşturabilir.
Bu sorunları ele almak için web API’si, istemci uygulamanın istekleri daha kolay yönetilebilir, farklı bloklar (veya sayfalar) halinde daraltmasını sağlayan sorgu dizelerini desteklemelidir. Aşağıdaki kod, denetleyicideki Orders
yöntemini gösterirGetAllOrders
. Bu yöntem, siparişlerin ayrıntılarını alır. Bu yöntem kısıtlanmamışsa büyük miktarda veri döndürebilir. limit
ve offset
parametreleri, veri hacmini daha küçük bir alt kümeye indirgemeye (bu örnekte varsayılan olarak ilk 10 sipariş) yöneliktir:
public class OrdersController : ApiController
{
...
[Route("api/orders")]
[HttpGet]
public IEnumerable<Order> GetAllOrders(int limit=10, int offset=0)
{
// Find the number of orders specified by the limit parameter
// starting with the order specified by the offset parameter
var orders = ...
return orders;
}
...
}
Bir istemci uygulama, https://www.adventure-works.com/api/orders?limit=30&offset=50
URI’sini kullanarak 50 uzaklıktan başlayarak 30 siparişi almak üzere bir istek gönderebilir.
İpucu
İstemci uygulamaların 2000 karakterden uzun bir URI ile sonuçlanan sorgu dizeleri belirtmesini önleyin. Birçok web istemcisi ve sunucusu bu kadar uzun URI'leri işleyemez.
Yanıt hızı, ölçeklenebilirlik ve kullanılabilirliği sürdürme
Aynı web API'si dünyanın herhangi bir yerinde çalışan birçok istemci uygulaması tarafından kullanılabilir. Ağır bir yük altında yanıt hızını korumak, yüksek oranda değişen bir iş yükünü destekleyecek şekilde ölçeklenebilir olmak ve kritik iş işlemleri gerçekleştiren istemciler için kullanılabilirliği garanti etmek amacıyla web API’sinin uygulandığından emin olmak gerekir. Bu gereksinimlerin nasıl karşılanacağını belirlerken aşağıdaki noktaları göz önünde bulundurun:
Uzun süreli istekler için zaman uyumsuz destek sağlama
İşlenmesi uzun sürebilecek bir istek, isteği gönderen istemciyi engellemeden gerçekleştirilmelidir. Web API’si isteği doğrulamak üzere bazı ilk denetimler gerçekleştirebilir, işi gerçekleştirmek üzere ayrı bir görev başlatabilir ve sonra 202 (Kabul Edildi) HTTP kodu ile bir yanıt iletisi döndürebilir. Görev web API'si kapsamında zaman uyumsuz olarak çalışabilir veya bir arka plan görevine boşaltılabilir.
Web API’si ayrıca işleme sonuçlarını istemci uygulamaya döndüren bir mekanizma sağlamalıdır. İstemci uygulamaların işlemenin tamamlanıp tamamlanmadığını düzenli aralıklarla sorgulayıp sonucu almasına yönelik bir yoklama mekanizması sağlayarak ya da işlem tamamlandığında web API’sinin bir bildirim göndermesini sağlayarak bunu gerçekleştirebilirsiniz.
Aşağıdaki yaklaşımı kullanarak, sanal bir kaynak olarak hareket eden bir yoklama URI’si sağlama yoluyla basit bir yoklama mekanizması uygulayabilirsiniz:
- İstemci uygulama, ilk isteği web API’sine gönderir.
- Web API'si, istekle ilgili bilgileri Azure Tablo Depolama veya Microsoft Azure Cache'te tutulan bir tabloda depolar ve bu giriş için büyük olasılıkla genel olarak benzersiz bir tanımlayıcı (GUID) biçiminde benzersiz bir anahtar oluşturur. Alternatif olarak, istek ve benzersiz anahtar hakkındaki bilgileri içeren bir ileti de Azure Service Bus aracılığıyla gönderilebilir.
- Web API'si işlemeyi ayrı bir görev olarak veya Hangfire gibi bir kitaplıkla başlatır. Web API'si, görevin durumunu tabloya Çalışıyor olarak kaydeder.
- Web API'si HTTP durum kodu 202 (Kabul Edildi) ve /polling/{guid} gibi oluşturulan benzersiz anahtarı içeren bir URI içeren bir yanıt iletisi döndürür.
- Görev tamamlandığında, web API'si sonuçları tabloda depolar ve görevin durumunu Tamamlandı olarak ayarlar. Görev başarısız olursa web API’sinin hatayla ilgili bilgileri de depolayabileceğini ve durumu Başarısız olarak ayarlayabileceğini unutmayın.
- Olası geçici hataları çözmek için yeniden deneme tekniklerini uygulamayı göz önünde bulundurun.
- Görev çalıştırılırken istemci kendi işlemini gerçekleştirmeye devam edebilir. Daha önce aldığı URI'ye düzenli aralıklarla istek gönderebilir.
- URI'deki web API'si, tablodaki karşılık gelen görevin durumunu sorgular ve bu durumu içeren HTTP durum kodu 200 (Tamam) içeren bir yanıt iletisi döndürür (Çalışıyor, Tamamlandı veya Başarısız). Görev tamamlandıysa veya başarısız olduysa, yanıt iletisi işlemin sonuçlarını veya hata nedeniyle ilgili mevcut tüm bilgileri de içerebilir.
- Uzun süre çalışan işlemin daha fazla ara durumu varsa, NServiceBus veya MassTransit gibi saga desenini destekleyen bir kitaplık kullanmak daha iyidir.
Bildirimleri uygulama seçenekleri şunlardır:
- İstemci uygulamalarına zaman uyumsuz yanıtlar göndermek için bildirim hub'ı kullanma. Daha fazla bilgi için bkz . Azure Notification Hubs kullanarak belirli kullanıcılara bildirim gönderme.
- İstemci ile web API’sini barındıran sunucu arasında kalıcı bir ağ bağlantısı sürdürmek üzere Comet modelini kullanma ve bu bağlantıyı kullanarak sunucudan istemciye iletileri geri gönderme. Building a Simple Comet Application in the Microsoft .NET Framework (Microsoft .NET Framework’te Basit Bir Comet Uygulaması Derleme) adlı MSDN dergisi makalesinde örnek bir çözüm açıklanmaktadır.
- Kalıcı bir ağ bağlantısı üzerinden verileri web sunucusundan istemciye gerçek zamanlı olarak göndermek için SignalR kullanma. SignalR, bir NuGet paketi olarak ASP.NET web uygulamaları için kullanılabilir. ASP.NET SignalR web sitesinde daha fazla bilgi bulabilirsiniz.
Her isteğin durum bilgisiz olduğundan emin olma
Her isteğin atomik olduğu kabul edilmelidir. Bir istemci uygulama tarafından yapılan istek ile aynı istemcinin gönderdiği sonraki istekler arasında bir bağımlılık olmamalıdır. Bu yaklaşım ölçeklenebilirliğe yardımcı olur; web hizmetinin örnekleri birkaç sunucuya üzerinde dağıtılabilir. İstemci istekleri bu örneklerin herhangi birine yönlendirilebilir ve sonuçlar her zaman aynı olmalıdır. Ayrıca, benzer bir nedenle kullanılabilirliği artırır; bir web sunucusu başarısız olursa, istemci uygulamalara olumsuz bir etkisi olmadan sunucu yeniden başlatılırken istekler başka bir örneğe yönlendirilebilir (Azure Traffic Manager kullanılarak).
DoS saldırılarının olasılığını azaltmak için istemcileri izleme ve azaltma uygulama
Belirli bir istemci belirli bir süre içinde çok sayıda istek yaparsa, hizmeti sadece kendi yönetimine alıp diğer istemcilerin performansını etkileyebilir. Bu sorunu gidermek için web API’si tüm gelen isteklerin IP adresini izleyerek veya kimliği doğrulanmış her erişimi günlüğe kaydederek istemci uygulamalardan gelen çağrıları izleyebilir. Bu bilgileri, kaynak erişimini sınırlamak için kullanabilirsiniz. Bir istemci tanımlı bir sınırı aşarsa, web API’si 503 (Hizmet Kullanılamıyor) durumu ile bir yanıt iletisi döndürebilir ve istemcinin reddedilmeden sonraki isteği ne zaman gönderebileceğini belirten bir Retry-After üst bilgisi ekleyebilir. Bu strateji, sistemi geciktiren bir istemci kümesinden Hizmet Reddi (DoS) saldırısı olasılığını azaltmaya yardımcı olabilir.
Kalıcı HTTP bağlantılarını dikkatli bir şekilde yönetme
HTTP protokolü, kullanılabilir olduğu durumlarda kalıcı HTTP bağlantılarını destekler. HTTP 1.0 belirtimi, istemci uygulamasının sunucuya yenilerini açmak yerine sonraki istekleri göndermek için aynı bağlantıyı kullanabileceğini belirtmesini sağlayan Connection:Keep-Alive üst bilgisini ekledi. İstemci, konak tarafından tanımlanan bir süre içinde bağlantıyı yeniden kullanmazsa bağlantı otomatik olarak kapanır. Bu davranış, Azure hizmetleri tarafından HTTP 1.1’de kullanılan varsayılan davranıştır; bu nedenle, iletilere Keep-Alive üst bilgilerini eklemek gerekmez.
Bağlantının açık tutulması, gecikme süresi ve ağ tıkanıklığını azaltarak yanıt süresini iyileştirmeye yardımcı olabilir, ancak gereksiz bağlantıları gerekenden daha uzun süre açık tutup diğer eşzamanlı istemcilerin bağlantı kurma becerisini sınırlayarak ölçeklenebilirliğe zarar verebilir. Ayrıca, istemci uygulama bir mobil cihazda çalışıyorsa pil ömrünü etkileyebilir; uygulama sunucuya yalnızca ara sıra istek gönderiyorsa, bağlantının açık tutulması pilin daha hızlı boşalmasına neden olabilir. Bir bağlantının HTTP 1.1 ile kalıcı hale getirilmediğinden emin olmak için istemci, varsayılan davranışı geçersiz kılmak üzere iletilere bir Connection:Close üst bilgisi ekleyebilir. Benzer şekilde, bir sunucu çok fazla sayıda istemciyi işliyorsa, yanıt iletilerine Connection:Close üst bilgisini ekleyerek bağlantıyı kapatması ve sunucu kaynaklarını koruması gerekir.
Not
Kalıcı HTTP bağlantıları, tekrarlayarak bir iletişim kanalı kurma ile ilişkili ağ yükünü azaltmaya yönelik tamamen isteğe bağlı bir özelliktir. Ne web API’sinin ne de istemcinin kullanılabilir olması, kalıcı bir HTTP bağlantısına bağlı olmalıdır. Comet stili bildirim sistemlerini uygulamak için kalıcı HTTP bağlantıları kullanmayın; bunun yerine TCP katmanında yuvalar (veya varsa web yuvaları) kullanmanız gerekir. Son olarak, istemci uygulama bir suucu ile ara sunucu üzerinden iletişim kuruyorsa Keep-Alive üst bilgilerinin sınırlı kullanıma sahip olduğunu unutmayın. Yalnızca istemci ve ara sunucu içeren bağlantı kalıcı olur.
Web API’si yayımlama ve yönetme
Bir web API’sini istemci uygulamalar için kullanılabilir hale getirmek üzere web API’sinin bir ana bilgisayar ortamına dağıtılması gerekir. Bu ortam diğer türdeki ana bilgisayar işlemlerinden bazıları olabilse de, genellikle bir web sunucusudur. Bir web API'sini yayımlarken aşağıdaki noktaları dikkate almanız gerekir:
- Tüm istekler kimlik doğrulamasından geçmiş ve yetkilendirilmiş olmalı ve uygun düzeyde erişim denetimi uygulanmalıdır.
- Ticari bir web API’si, yanıt süreleriyle ilgili çeşitli kalite garantilerine tabi olabilir. Yük zaman içinde önemli ölçüde farklılık gösterebiliyorsa konak ortamının ölçeklenebilir olduğundan emin olmak önemlidir.
- Gelir elde etme amacıyla isteklerin ölçülmesi gerekebilir.
- Web API’sine trafik akışının düzenlenmesi ve kotalarını tüketmiş belirli istemciler için ağ kapasitesinin azaltılması gerekebilir.
- Yasal düzenlemeler tüm istek ve yanıtların kaydedilmesini ve denetlenmesini zorunlu kılabilir.
- Kullanılabilirliği sağlamak için, web API’sini barındıran sunucunun durumunun izlenmesi ve gerekirse yeniden başlatılması gerekebilir.
Bu sorunları web API'sinin uygulanmasıyla ilgili teknik sorunlardan ayrıştırabilmek yararlıdır. Bu nedenle, ayrı işlem olarak çalışan ve istekleri web API’sine yönlendiren bir cephe oluşturmayı düşünün. Cephe, yönetim işlemlerini sağlayabilir ve doğrulanmış istekleri web API’sine iletebilir. Cephe kullanılması aşağıdaki gibi çok sayıda işlevsel avantaj da sağlayabilir:
- Birden çok web API'si için tümleştirme noktası olarak hareket etme.
- Çeşitli teknolojiler kullanılarak oluşturulan istemciler için iletileri dönüştürme ve iletişim protokollerini çevirme.
- Web API’sini barındıran sunucu üzerindeki yükü azaltmak üzere istekleri ve yanıtları önbelleğe alma.
Web API'sini test etme
Bir web API’si, yazılımın herhangi bir kısmı kadar ayrıntılı bir şekilde test edilmelidir. İşlevselliği doğrulamak için birim testleri oluşturmayı düşünmelisiniz.
Bir web API'sinin doğası, düzgün çalıştığını doğrulamak için kendi ek gereksinimlerini getirir. Aşağıdaki durumlara özellikle dikkat etmeniz gerekir:
Doğru işlemleri çağırdığını onaylamak üzere tüm yolları test edin. Bir yol ile bu yola gönderilebilen HTTP yöntemleri (GET, POST, PUT, DELETE) arasında bir uyumsuzluk olduğunu gösterebileceği için, beklenmedik şekilde döndürülen 405 (Yönteme İzin Verilmiyor) HTTP durum koduna özellikle dikkat edin.
Belirli bir kaynağa POST isteği gönderme gibi, bunları desteklemeyen yollara HTTP istekleri gönderin (POST istekleri yalnızca kaynak koleksiyonlarına gönderilmelidir). Bu durumlarda tek geçerli yanıt 405 (İzin Verilmiyor) durum kodu olmalıdır.
Tüm yolların uygun şekilde korunduğunu ve uygun kimlik doğrulama ile yetkilendirme denetimlerine tabi olduğunu doğrulayın.
Not
Kullanıcı kimlik doğrulaması gibi bazı güvenlik yönlerinin web API’si yerine ana bilgisayar ortamının sorumluluğunda olması daha yüksek bir olasılıktır, ancak yine de dağıtım işlemine güvenlik testlerinin dahil edilmesi gerekir.
Her bir işlem tarafından gerçekleştirilen özel durum işlemeyi test edin ve istemci uygulamaya uygun ve anlamlı bir HTTP yanıtının geri gönderildiğini doğrulayın.
İstek ve yanıt iletilerinin doğru oluşturulduğunu onaylayın. Örneğin, bir HTTP POST isteği yeni bir kaynağın verilerini x-www-form-urlencoded biçiminde içeriyorsa, karşılık gelen işlemin verileri doğru şekilde ayıkladığını, kaynakları oluşturduğunu ve doğru Location üst bilgisi dahil olmak üzere yeni kaynağın ayrıntılarını içeren bir yanıt döndürdüğünü onaylayın.
Yanıt iletilerindeki tüm bağlantıları ve URI'leri doğrulayın. Örneğin, bir HTTP POST iletisi yeni oluşturulan kaynağın URI'sini döndürmelidir. Tüm HATEOAS bağlantıları geçerli olmalıdır.
Her işlemin farklı giriş birleşimleri için doğru durum kodlarını döndürdüğünden emin olun. Örneğin:
- Bir sorgu başarılı olursa, 200 (Tamam) durum kodunu döndürmelidir
- Bir kaynak bulunamıyorsa, işlem 404 (Bulunamadı) HTTP durum kodunu döndürmelidir.
- İstemci bir kaynağı başarıyla silen bir istek gönderirse durum kodu 204 (İçerik Yok) olmalıdır.
- İstemci yeni bir kaynak oluşturan bir istek gönderirse, durum kodu 201 (Oluşturuldu) olmalıdır.
5xx aralığında beklenmedik yanıt durum kodlarına dikkat edin. Bu iletiler genellikle geçerli bir isteği yerine getiremediğini belirtmek üzere ana bilgisayar sunucusu tarafından raporlanır.
Bir istemci uygulamanın belirtebildiği farklı istek üst bilgisi birleşimlerini test edin ve web API’sinin yanıt iletilerinde beklenen bilgileri döndürdüğünden emin olun.
Sorgu dizelerini test edin. Bir işlem isteğe bağlı parametreler (örneğin, sayfalandırma istekleri) alabiliyorsa, parametrelerin farklı birleşimlerini ve sırasını test edin.
Zaman uyumsuz işlemlerin başarıyla tamamlandığını doğrulayın. Web API’si büyük ikili nesneler (video veya ses gibi) döndüren istekler için akış yapmayı destekliyorsa, veriler akışla aktarılırken istemci isteklerinin engellenmediğinden emin olun. Web API'si uzun süre çalışan veri değiştirme işlemleri için yoklama uygularsa, işlemlerin devam ederken durumlarını doğru bildirdiğini doğrulayın.
Ayrıca, web API’sinin zorlama altında tatmin edici bir şekilde çalışıp çalışmadığını denetlemek için performans testleri oluşturup çalıştırmanız gerekir. Visual Studio Ultimate’ı kullanarak bir web performansı ve yük testi projesi oluşturabilirsiniz.
Azure API Management’ı Kullanma
Azure'da, web API'sini yayımlamak ve yönetmek için Azure API Management'ı kullanmayı göz önünde bulundurun. Bu özelliği kullanarak, bir veya daha fazla web API’si için cephe olarak davranan bir hizmet oluşturabilirsiniz. Hizmet, Azure portalını kullanarak oluşturabileceğiniz ve yapılandırabileceğiniz ölçeklenebilir bir web hizmetidir. Bu hizmeti kullanarak bir web API’sini aşağıdaki gibi yayımlayıp yönetebilirsiniz:
Web API’sini bir web sitesine, Azure bulut hizmetine veya Azure sanal makinesine dağıtın.
API yönetim hizmetini web API'sine bağlayın. Yönetim API’sinin URL’sine gönderilen istekler, web API’sindeki URI’ler ile eşlenir. Aynı API yönetimi hizmeti, istekleri birden fazla web API’sine yönlendirebilir. Bunun yapılması, birden fazla web API’sini tek bir yönetim hizmetinde toplamanıza olanak tanır. Benzer şekilde, farklı uygulamaların kullanabileceği işlevleri kısıtlamanız veya bölmeniz gerekirse aynı web API’sine birden fazla API yönetim hizmetinden başvurulabilir.
Not
HTTP GET isteklerine yönelik yanıtın bir parçası olarak oluşturulan HATEOAS bağlantılarındaki URI'ler, web API'sini barındıran web sunucusuna değil API yönetim hizmetinin URL'sine başvurmalıdır.
Her bir web API’si için web API’sinin işleme giriş olarak eklenebilecek isteğe bağlı parametrelerle birlikte kullanıma sunduğu HTTP işlemlerini belirtin. API yönetim hizmetinin aynı verilere yönelik tekrarlayan istekleri en iyi duruma getirmek üzere web API’sinden alınan yanıtı önbelleğe alıp almayacağını da yapılandırabilirsiniz. Her bir işlemin oluşturabileceği HTTP yanıtlarının ayrıntılarını kaydedin. Bu bilgiler geliştiricilere yönelik belgeler oluşturmak için kullanılır, bu nedenle doğru ve eksiksiz olması önemlidir.
Azure portalı tarafından sağlanan sihirbazları kullanarak işlemleri el ile tanımlayabilir veya wadl veya Swagger biçiminde tanımları içeren bir dosyadan içeri aktarabilirsiniz.
API yönetim hizmeti ile web API’sini barındıran web sunucusu arasındaki iletişime yönelik güvenlik ayarlarını yapılandırın. API management hizmeti şu anda sertifikaları kullanarak Temel kimlik doğrulamasını ve karşılıklı kimlik doğrulamasını ve Açık Yetkilendirme (OAuth) 2.0 kullanıcı yetkilendirmesini destekler.
Ürün oluşturma. Ürün, yayın birimidir; daha önce yönetim hizmetine bağladığınız web API’lerini ürüne eklersiniz. Ürün yayımlandığında web API’leri geliştiriciler için kullanılabilir hale gelir.
Not
Bir ürün yayımlanmadan önce ürüne erişebilecek kullanıcı grupları tanımlayabilir ve bu gruplara kullanıcı ekleyebilirsiniz. Böylece, web API’sini kullanabilecek geliştiriciler ve uygulamalar üzerinde denetim elde edersiniz. Bir web API’si onaya tabidir; bir geliştiricinin web API’sine erişebilmesi için ürün yöneticisine istek göndermesi gerekir. Yönetici, geliştiriciye erişim verebilir veya erişimi engelleyebilir. Koşulların değişmesi halinde mevcut geliştiriciler de engellenebilir.
Her bir web API'sine yönelik ilkeleri yapılandırın. İlkeler, etki alanları arası çağrılara izin verilip verilmeyeceği, istemci kimliklerinin nasıl doğrulanacağı, XML ile JSON veri biçimleri arasında şeffaf dönüştürme yapılıp yapılmayacağı, belirli bir IP aralığından çağrıların kısıtlanıp kısıtlanmayacağı, kullanım kotaları ve çağrı hızının sınırlanıp sınırlanmayacağı gibi konuları yönetir. İlkeler ürünün tamamına genel olarak, bir üründeki tek bir web API’si için veya bir web API’sindeki tek işlemler için uygulanabilir.
Daha fazla bilgi için API Management belgelerine bakın.
İpucu
Azure, yük devretme ve yük dengeleme işlemlerini uygulamanıza ve farklı coğrafi bölgelerde barındırılan bir web sitesinin birden fazla örneğinde gecikme süresini azaltmanıza olanak tanıyan Azure Traffic Manager’ı sunar. Azure Traffic Manager’ı API Management Hizmeti ile birlikte kullanabilirsiniz; API Management Hizmeti, istekleri Azure Traffic Manager aracılığıyla bir web sitesinin örneklerine yönlendirebilir. Daha fazla bilgi için bkz . Traffic Manager yönlendirme yöntemleri.
Bu yapıda, web siteleriniz için özel DNS adları kullanıyorsanız, her web sitesi için uygun CNAME kaydını Azure Traffic Manager web sitesinin DNS adına işaret eden şekilde yapılandırmanız gerekir.
İstemci tarafı geliştiricileri destekleme
İstemci uygulamalar oluşturan geliştiriciler genellikle web API’sine erişim ile ilgili bilgiler ve web hizmeti ile istemci uygulama arasındaki farklı istek ve yanıtları tanımlayan parametreler, veri türleri, dönüş türleri ve dönüş kodları ile ilgili belgeler gerektirir.
Bir web API’sinin REST işlemlerini belgeleme
Azure API Management Hizmeti bir web API’si tarafından kullanıma sunulan REST işlemlerini tanımlayan bir geliştirici portalı içerir. Bir ürün yayımlandığında bu portalda görüntülenir. Geliştiriciler, erişime kaydolmak için bu portalı kullanabilir; daha sonra yönetici, isteği onaylayabilir veya reddedebilir. Geliştirici onaylanırsa kendisine geliştirdiği istemci uygulamalardan gelen çağrıların kimliğini doğrulamak için kullanılan bir abonelik anahtarı atanır. Bu anahtar her web API çağrısında kullanılmalıdır; aksi takdirde çağrı reddedilir.
Bu portal ayrıca şunları sağlar:
- Ürünün kullanıma sunduğu işlemleri, gerekli parametreleri ve döndürülebilecek farklı yanıtları listeleyen ürün belgeleri. Bu bilgilerin Microsoft Azure API Management Hizmetini kullanarak web API’si yayımlama bölümünde bulunan listedeki 3. adımda verilen ayrıntılardan oluşturulduğunu unutmayın.
- JavaScript, C#, Java, Ruby, Python ve PHP dahil olmak üzere birkaç dilden işlemlerin nasıl çağrılacağını gösteren kod parçacıkları.
- Geliştiricinin üründeki her bir işlemi test etmek ve sonuçları görüntülemek üzere HTTP isteği göndermesini sağlayan geliştirici konsolu.
- Geliştiricinin bulunan her türlü sorunu bildirebileceği bir sayfa.
Azure portalı, kuruluşunuzun markasıyla eşleşecek şekilde stil ve düzeni değiştirmek için geliştirici portalını özelleştirmenizi sağlar.
İstemci SDK’sını uygulama
Bir web API’sine erişmek üzere REST istekleri çağıran bir istemci uygulamanın derlenmesi, her bir isteği oluşturmak için önemli miktarda kod yazıp uygun şekilde biçimlendirmeyi, isteği web hizmetini barındıran sunucuya göndermeyi ve isteğin başarılı olup olmadığını belirlemek ve döndürülen verileri ayıklamak üzere yanıtı ayrıştırmayı gerektirir. İstemci uygulamayı bu sorunlardan uzak tutmak için REST arabirimini sarmalayan ve bu düşük düzeyli ayrıntıları daha işlevsel bir yöntem kümesinde soyutlayan bir SDK sağlayabilirsiniz. İstemci uygulama, çağrıları saydam bir şekilde REST isteklerine dönüştüren ve sonra yanıtları yeniden yöntem dönüş değerlerine dönüştüren bu yöntemleri kullanır. Bu teknik, Azure SDK’sı dahil birçok hizmet tarafından yaygın olarak uygulanır.
İstemci tarafı SDK oluşturma işlemi tutarlı bir şekilde uygulanması ve dikkatlice test edilmesi gereken önemli bir iştir. Ancak, bu işlemin büyük bölümü mekanik hale getirilebilir ve birçok satıcı bu görevlerin birçoğunu otomatikleştirebilen araçlar sağlar.
Web API'sini izleme
Web API’nizi nasıl yayımlayıp dağıttığınıza bağlı olarak, web API’sini doğrudan izleyebilir veya API Management hizmetinden geçen trafiği analiz ederek kullanım ve sistem durumu bilgilerini toplayabilirsiniz.
Web API'sini doğrudan izleme
Web API’nizi ASP.NET Web API şablonu (bir Web API projesi ya da Azure bulut hizmetinde bir Web rolü olarak) ve Visual Studio 2013 kullanarak uyguladıysanız, ASP.NET Application Insights’ı kullanarak kullanılabilirlik, performans ve kullanım verilerini toplayabilirsiniz. Application Insights, web API’si buluta dağıtıldığında istek ve yanıtlara ilişkin bilgileri şeffaf bir şekilde izleyip kaydeden bir pakettir; paket yüklenip yapılandırıldıktan sonra paketi kullanmak için web API’nizde herhangi bir kodu değiştirmeniz gerekmez. Web API’sini bir Azure web sitesine dağıttığınızda tüm trafik incelenir ve aşağıdaki istatistikler toplanır:
- Sunucu yanıt süresi.
- Sunucu isteklerinin sayısı ve her isteğin ayrıntıları.
- Ortalama yanıt süresi bakımından en yavaş istekler.
- Başarısız olan isteklerin ayrıntıları.
- Farklı tarayıcılar ve kullanıcı aracıları tarafından başlatılan oturum sayısı.
- En sık görüntülenen sayfalar (web API’leri yerine öncelikle web uygulamaları için yararlıdır).
- Web API’sine erişen farklı kullanıcı rolleri.
Bu verileri Azure portalında gerçek zamanlı olarak görüntüleyebilirsiniz. Ayrıca, web API'sinin durumunu izleyen web testleri de oluşturabilirsiniz. Web testi, web API'sinde belirtilen URI'ye düzenli bir istek gönderir ve yanıtı yakalar. Başarılı bir yanıtın tanımını belirtebilir (HTTP durum kodu 200 gibi) ve istek bu yanıtı döndürmezse yöneticiye gönderilecek bir uyarı ayarlayabilirsiniz. Gerekirse, yönetici başarısız olması durumunda web API’sini barındıran sunucuyu yeniden başlatabilir.
Daha fazla bilgi için bkz. Application Insights - ASP.NET kullanmaya başlama.
API Management Hizmeti aracılığıyla web API’si izleme
Web API'nizi API Management hizmetini kullanarak yayımladıysanız, Azure portalındaki API Management sayfasında hizmetin genel performansını görüntülemenizi sağlayan bir pano bulunur. Analiz sayfası, ürünün kullanımına ilişkin ayrıntılara inmenizi sağlar. Bu sayfa aşağıdaki sekmeleri içerir:
- Kullanım. Bu sekme, yapılan API çağrılarının sayısı ve zaman içinde bu çağrıları işlemek için kullanılan bant genişliği hakkında bilgi verir. Kullanım ayrıntılarını ürün, API ve işleme göre filtreleyebilirsiniz.
- Sistem Durumu. Bu sekmeyi kullanarak API isteklerinin sonucunu (döndürülen HTTP durum kodları), önbelleğe alma ilkesinin etkinliğini, API yanıt süresini ve hizmet yanıt süresini görüntüleyebilirsiniz. Sistem durumu verilerini de ürün, API ve işleme göre filtreleyebilirsiniz.
- Etkinlik. Bu sekme başarılı çağrı, başarısız çağrı, engellenen çağrı, ortalama yanıt süresi ve her bir ürüne ait yanıt süresi, web API’si ve işlem sayısının metin özetini sağlar. Bu sayfa ayrıca her bir geliştirici tarafından yapılan çağrıların sayısını listeler.
- Bir bakışta. Bu sekme, çoğu API çağrısını yapmaktan sorumlu geliştiriciler dahil olmak üzere performans verilerinin, ürünlerin, web API’lerinin ve bu çağrıları alan işlemlerin bir özeti gösterir.
Belirli bir web API'si veya işlemin bir performans sorununa neden olup olmadığını belirlemek ve gerekirse ana bilgisayar ortamını ölçeklendirip daha fazla sunucu eklemek için bu bilgileri kullanabilirsiniz. Ayrıca bir veya daha fazla uygulamanın orantısız hacimlerde kaynak kullanıp kullanmadığını öğrenebilir ve kota ayarlamak ve çağrı oranlarını sınırlamak üzere uygun ilkeler uygulayabilirsiniz.
Not
Yayımlanmış bir ürünün ayrıntılarını değiştirdiğinizde değişiklikler hemen uygulanır. Örneğin, bir web API’sini içeren ürünü yeniden yayımlamanıza gerek kalmadan web API’sine işlem ekleyebilir ya da kaldırabilirsiniz.
Sonraki adımlar
- ASP.NET Web API OData, ASP.NET kullanarak bir OData web API’si uygulamaya ilişkin örnekler ve daha ayrıntılı bilgiler içerir.
- Web API'sinde ve Web API'sinde toplu iş desteğine giriş OData kullanılarak bir web API'sinde toplu işlemlerin nasıl uygulandığı açıklanır.
- Jonathan Oliver'ın blogundaki Idempotency desenleri , bir kez etkililiğe ve bunun veri yönetimi işlemleriyle ilişkisine genel bir bakış sağlar.
- W3C web sitesindeki durum kodu tanımları , HTTP durum kodlarının ve açıklamalarının tam listesini içerir.
- WebJobs ile arka plan görevleri çalıştırma, arka plan işlemleri gerçekleştirmek için WebJobs kullanmaya ilişkin bilgi ve örnekler sağlar.
- Azure Notification Hubs, kullanıcılara istemci uygulamalarına zaman uyumsuz yanıtlar göndermek için Azure Notification Hub'ın nasıl kullanılacağını gösterir.
- API Management, bir web API'sine denetimli ve güvenli erişim sağlayan bir ürünü yayımlama işlemini açıklar.
- Azure API Management REST API başvurusu , özel yönetim uygulamaları oluşturmak için API Management REST API'sinin nasıl kullanılacağını açıklar.
- Traffic Manager yönlendirme yöntemleri , Azure Traffic Manager'ın web API'sini barındıran bir web sitesinin birden çok örneğinde isteklerin yükünü dengelemek için nasıl kullanılabileceğini özetler.
- Application Insights - ASP.NET kullanmaya başlama, bir ASP.NET Web API projesinde Application Insights yükleme ve yapılandırma hakkında ayrıntılı bilgiler sağlar.