ASP.NET Core: Создание серверных служб для мобильных приложений

в 8:56, , рубрики: .net, android, api, ASP, ASP.NET, asp.net core, ASP.NET Core Web Application, C#, c#.net, http, iOS, microsoft, msaspnetcore, SDK, Visual Studio, web-application, web-разработка, windows, xamarin, Блог компании Microsoft, веб-службы, мобильная разработка, разработка мобильных приложений, руководство, руководство для разработчика

Представляем вторую часть из серии статей, посвящённых разработке на ASP.NET Core. В этом обучающем материале вы узнаете, как создавать серверные службы с помощью ASP.NET Core MVC для поддержки мобильных приложений.

ASP.NET Core: Создание серверных служб для мобильных приложений - 1

Второй цикл статей по 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 из этой статьи (со стороны клиента изменения не понадобятся).

ASP.NET Core: Создание серверных служб для мобильных приложений - 2

Функции

Приложение ToDoRest поддерживает составление списков, добавление, удаление и обновление элементов To-Do. Каждый элемент наделён своим идентификатором, названием, примечаниями и свойством, которое указывает, выполнен ли элемент.

В основном представлении элементов, как показано выше, имеется название каждого элемента, а наличие флажка указывает, был ли он выполнен.

Коснитесь значка +, чтобы открыть диалоговое окно для добавления элементов:

ASP.NET Core: Создание серверных служб для мобильных приложений - 3

Коснитесь элемента в главном списке, чтобы открыть диалоговое окно для редактирования названия, примечания и статуса выполнения, либо чтобы удалить элемент:

ASP.NET Core: Создание серверных служб для мобильных приложений - 4

Этот образец по умолчанию использует сервисные службы, размещённые по адресу 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.

ASP.NET Core: Создание серверных служб для мобильных приложений - 5

Приложение должно отвечать на все запросы к порту 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 framework services.
    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, как показано ниже:

ASP.NET Core: Создание серверных служб для мобильных приложений - 6

Создание элементов

По соглашению, создание новых элементов данных сопоставляется с командой 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.

ASP.NET Core: Создание серверных служб для мобильных приложений - 7

В ответе метод выдает только что созданный элемент.

Обновление элементов

Изменять записи можно с помощью запросов 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. Укажите данные обновляемого объекта в теле запроса.

ASP.NET Core: Создание серверных служб для мобильных приложений - 8

При успешном выполнении метод выдает ответ 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();
}

Помните, что при тестировании функции удаления в тело запроса добавлять ничего не нужно.

ASP.NET Core: Создание серверных служб для мобильных приложений - 9

Распространенные соглашения веб-API

При разработке серверных служб для приложения рекомендуем создать ряд логичных соглашений или политик для разрешения возникающих вопросов. Например, в описанных выше службах запросы для конкретных записей, которые не были найдены, получили ответ NotFound, а не BadRequest. Аналогично, команды, выполненные в адрес этой службы и переданные в типах модели, всегда проверяли ModelState.IsValid и выдавали BadRequest для недействительных типов моделей.

Когда вы определите общую политику для своих API, то можете выполнить инкапсуляцию в фильтре. В этой статьей можно узнать, как инкапсулировать общие политики API в приложениях ASP.NET Core MVC.

Автор: Microsoft

Источник

Поделиться

* - обязательные к заполнению поля