Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Autor: James Montemagno
Aplikacje mobilne mogą komunikować się z usługami zaplecza ASP.NET Core. Aby uzyskać instrukcje dotyczące łączenia lokalnych usług sieci Web z symulatorów systemu iOS i emulatorów systemu Android, zobacz Connect to local web services from Android emulators and iOS simulators.
Wyświetlanie lub pobieranie przykładowego kodu usług zaplecza
Przykładowa natywna aplikacja mobilna
W tym samouczku pokazano, jak tworzyć usługi zaplecza przy użyciu platformy ASP.NET Core do obsługi natywnych aplikacji mobilnych. Używa aplikacji .NET MAUI jako swojego natywnego klienta. Przykład zawiera projekt usług ASP.NET Core Web API, który w tym artykule pokazuje, jak utworzyć.
aplikacja
Funkcje
Aplikacja TodoREST obsługuje wyświetlanie listy, dodawanie, usuwanie i aktualizowanie elementów zadań do wykonania. Każdy element ma identyfikator, nazwę, notatki i właściwość wskazującą, czy został już wykonany.
W poprzednim przykładzie główny widok elementów zawiera listę nazw każdego elementu i wskazuje, czy jest on ukończony za pomocą znacznika wyboru.
Naciśnięcie ikony +
powoduje przejście do strony dodawania elementu:
Naciśnięcie elementu na stronie głównej powoduje przejście do strony edycji, na której można zmodyfikować nazwę, notatki i gotowe ustawienia elementu lub element można usunąć:
Aby przetestować ją samodzielnie względem aplikacji ASP.NET Core utworzonej w następnej sekcji, jeśli hostujesz ją w trybie online, zaktualizuj stałą RestUrl
aplikacji. W przeciwnym razie aplikacja będzie komunikować się z aplikacją ASP.NET Core hostowaną lokalnie na maszynie.
Emulatory Android nie działają na maszynie lokalnej i używają adresu IP pętli zwrotnej (10.0.2.2), aby komunikować się z maszyną lokalną. Użyj klasy .NET MAUIDeviceInfo, aby wykryć system operacyjny, na którym działa aplikacja, aby użyć poprawnego adresu URL.
Przejdź do TodoREST
projektu i otwórz Constants.cs
plik. Plik Constants.cs
zawiera następującą konfigurację.
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}}";
}
}
Opcjonalnie możesz wdrożyć usługę internetową w usłudze w chmurze, takiej jak platforma Azure, i zaktualizować usługę RestUrl
.
Tworzenie projektu podstawowego ASP.NET
Utwórz nową aplikację internetową ASP.NET Core w programie Visual Studio. Wybierz szablon internetowego interfejsu API. Nadaj projektowi nazwę TodoAPI.
Aplikacja powinna odpowiadać na wszystkie żądania wysyłane za pośrednictwem protokołu HTTPS do portu 5001.
Uwaga
Uruchom aplikację bezpośrednio, zamiast za pośrednictwem IIS Express. Usługa IIS Express domyślnie ignoruje żądania inne niż lokalne. Uruchom dotnet run z poziomu wiersza polecenia lub wybierz profil aplikacji z listy rozwijanej celu debugowania na pasku narzędzi programu Visual Studio.
Dodaj klasę modelu do reprezentowania elementów zadań do wykonania. Oznacz wymagane pola atrybutem [Required]
:
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 interfejsu API wymagają zdefiniowania, aby pracować z danymi. Użyj tego samego interfejsu ITodoRepository
, którego używa przykład.
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);
}
}
W tym przykładzie implementacja repozytorium używa tylko prywatnej kolekcji elementów:
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);
}
}
}
Skonfiguruj implementację w programie Program.cs
:
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();
Tworzenie kontrolera
Dodaj nowy kontroler do projektu TodoItemsController. Powinien dziedziczyć z ControllerBase.
Route
Dodaj atrybut wskazujący, że kontroler obsługuje żądania wysyłane do ścieżek rozpoczynających się od api/todoitems
. Token [controller]
w ścieżce jest zastępowany nazwą kontrolera (pomijając sufiks Controller
) i jest szczególnie przydatny w trasach globalnych. Dowiedz się więcej o routingu.
Kontroler wymaga ITodoRepository
do działania; żądaj utworzenia instancji tego typu za pośrednictwem konstruktora kontrolera. Podczas działania to wystąpienie jest udostępniane dzięki wsparciu platformy dla iniekcji zależności.
[ApiController]
[Route("api/[controller]")]
public class TodoItemsController : ControllerBase
{
private readonly ITodoRepository _todoRepository;
public TodoItemsController(ITodoRepository todoRepository)
{
_todoRepository = todoRepository;
}
Ten interfejs API obsługuje cztery różne czasowniki HTTP do wykonywania operacji CRUD (tworzenie, odczyt, aktualizacja, usuwanie) w źródle danych. Najprostszą z nich jest operacja Odczyt, która odpowiada żądaniu HTTP GET
.
Testowanie interfejsu API przy użyciu narzędzia curl
Metodę interfejsu API można przetestować przy użyciu różnych narzędzi. W tym samouczku są używane następujące narzędzia wiersza polecenia typu open source:
-
curl: transferuje dane przy użyciu różnych protokołów, w tym HTTP i HTTPS. Program curl jest używany w tym samouczku do wywoływania interfejsu API przy użyciu metod
GET
HTTP ,POST
,PUT
iDELETE
. - jq: procesor JSON używany w tym samouczku do formatowania danych JSON, dzięki czemu są łatwe do odczytania z odpowiedzi API.
Instalowanie narzędzia curl i jq
Program curl jest wstępnie zainstalowany w systemie macOS i jest używany bezpośrednio w aplikacji terminalu systemu macOS. Aby uzyskać więcej informacji na temat instalowania programu curl, zobacz oficjalną witrynę internetową curl.
Pakiet jq można zainstalować z poziomu oprogramowania Homebrew z poziomu terminalu:
Zainstaluj oprogramowanie Homebrew, jeśli jeszcze nie jest zainstalowane, za pomocą następującego polecenia:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Postępuj zgodnie z instrukcjami przedstawionymi przez instalatora.
Zainstaluj pakiet jq przy użyciu oprogramowania Homebrew za pomocą następującego polecenia:
brew install jq
Aby uzyskać więcej informacji na temat instalacji oprogramowania Homebrew i jq, zobacz Homebrew i jq.
Odczytywanie elementów
Żądanie listy elementów odbywa się za pomocą żądania GET do List
metody . Atrybut [HttpGet]
metody List
wskazuje, że ta akcja powinna obsługiwać tylko żądania GET. Trasa dla tej akcji to trasa określona na kontrolerze. Nie musisz używać nazwy akcji w ramach trasy. Wystarczy upewnić się, że każda akcja ma unikatową i jednoznaczną trasę. Atrybuty routingu można stosować zarówno na poziomie kontrolera, jak i metody w celu utworzenia określonych tras.
[HttpGet]
public IActionResult List()
{
return Ok(_todoRepository.All);
}
W terminalu wywołaj następujące polecenie curl:
curl -v -X GET 'https://localhost:5001/api/todoitems/' | jq
Poprzednie polecenie curl zawiera następujące składniki:
-
-v
: Aktywuje tryb szczegółowy, zapewniając szczegółowe informacje o odpowiedzi HTTP i jest przydatny do testowania API oraz rozwiązywania problemów. -
-X GET
: określa użycie metody HTTPGET
dla żądania. Chociaż narzędzie curl często może wywnioskować docelową metodę HTTP, ta opcja sprawia, że jest jawna. -
'https://localhost:5001/api/todoitems/'
: jest to docelowy adres URL żądania. W tym przypadku jest to punkt końcowy interfejsu REST API. -
| jq
: ten segment nie jest powiązany bezpośrednio z curl. Operator potokowy|
jest operatorem powłoki, który pobiera dane wyjściowe z polecenia po lewej stronie i przekazuje je do polecenia po prawej stronie.jq
jest procesorem JSON wiersza polecenia. Chociaż nie jest to wymagane,jq
zwracane dane JSON są łatwiejsze do odczytania.
Metoda List
zwraca kod odpowiedzi 200 OK i wszystkie elementy listy rzeczy do zrobienia w formacie JSON.
[
{
"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
}
]
Tworzenie elementów
Zgodnie z konwencją tworzenie nowych elementów danych przypisuje się czasownikowi HTTP POST
. Metoda Create
ma zastosowany atrybut [HttpPost]
i akceptuje wystąpienie TodoItem
.
item
Ponieważ argument jest przekazywany w treści POST-a, ten parametr określa [FromBody]
atrybut.
Wewnątrz metody element jest sprawdzany pod kątem ważności i wcześniejszego istnienia w magazynie danych, a jeśli nie wystąpią żadne problemy, zostanie dodany przy użyciu repozytorium. Sprawdzanie ModelState.IsValid
przeprowadza weryfikację modelu i powinno być wykonywane w każdej metodzie API, która akceptuje dane wejściowe użytkownika.
[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);
}
W przykładzie użyto enum
zawierających kody błędów, które są przekazywane do klienta mobilnego.
public enum ErrorCode
{
TodoItemNameAndNotesRequired,
TodoItemIDInUse,
RecordNotFound,
CouldNotCreateItem,
CouldNotUpdateItem,
CouldNotDeleteItem
}
W terminalu przetestuj dodawanie nowych elementów, wywołując następujące polecenie curl przy użyciu czasownika POST
i podając nowy obiekt w formacie JSON w treści żądania.
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
Poprzednie polecenie curl zawiera następujące opcje:
-
--header 'Content-Type: application/json'
: UstawiaContent-Type
nagłówek naapplication/json
, wskazując, że treść żądania zawiera dane JSON. -
--data '{...}'
: wysyła określone dane w treści żądania.
Metoda zwraca nowo utworzony element w odpowiedzi.
Aktualizowanie elementów
Modyfikowanie rekordów jest osiągane przy użyciu żądań PUT
HTTP. Poza tą zmianą metoda jest prawie identyczna Edit
z Create
. Jeśli rekord nie zostanie znaleziony, Edit
akcja zwróci NotFound
odpowiedź (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();
}
Aby przetestować polecenie curl, zmień czasownik na PUT
. Określ zaktualizowane dane obiektu w treści żądania.
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
Ta metoda zwraca odpowiedź NoContent
(204) w przypadku powodzenia, aby zapewnić spójność z istniejącym już wcześniej interfejsem API.
Usuwanie elementów
Usuwanie rekordów jest realizowane przez wykonywanie DELETE
żądań do usługi i przekazywanie identyfikatora elementu do usunięcia. Podobnie jak w przypadku aktualizacji, żądania dotyczące elementów, które nie istnieją, otrzymują NotFound
odpowiedzi. W przeciwnym razie pomyślne żądanie zwraca odpowiedź o kodzie NoContent
(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();
}
Przetestuj przy użyciu narzędzia curl, zmieniając czasownik HTTP na DELETE
i dołączając identyfikator obiektu danych, który chcesz usunąć, na końcu adresu URL. Treść żądania nie jest konieczna.
curl -v -X DELETE 'https://localhost:5001/api/todoitems/6bb8b868-dba1-4f1a-93b7-24ebce87e243'
Zapobieganie nadmiernemu publikowaniu
Obecnie przykładowa aplikacja uwidacznia cały TodoItem
obiekt. Aplikacje produkcyjne zwykle ograniczają dane wejściowe i zwracane przy użyciu podzestawu modelu. Istnieje wiele powodów, a jednym z głównych jest bezpieczeństwo. Podzbiór modelu jest zwykle nazywany obiektem transferu danych (DTO), modelem wejściowym lub modelem widoku.
DTO jest używane w tym artykule.
DTO może służyć do:
- Zapobiegaj nadmiernemu publikowaniu.
- Ukryj właściwości, których klienci nie powinni wyświetlać.
- Pomiń niektóre właściwości, aby zmniejszyć rozmiar ładunku.
- Spłaszczać grafy obiektów zawierające zagnieżdżone obiekty. Spłaszczone grafy obiektów mogą być wygodniejsze dla klientów.
Aby zademonstrować podejście DTO, zobacz Zapobieganie nadmiernemu przesyłaniu danych
Typowe konwencje internetowego interfejsu API
Podczas opracowywania usług zaplecza dla aplikacji, powinieneś ustalić spójny zestaw konwencji lub zasad dotyczących obsługi zagadnień przekrojowych. Na przykład w przedstawionej wcześniej usłudze żądania dotyczące określonych rekordów, które nie zostały znalezione, otrzymały odpowiedź NotFound
, zamiast odpowiedzi BadRequest
. Polecenia wysyłane do tej usługi, które dotyczyły typów powiązanych z modelem, zawsze sprawdzały ModelState.IsValid
i zwracały dla BadRequest
nieprawidłowych typów modeli.
Po zidentyfikowaniu typowych zasad dla interfejsów API można zwykle hermetyzować je w filtrze. Dowiedz się więcej o sposobie hermetyzacji typowych zasad interfejsu API w aplikacjach ASP.NET Core MVC.