Aracılığıyla paylaş


ASP.NET Core ile yerel mobil uygulamalar için arka uç hizmetleri oluşturma

Tarafından James Montemagno

Mobil uygulamalar ASP.NET Core arka uç hizmetleriyle iletişim kurabilir. iOS simülatörlerinden ve Android öykünücülerinden yerel web hizmetlerini bağlama yönergeleri için bkz. Android öykünücülerinden ve iOS simülatörlerinden yerel web hizmetlerine bağlanma.

Örnek arka uç hizmetleri kodunu görüntüleme veya indirme

Örnek yerel mobil uygulama

Bu öğreticide, yerel mobil uygulamaları desteklemek için ASP.NET Core kullanarak arka uç hizmetlerinin nasıl oluşturulacağı gösterilmektedir. Yerel istemcisi olarak .NET MAUI uygulaması kullanır. Örnek, bu makalede nasıl oluşturabileceğinizi gösteren bir ASP.NET Core Web API hizmetleri projesi içerir.

Android akıllı telefon üzerinde çalışan To Do Rest uygulaması

Özellikler

TodoREST uygulaması yapılacaklar öğelerini listelemeyi, eklemeyi, silmeyi ve güncelleştirmeyi destekler. Her öğenin kimliği, adı, notları ve henüz yapılıp yapılmadığını belirten bir özelliği vardır.

Önceki örnekte, öğelerin ana görünümü her öğenin adını listeler ve bir onay işaretiyle tamamlanıp bitmediğini gösterir.

+ simgesine dokunduğunuzda öğe ekle sayfasına gider:

Öğe ekle iletişim kutusu

Ana sayfadaki bir öğeye dokunulduğunda, öğenin adı, notları ve bitti ayarlarının değiştirilebildiği veya öğenin silinebileceği bir düzenleme sayfasına gider:

Öğeyi düzenle iletişim kutusu

Bir sonraki bölümde oluşturulan ASP.NET Core uygulamasında test etmek için uygulamayı çevrimiçi olarak barındıracaksanız uygulamanın RestUrl sabitini güncelleştirin. Aksi takdirde uygulama, makinenizde yerel olarak barındırılan ASP.NET Core uygulamasıyla iletişim kurar.

Android öykünücüleri yerel makinede çalışmaz ve yerel makineyle iletişim kurmak için loopback IP adresi (10.0.2.2) kullanır. Doğru URL'yi kullanmak üzere uygulamanın üzerinde çalıştığı işletim sistemini algılamak için .NET MAUIDeviceInfo sınıfını kullanın.

TodoREST Projeye gidin ve dosyayı açınConstants.cs. Dosya Constants.cs aşağıdaki yapılandırmayı içerir.

namespace TodoREST
{
    public static class Constants
    {
        // URL of REST service
        //public static string RestUrl = "https://dotnetmauitodorest.azurewebsites.net/api/todoitems/{0}";

        // URL of REST service (Android does not use localhost)
        // Use http cleartext for local deployment. Change to https for production
        public static string LocalhostUrl = DeviceInfo.Platform == DevicePlatform.Android ? "10.0.2.2" : "localhost";
        public static string Scheme = "https"; // or http
        public static string Port = "5001";
        public static string RestUrl = $"{Scheme}://{LocalhostUrl}:{Port}/api/todoitems/{{0}}";
    }
}

İsteğe bağlı olarak web hizmetini Azure gibi bir bulut hizmetine dağıtabilir ve güncelleştirebilirsiniz RestUrl.

ASP.NET Çekirdek Projesini Oluşturma

Visual Studio'da yeni bir ASP.NET Core Web Uygulaması oluşturun. Web API şablonunu seçin. Projeyi TodoAPI olarak adlandırın.

Web API proje şablonunun seçili olduğu Yeni ASP.NET Web Uygulaması iletişim kutusu

Uygulama, 5001 numaralı bağlantı noktasına HTTPS üzerinden yapılan tüm isteklere yanıt vermelidir.

Not

