Vytváření back-end služeb pro nativní mobilní aplikace s ASP.NET Core

Od James Montemagno

mobilní aplikace můžou komunikovat s ASP.NET Core službami back-endu. pokyny k připojení místních webových služeb od simulátorů ios a emulátorů androidu najdete v tématu Připojení místních webových služeb z simulátorů ios a emulátorů androidu.

Zobrazit nebo stáhnout ukázkový kód back-end služeb

Ukázková nativní mobilní aplikace

tento kurz ukazuje, jak vytvořit back-end služby pomocí ASP.NET Core pro podporu nativních mobilních aplikací. Používá aplikaci Xamarin. Forms TodoRest jako nativního klienta, který zahrnuje samostatné nativní klienty pro Android, iOS a Windows. Můžete postupovat podle propojeného kurzu a vytvořit nativní aplikaci (a nainstalovat potřebné bezplatné nástroje Xamarin) a stáhnout ukázkové řešení Xamarin. ukázka Xamarin obsahuje projekt služeb ASP.NET Core Web API, který ASP.NET Core aplikace tohoto článku nahrazuje (bez jakýchkoli změn, které klient nevyžaduje).

To Do Aplikace REST běžící na telefonu s Androidem

Funkce

Aplikace TodoREST podporuje výpis, přidávání, odstraňování a aktualizaci položek To-Do. Každá položka má ID, název, poznámky a vlastnost, která označuje, zda byla provedena ještě předtím.

Hlavní zobrazení položek, jak je uvedeno výše, uvádí název každé položky a označuje, zda se značka zaškrtne.

Klepnutím na + ikonu se otevře dialogové okno Přidat položku:

Dialogové okno Přidat položku

Klepnutím na položku na obrazovce hlavní seznam se otevře dialogové okno pro úpravy, ve kterém můžete upravit název položky, poznámky a hotové nastavení, nebo můžete položku odstranit:

Dialogové okno Upravit položku

pokud si ji chcete vyzkoušet sami s aplikací ASP.NET Core vytvořenou v další části běžící na vašem počítači, aktualizujte RestUrl konstantu aplikace.

Emulátory Androidu se na místním počítači nespouštějí a ke komunikaci s místním počítačem použijte IP adresu zpětné smyčky (10.0.2.2). Využijte Xamarin. Essentials DeviceInfo k detekci, na které operační systém běží, aby používal správnou adresu URL.

Přejděte do TodoREST projektu a otevřete Constants.cs soubor. Soubor konstanty. cs obsahuje následující konfiguraci.

using Xamarin.Essentials;
using Xamarin.Forms;

namespace TodoREST
{
    public static class Constants
    {
        // URL of REST service
        //public static string RestUrl = "https://YOURPROJECT.azurewebsites.net:8081/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 RestUrl = DeviceInfo.Platform == DevicePlatform.Android ? "http://10.0.2.2:5000/api/todoitems/{0}" : "http://localhost:5000/api/todoitems/{0}";
    }
}

Volitelně můžete nasadit webovou službu do cloudové služby, jako je Azure, a aktualizovat RestUrl .

vytváření ASP.NET Core Project

vytvoří novou ASP.NET Core webovou aplikaci v Visual Studio. Vyberte šablonu webové rozhraní API. Pojmenujte projekt TodoAPI.

dialogové okno nový ASP.NET webové aplikace s vybraným šablonou projektu webového rozhraní API

Aplikace by měla reagovat na všechny požadavky na port 5000, včetně přenosů http nešifrovaných textů pro náš mobilní klient. Aktualizujte Startup. cs , takže UseHttpsRedirection neběží ve vývoji:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        // For mobile apps, allow http traffic.
        app.UseHttpsRedirection();
    }

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

Poznámka

Spusťte aplikaci přímo místo za IIS Express. IIS Express ignoruje nemístní požadavky ve výchozím nastavení. spusťte příkaz dotnet run z příkazového řádku nebo vyberte profil název aplikace z rozevíracího seznamu cíl ladění na panelu nástrojů Visual Studio.

Přidejte třídu modelu představující To-Do položky. Označte povinná pole s [Required] atributem:

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; }
    }
}

Metody rozhraní API vyžadují nějaký způsob, jak pracovat s daty. Použijte stejné ITodoRepository rozhraní, jaké používá původní ukázka Xamarin:

using System.Collections.Generic;
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);
    }
}

Pro tuto ukázku implementace používá pouze soukromou kolekci položek:

using System.Collections.Generic;
using System.Linq;
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 for Mac",
                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);
        }
    }
}

Konfigurace implementace při spuštění. cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<ITodoRepository, TodoRepository>();
    services.AddControllers();
}

Vytváření kontroleru

Přidejte do projektu nový kontroler, TodoItemsController. Měl by dědit z ControllerBase . Přidejte Route atribut, který označuje, že kontroler zpracuje požadavky provedené na cesty začínající na api/todoitems . [controller]Token v trase je nahrazen názvem kontroleru (vynechání Controller přípony) a je zvláště užitečný pro globální trasy. Přečtěte si další informace o Směrování.

