ASP.NET Core: Створення серверних служб для мобільних додатків

Представляємо другу частину серії статей, присвячених розробці на ASP.NET Core. У цьому навчальному матеріалі ви дізнаєтеся, як створювати серверні служби за допомогою ASP.NET Core MVC для підтримки мобільних додатків.


Другий цикл статей по ASP.NET Core
  1. Створення серверних служб для мобільних додатків.
  2. Розробка додатків ASP.NET Core за допомогою dotnet watch.
  3. Створення сторінок веб-API ASP.NET з допомогою Swagger.
  4. Відкритий веб-інтерфейс для .NET (OWIN).
  5. Вибір правильної середовища розробки .NET на сервері.
Перший цикл статей можна знайти на тут.
Зразок мобільного додатка
Мобільні додатки можуть легко обмінюватися даними з фонових служб ASP.NET Core. Здесь можна завантажити зразок коду серверних служб.
В даному матеріалі в якості клієнта використовується додаток Xamarin Forms ToDoRest. Воно включає окремі клієнти для пристроїв під Android, iOS і Windows. За посиланням вище ви знайдете керівництво, яке допоможе створити додаток (і встановити необхідні безкоштовні інструменти Xamarin), а також зможете скачати зразок рішення Xamarin. У нього входить проект двох служб ASP.NET веб-API, на заміну яким приходить додаток ASP.NET Core підставі цієї статті (зі сторони клієнта зміни не знадобляться).



Додаток ToDoRest підтримує складання списків, додавання, видалення і оновлення елементів To-Do. Кожен елемент наділений своїм ідентифікатором, назвою, примітками і властивістю, яке вказує, чи виконаний елемент.
В основному поданні елементів, як показано вище, є назва кожного елемента, а прапорець вказує чи був він виконаний.
Торкніться значка +, щоб відкрити діалогове вікно для додавання елементів:

Торкніться елемента в головному списку, щоб відкрити діалогове вікно для редагування назви, примітки і статусу виконання, або щоб видалити елемент:

Цей зразок за замовчуванням використовує сервісні служби, розміщені за адресою developer.xamarin.com, і дозволяє виконувати тільки читання. Щоб самостійно протестувати його з додатком ASP.NET Core, яке буде створено в наступному розділі і буде працювати на вашому комп'ютері, потрібно оновити константу
RestUrl
. Перейдіть до проекту
ToDoREST
і відкрийте файл Constants.cs. Замініть
RestUrl
на IP-адресу вашого комп'ютера (це не повинен бути localhost або 127.0.0.1, оскільки адресу використовується з емулятора пристрою, а не з вашого ПК). Також додайте номер порту (5000). Щоб служби працювали на пристрої, не забудьте вимкнути брандмауер, що блокує доступ до цього порту.
// URL of REST service (Xamarin ReadOnly Service)
//public static string RestUrl = "http://developer.xamarin.com:8081/api/todoitems{0}";

// use your machine's IP address
public static string RestUrl = "http://192.168.1.207:5000/api/todoitems/{0}";

Створення проекту ASP.NET Core
Створити новий веб-застосунок ASP.NET Core Visual Studio. Виберіть шаблон веб-API і вимкніть аутентифікацію. Назвіть проектом ім'я ToDoApi.

Додаток повинен відповідати на всі запити до порту 5000. Додайте Program.cs
.UseUrls("http://*:5000")
, щоб отримати наступний результат:
var host = new WebHostBuilder()
.UseKestrel()
.UseUrls("http://*:5000")
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();

Примітка: обов'язково запустіть додаток безпосередньо, а не через IIS Express, який за замовчуванням ігнорує не локальні запити. Виконайте
dotnet run
з командного рядка або виберіть назву програми з розкривного меню Debug Target на панелі інструментів Visual Studio.
Додайте клас моделі для представлення елементів To-Do. Відзначте обов'язкові поля за допомогою атрибута
[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; }
}
}

Методам API необхідний спосіб обробки даних. Використовуйте той же інтерфейс
IToDoRepository
, що і в зразку 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);
}
}

У цьому прикладі при реалізації використовується приватна колекція елементів:
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 = "Attend Xamarin University",
Done = true
};

var todoItem2 = new ToDoItem
{
ID = "b94afb54-a1cb-4313-8af3-b7511551b33b",
Name = "Develop apps",
Notes = "Use Xamarin Studio/Visual Studio",
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);
}
}
}

Налаштуйте реалізацію Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
// Add services framework.
services.AddMvc();

services.AddSingleton<IToDoRepository,ToDoRepository>();
}

Тепер можна перейти до створення ToDoItemsController.
Детальніше про створення веб-API можна дізнатися в статті «Створення першого веб-API з використанням ASP.NET Core MVC і Visual Studio.
Створення контролера
Додайте до проекту новий контролер ToDoItemsController. Він має успадкувати властивості від Microsoft.AspNetCore.Mvc.Controller. Додайте атрибут
Route
, щоб вказати, що контролер обробляє запити, які виконані до шляхів і починаються з
api/todoitems
. Токен
[controller]
в маршруті замінюється назвою контролера (без суфікса Controller); це особливо корисно для глобальних маршрутів. Детальніше про маршрутизації.
Для роботи контролера необхідний параметр
IToDoRepository;
запросіть примірник цього типу через конструктор контролера. В середовищі виконання цей екземпляр буде надана завдяки підтримці платформи для впровадження залежності.
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using ToDoApi.Interfaces;
using ToDoApi.Models;