Uygulamayı IIS Express'in arkasında değil doğrudan çalıştırın. IIS Express, yerel olmayan istekleri varsayılan olarak yoksayar. Komut isteminden dotnet çalıştır'ı çalıştırın veya Visual Studio araç çubuğundaki Hata Ayıklama Hedefi açılır menüsünden uygulama adı profilini seçin.

Yapılacaklar öğelerini temsil eden bir model sınıfı ekleyin. Gerekli alanları şu öznitelikle [Required] işaretleyin:

using System.ComponentModel.DataAnnotations;

namespace TodoAPI.Models
{
    public class TodoItem
    {
        [Required]
        public string ID { get; set; }

        [Required]
        public string Name { get; set; }

        [Required]
        public string Notes { get; set; }

        public bool Done { get; set; }
    }
}

API yöntemleri, verilerle çalışmak için tanımlama gerektirir. Aynı ITodoRepository arabirimini kullanın, örnekte kullanıldığı gibi.

using TodoAPI.Models;

namespace TodoAPI.Interfaces
{
    public interface ITodoRepository
    {
        bool DoesItemExist(string id);
        IEnumerable<TodoItem> All { get; }
        TodoItem Find(string id);
        void Insert(TodoItem item);
        void Update(TodoItem item);
        void Delete(string id);
    }
}

Bu örnek için depo uygulaması yalnızca özel bir öğe koleksiyonu kullanır:

using TodoAPI.Interfaces;
using TodoAPI.Models;

namespace TodoAPI.Services
{
    public class TodoRepository : ITodoRepository
    {
        private List<TodoItem> _todoList;

        public TodoRepository()
        {
            InitializeData();
        }

        public IEnumerable<TodoItem> All
        {
            get { return _todoList; }
        }

        public bool DoesItemExist(string id)
        {
            return _todoList.Any(item => item.ID == id);
        }

        public TodoItem Find(string id)
        {
            return _todoList.FirstOrDefault(item => item.ID == id);
        }

        public void Insert(TodoItem item)
        {
            _todoList.Add(item);
        }

        public void Update(TodoItem item)
        {
            var todoItem = this.Find(item.ID);
            var index = _todoList.IndexOf(todoItem);
            _todoList.RemoveAt(index);
            _todoList.Insert(index, item);
        }

        public void Delete(string id)
        {
            _todoList.Remove(this.Find(id));
        }

        private void InitializeData()
        {
            _todoList = new List<TodoItem>();

            var todoItem1 = new TodoItem
            {
                ID = "6bb8a868-dba1-4f1a-93b7-24ebce87e243",
                Name = "Learn app development",
                Notes = "Take Microsoft Learn Courses",
                Done = true
            };

            var todoItem2 = new TodoItem
            {
                ID = "b94afb54-a1cb-4313-8af3-b7511551b33b",
                Name = "Develop apps",
                Notes = "Use Visual Studio and Visual Studio Code",
                Done = false
            };

            var todoItem3 = new TodoItem
            {
                ID = "ecfa6f80-3671-4911-aabe-63cc442c1ecf",
                Name = "Publish apps",
                Notes = "All app stores",
                Done = false,
            };

            _todoList.Add(todoItem1);
            _todoList.Add(todoItem2);
            _todoList.Add(todoItem3);
        }
    }
}

Program.cs içinde uygulamanın yapılandırmasını yapın.

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddSingleton<TodoAPI.Interfaces.ITodoRepository, TodoAPI.Services.TodoRepository>();
builder.Services.AddControllers();

var app = builder.Build();

// Configure the HTTP request pipeline.

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Denetleyici Oluşturma

Projeye todoItemsController adlı yeni bir denetleyici ekleyin. öğesinden ControllerBasedevralmalıdır. Denetleyicinin ile Routebaşlayan yollara yapılan istekleri işlediğini belirtmek için bir api/todoitems öznitelik ekleyin. [controller] Yoldaki belirteç, denetleyicinin adıyla değiştirilir (sonek atlanırController) ve özellikle genel yollar için yararlıdır. Yönlendirme hakkında daha fazla bilgi edinin.