Kontroler vyžaduje ITodoRepository funkci. požádejte o instanci tohoto typu prostřednictvím konstruktoru kontroleru. Za běhu se tato instance poskytne s použitím podpory rozhraní pro vkládání závislostí.

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

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

Toto rozhraní API podporuje čtyři různé příkazy HTTP pro provádění operací CRUD (vytvoření, čtení, aktualizace, odstranění) na zdroji dat. Nejjednodušší z nich je operace čtení, která odpovídá požadavku HTTP GET.

Čtení položek

Požadavek na seznam položek se provádí s požadavkem GET na List metodu. [HttpGet]Atribut List metody označuje, že by tato akce měla zpracovat pouze požadavky GET. Trasa pro tuto akci je trasa určená na řadiči. Nemusíte nutně použít název akce jako součást trasy. Stačí, abyste zajistili, že každá akce má jedinečnou a jednoznačnou trasu. Atributy směrování lze použít jak na úrovni kontroléru, tak na úrovni metody pro sestavování specifických tras.

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

ListMetoda vrátí kód odpovědi 200 OK a všechny položky ToDo serializované jako JSON.

Novou metodu rozhraní API můžete otestovat pomocí nejrůznějších nástrojů, jako je například post, jak je znázorněno zde:

Dodatečná konzola ukazující požadavek GET pro TodoItems a tělo odpovědi zobrazující JSON pro tři vrácené položky

Vytváření položek

Podle konvence je vytváření nových datových položek mapováno na operaci HTTP POST. V Create metodě je [HttpPost] použit atribut a je přijímána TodoItem instance. Vzhledem k item tomu, že argument je předán v těle příspěvku, tento parametr určuje [FromBody] atribut.

V rámci metody je položka kontrolována platnosti a předchozí existence v úložišti dat, a pokud nedojde k žádnému problému, bude přidána pomocí úložiště. Kontrola ModelState.IsValid provede ověření modelua měla by se provést v každé metodě rozhraní API, která přijímá vstup uživatele.

[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);
}

Ukázka používá enum obsahující chybové kódy, které jsou předány mobilnímu klientovi:

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

Otestujte přidáním nových položek pomocí příkazu post tak, že vyberete příkaz POST, který poskytuje nový objekt ve formátu JSON v těle požadavku. Měli byste také přidat hlavičku požadavku určující a Content-Type application/json .

Dodatečná konzola ukazující příspěvek a odpověď

Metoda vrátí nově vytvořenou položku v odpovědi.

Aktualizace položek

Změny záznamů se provádí pomocí požadavků HTTP PUT. Kromě této změny Edit je metoda skoro shodná s Create . Všimněte si, že pokud se záznam nenajde, Edit akce vrátí NotFound odpověď (404).

[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();
}

Chcete-li testovat pomocí metody post, změňte operaci na PUT. Zadejte data aktualizovaných objektů v těle žádosti.

Dodatečná konzola ukazující vložení a odpověď

Tato metoda vrátí NoContent odpověď (204), pokud je úspěšná, kvůli konzistenci s dříve existujícím rozhraním API.

Odstraňování položek

Odstranění záznamů je provedeno tím, že se do služby vyžádají žádosti o odstranění a předáte ID položky, která se má odstranit. Stejně jako u aktualizací jsou požadavky na položky, které neexistují, přijímat NotFound odpovědi. V opačném případě bude úspěšná žádost dostávat NoContent odpověď (204).

[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();
}

Všimněte si, že při testování funkce odstranění není v těle žádosti nic nutné.

Konzola pro publikování ukazující odstranění a odpověď

Zabránit navýšení příspěvků

V současné době ukázková aplikace zveřejňuje celý TodoItem objekt. Produkční aplikace obvykle omezují zadaná data a vracejí je pomocí podmnožiny modelu. Je to několik důvodů na pozadí a zabezpečení je hlavní. Podmnožina modelu je obvykle označována jako objekt Přenos dat (DTO), vstupní model nebo model zobrazení. DTO se používá v tomto článku.

DTO se dá použít k těmto akcím:

  • Zabránit přeúčtování.
  • Skrytí vlastností, které klienti nemají zobrazovat.
  • Vynechejte některé vlastnosti, aby se snížila velikost datové části.
  • Ploché grafy objektů, které obsahují vnořené objekty. Ploché grafy objektů můžou být pro klienty pohodlnější.

Pokud chcete předvést přístup založený na DTO, podívejte se na článek Prevence přeúčtování.

Běžné konvence webového rozhraní API

Při vývoji back-endových služeb pro vaši aplikaci budete chtít vytvořit konzistentní sadu konvencí nebo zásad pro řešení průřezových problémů. Například ve výše uvedené službě požadavky na konkrétní záznamy, které se nenašly, dostaly odpověď NotFound místo BadRequest odpovědi. Podobně příkazy provedené této službě, které byly předány v modelem vázaných typech, vždy zkontrolovaly a vrátily ModelState.IsValid pro BadRequest neplatné typy modelu.

Jakmile pro rozhraní API najdete společnou zásadu, můžete ji obvykle zapouzdřit do filtru. Další informace o zapouzdření běžných zásad rozhraní API v ASP.NET Core MVC.

Další zdroje informací