namespace ToDoApi.Controllers
{
[Route("api/[controller]")]
public class ToDoItemsController : Controller
{
private readonly IToDoRepository _toDoRepository;

public ToDoItemsController(IToDoRepository toDoRepository)
{
_toDoRepository = toDoRepository;
}

Цей API підтримує чотири команди HTTP для операцій створення, читання, оновлення та видалення (CRUD) у джерелі даних. Найпростіша операція — Read (читання), вона відповідає запиту HTTP Get.
Читання елементів
Щоб запросити список елементів, виконайте запит GET до методу
List
. Атрибут
[HttpGet]
в методі
List
вказує, що це дія повинна обробляти тільки запити GET. Маршрут для цієї дії — це маршрут, зазначений на контролері. Вам не обов'язково використовувати назву дії в якості частини маршруту. Потрібно лише переконатися, що кожна дія має унікальним і однозначним маршрутом. Маршрутизацію атрибутів для створення конкретних маршрутів можна застосовувати на рівні як контролера, так і методу.
[HttpGet]
public IActionResult List()
{
return Ok(_toDoRepository.All);
}

Метод
List
видає код відповіді 200 OK і список всіх елементів ToDo, серіалізовать як JSON.
Ви можете протестувати новий метод API за допомогою низки інструментів, наприклад Postman, як показано нижче:

Створення елементів
За угодою, створення нових елементів даних зіставляється з командою HTTP POST. До методу
Create
застосований атрибут
[HttpPost];
крім того, метод приймає параметр ID примірник
ToDoItem
. Такі командні атрибути, як
[HttpPost]
, можуть прийняти рядок маршруту (у цьому прикладі
{id}
). Результат буде таким же, що і при додаванні атрибута
[Route]
до дії. Оскільки аргумент
item
буде переданий в тілі POST, цей параметр прикрашається атрибутом
[FromBody]
.
Всередині методу перевіряється, чи правильно складений елемент і чи існував він раніше в сховищі даних; якщо помилок немає, він додається за допомогою репозиторію.
ModelState.IsValid
виконує перевірку моделі; це слід зробити в кожному методі API, який приймає дані, що вводяться користувачем.
[HttpPost("{id}")]
public IActionResult Create(string id, [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);
}

У зразку використовується перерахування кодів помилок, переданих в мобільний клієнт.
public enum ErrorCode
{
TodoItemNameAndNotesRequired,
TodoItemIDInUse,
RecordNotFound,
CouldNotCreateItem,
CouldNotUpdateItem,
CouldNotDeleteItem
}

Щоб перевірити додавання нових елементів, використовуйте Postman: виберіть POST, яка надає новий об'єкт у форматі JSON в тілі запиту. Також додайте заголовок, який вказує
Content-Type
,
application/json
.

У відповіді метод видає тільки що створений елемент.
Оновлення елементів
Змінювати записи можна за допомогою запитів HTTP PUT. Крім того, метод
Edit
практично ідентичний
Create
. Пам'ятайте, що якщо запис не буде знайдена, дія
Edit
видасть відповідь
NotFound
(404).
[HttpPut("{id}")]
public IActionResult Edit(string id, [FromBody] ToDoItem item)
{
try
{
if (item == null || !ModelState.IsValid)
{
return BadRequest(ErrorCode.TodoItemNameAndNotesRequired.ToString());
}
var existingItem = _toDoRepository.Find(id);
if (existingItem == null)
{
return NotFound(ErrorCode.RecordNotFound.ToString());
}
_toDoRepository.Update(item);
}
catch (Exception)
{
return BadRequest(ErrorCode.CouldNotUpdateItem.ToString());
}
return NoContent();
}

Щоб протестувати Postman, змініть команду PUT і додайте ID оновлюваною записи в URL. Вкажіть дані оновлюваного об'єкта в тілі запиту.

При успішному виконанні метод видає відповідь
NoContent
(204), забезпечуючи тим самим узгодженість з існуючими API.
Видалення елементів
Для видалення записів потрібно зробити запити DELETE до сервісу і передати ID видаляється елемента. Після цих оновлень запити для неіснуючих елементів отримають відповіді
NotFound
, а успішний запит — відповідь
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();
}

Пам'ятайте, що при тестуванні функції видалення в тіло запиту додавати нічого не потрібно.


Поширені угоди веб-API
При розробці серверних служб для додатка рекомендуємо створити ряд логічних угод або політик для вирішення виникаючих питань. Наприклад, в описаних вище службах запити для конкретних записів, які не були знайдені, отримали відповідь
NotFound
, а не
BadRequest
. Аналогічно, команди, виконані в адресу цієї служби і передані в типах моделі, завжди перевіряли
ModelState.IsValid
і видавали
BadRequest
для недійсних типів моделей.
Коли ви визначите загальну політику для своїх API, то можете виконати інкапсуляцію у фільтрі. У цій статті можна дізнатися, як инкапсулировать політики API в додатках ASP.NET Core MVC.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.