Denetleyicinin çalışabilmesi için bir ITodoRepository gereklidir. Bu tür bir örneği denetleyicinin oluşturucusu vasıtasıyla isteyin. Çalışma zamanında bu örnek, çerçevenin bağımlılık ekleme desteğiyle sağlanır.

[ApiController]
[Route("api/[controller]")]
public class TodoItemsController : ControllerBase
{
    private readonly ITodoRepository _todoRepository;

    public TodoItemsController(ITodoRepository todoRepository)
    {
        _todoRepository = todoRepository;
    }

Bu API, veri kaynağında CRUD (Oluşturma, Okuma, Güncelleştirme, Silme) işlemlerini gerçekleştirmek için dört farklı HTTP fiilini destekler. Bunların en basiti, http GET isteğine karşılık gelen Okuma işlemidir.

Curl kullanarak API'yi test edin

API yöntemini çeşitli araçları kullanarak test edebilirsiniz. Bu ders için aşağıdaki açık kaynak komut satırı tabanlı araçlar kullanılır.

  • curl: HTTP ve HTTPS gibi çeşitli protokolleri kullanarak verileri aktarır. curl, bu öğreticide, , GETPOSTve PUTHTTP yöntemlerini DELETEkullanarak API'yi çağırmak için kullanılır.
  • jq: API yanıtından kolayca okunabilmesi için JSON verilerini biçimlendirmek için bu öğreticide kullanılan bir JSON işlemcisi.

Curl ve jq yükleme

curl, macOS'a önceden yüklenmiştir ve doğrudan macOS Terminal uygulamasında kullanılır. Curl yükleme hakkında daha fazla bilgi için resmi curl web sitesine bakın.

jq, terminalden Homebrew'dan yüklenebilir:

Homebrew'u, henüz yüklü değilse aşağıdaki komutla yükleyin:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Yükleyici tarafından sunulan yönergeleri izleyin.

Aşağıdaki komutla Homebrew kullanarak jq yükleyin:

brew install jq

Homebrew ve jq yüklemesi hakkında daha fazla bilgi için bkz . Homebrew ve jq.

Öğeleri okumak

Öğe listesi isteğinde bulunmak, yöntemine List yönelik get isteğiyle gerçekleştirilir. [HttpGet] yöntemindeki List özniteliği, bu eylemin yalnızca GET isteklerini işlemesi gerektiğini gösterir. Bu eylemin yolu, denetleyicide belirtilen yoldur. Yolun bir parçası olarak eylem adını kullanmanız gerekmez. Her eylemin benzersiz ve kesin bir yolu olduğundan emin olmanız yeterlidir. Yönlendirme öznitelikleri, belirli yolları oluşturmak için hem denetleyici hem de yöntem düzeylerinde uygulanabilir.

[HttpGet]
public IActionResult List()
{
    return Ok(_todoRepository.All);
}

Terminalde aşağıdaki curl komutunu çağırın:

curl -v -X GET 'https://localhost:5001/api/todoitems/' | jq

Önceki curl komutu aşağıdaki bileşenleri içerir:

  • -v: AYRıNTıLı modu etkinleştirerek HTTP yanıtı hakkında ayrıntılı bilgi sağlar ve API testi ve sorun giderme için kullanışlıdır.
  • -X GET: İstek için HTTP GET yönteminin kullanımını belirtir. Curl genellikle hedeflenen HTTP yöntemini çıkarsasa da, bu seçenek bunu açık hale getirir.
  • 'https://localhost:5001/api/todoitems/': Bu, isteğin hedef URL'sidir. Bu örnekte bir API uç noktasıdır REST .
  • | jq: Bu segment doğrudan curl ile ilgili değildir. Kanal | , sol tarafındaki komuttan çıkışı alan ve bunu sağındaki komuta "kanal" eden bir kabuk işlecidir. jq bir komut satırı JSON işlemcidir. Gerekli olmasa da, jq döndürülen JSON verilerinin okunmasını kolaylaştırır.

List yöntemi, JSON olarak seri hale getirilmiş 200 Ok yanıt kodunu ve tüm Todo öğelerini döndürür:

[
  {
    "id": "6bb8a868-dba1-4f1a-93b7-24ebce87e243",
    "name": "Learn app development",
    "notes": "Take Microsoft Learn Courses",
    "done": true
  },
  {
    "id": "b94afb54-a1cb-4313-8af3-b7511551b33b",
    "name": "Develop apps",
    "notes": "Use Visual Studio and Visual Studio Code",
    "done": false
  },
  {
    "id": "ecfa6f80-3671-4911-aabe-63cc442c1ecf",
    "name": "Publish apps",
    "notes": "All app stores",
    "done": false
  }
]

Öğe oluşturma

Kural gereği, yeni veri öğeleri oluşturma IŞLEMI HTTP POST fiiline eşlenir. Create yöntemine [HttpPost] bir öznitelik uygulanmış ve TodoItem bir örneği kabul eder. POST gövdesinde geçilen item bağımsız değişkeni nedeniyle, bu parametre [FromBody] özniteliğini belirtir.

Metot içerisinde, öğenin geçerliliği ve veri deposunda önceden var olup olmadığı kontrol edilir ve herhangi bir sorun olmadığı takdirde, öğe depoya depo kullanılarak eklenir. Kontrol ModelState.IsValid, model doğrulama gerçekleştirir ve kullanıcı girişini kabul eden her API yönteminde yapılmalıdır.

[HttpPost]
public IActionResult Create([FromBody]TodoItem item)
{
    try
    {
        if (item == null || !ModelState.IsValid)
        {
            return BadRequest(ErrorCode.TodoItemNameAndNotesRequired.ToString());
        }
        bool itemExists = _todoRepository.DoesItemExist(item.ID);
        if (itemExists)
        {
            return StatusCode(StatusCodes.Status409Conflict, ErrorCode.TodoItemIDInUse.ToString());
        }
        _todoRepository.Insert(item);
    }
    catch (Exception)
    {
        return BadRequest(ErrorCode.CouldNotCreateItem.ToString());
    }
    return Ok(item);
}

Örnek, mobil istemciye geçirilen hata kodlarını içeren bir enum öğesi kullanır.

public enum ErrorCode
{
    TodoItemNameAndNotesRequired,
    TodoItemIDInUse,
    RecordNotFound,
    CouldNotCreateItem,
    CouldNotUpdateItem,
    CouldNotDeleteItem
}

Terminalde, POST fiilini kullanarak aşağıdaki curl komutunu çağırın ve isteğin gövdesinde yeni nesneyi JSON formatında sağlayarak yeni öğeler eklemeyi test edin.

curl -v -X POST 'https://localhost:5001/api/todoitems/' \
--header 'Content-Type: application/json' \
--data '{
  "id": "6bb8b868-dba1-4f1a-93b7-24ebce87e243",
  "name": "A Test Item",
  "notes": "asdf",
  "done": false
}' | jq

Önceki curl komutu aşağıdaki seçenekleri içerir:

  • --header 'Content-Type: application/json': üst bilgisini Content-Typeolarak ayarlar application/json ve istek gövdesinin JSON verileri içerdiğini belirtir.
  • --data '{...}': belirtilen verileri istek gövdesine gönderir.

yöntemi yanıtta yeni oluşturulan öğeyi döndürür.

Öğeleri güncelleştirme

Kayıtların değiştirilmesi, HTTP PUT istekleri kullanılarak sağlanır. Bu değişiklik dışında, Edit yöntemi neredeyse ile Createaynıdır. Kayıt bulunamazsa, Edit eylem bir NotFound (404) yanıtı döndürür.

[HttpPut]
public IActionResult Edit([FromBody] TodoItem item)
{
    try
    {
        if (item == null || !ModelState.IsValid)
        {
            return BadRequest(ErrorCode.TodoItemNameAndNotesRequired.ToString());
        }
        var existingItem = _todoRepository.Find(item.ID);
        if (existingItem == null)
        {
            return NotFound(ErrorCode.RecordNotFound.ToString());
        }
        _todoRepository.Update(item);
    }
    catch (Exception)
    {
        return BadRequest(ErrorCode.CouldNotUpdateItem.ToString());
    }
    return NoContent();
}

Curl ile test etmek için fiili PUT olarak değiştirin. İsteğin Gövdesinde güncelleştirilmiş nesne verilerini belirtin.

curl -v -X PUT 'https://localhost:5001/api/todoitems/' \
--header 'Content-Type: application/json' \
--data '{
  "id": "6bb8b868-dba1-4f1a-93b7-24ebce87e243",
  "name": "A Test Item",
  "notes": "asdf",
  "done": true
}' | jq

Bu yöntem, önceden var olan API ile tutarlılık için başarılı olduğunda bir NoContent (204) yanıt döndürür.

Öğeleri silme

Kayıtları silme işlemi hizmete istek gönderilerek DELETE ve silinecek öğenin kimliği geçirilerek gerçekleştirilir. Güncelleştirmelerde olduğu gibi, var olmayan öğelere yönelik istekler yanıt alır NotFound . Aksi takdirde, başarılı bir istek 204 (NoContent) yanıtı döndürür.

[HttpDelete("{id}")]
public IActionResult Delete(string id)
{
    try
    {
        var item = _todoRepository.Find(id);
        if (item == null)
        {
            return NotFound(ErrorCode.RecordNotFound.ToString());
        }
        _todoRepository.Delete(id);
    }
    catch (Exception)
    {
        return BadRequest(ErrorCode.CouldNotDeleteItem.ToString());
    }
    return NoContent();
}

HTTP fiilini DELETE olarak değiştirip URL'nin sonunda silinecek veri nesnesinin kimliğini ekleyerek curl ile test edin. Talep Gövdesinde hiçbir şey gerekli değil.

curl -v -X DELETE 'https://localhost:5001/api/todoitems/6bb8b868-dba1-4f1a-93b7-24ebce87e243'

Aşırı paylaşımı engelle

Şu anda örnek uygulama tüm TodoItem nesneyi kullanıma sunar. Üretim uygulamaları genellikle modelin bir alt kümesi kullanılarak giriş ve döndürülen verileri sınırlar. Bunun arkasında birden çok neden vardır ve güvenlik önemli bir nedendir. Modelin alt kümesi genellikle Veri Aktarım Nesnesi (DTO), giriş modeli veya görünüm modeli olarak adlandırılır. DTO bu makalede kullanılmıştır.

DTO, şu durumlarda kullanılabilir:

  • Fazla göndermeyi engelle.
  • İstemcilerin görüntülememesi gereken özellikleri gizleyin.
  • Yük boyutunu küçültmek için bazı özellikleri atlar.
  • İç içe nesneler içeren nesne grafiklerini düzleştirme. Düzleştirilmiş nesne grafikleri istemciler için daha kullanışlı olabilir.

DTO yaklaşımını göstermek için bkz . Fazla göndermeyi engelleme

Yaygın Web API'leri kuralları

Uygulamanız için arka uç hizmetlerini geliştirirken, çapraz kesme sorunlarını ele almak için tutarlı bir dizi kural veya ilke bulmak isteyeceksiniz. Örneğin, daha önce gösterilen hizmette, bulunamamış belirli kayıtlar için istekler NotFound yanıtı yerine bir BadRequest yanıtı aldı. Benzer şekilde, bu hizmete iletilen ve modele bağlı türlerde girilmiş komutlar her zaman denetlendi ve geçersiz model türleri için bir ModelState.IsValid döndürüldü.

API'leriniz için ortak bir ilke belirledikten sonra, bunu genellikle bir filtrede kapsülleyebilirsiniz. ASP.NET Core MVC uygulamalarında yaygın API ilkelerini kapsülleme hakkında daha fazla bilgi edinin.

Ayrıca bkz.