Рейтинговые книги
Читем онлайн Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
id="id1543">

Вызов HTTP-метода PUT

Метод для обновления записи Car использует HTTP-метод PUT. Он применяет вспомогательный метод для отправки записи Car в формате JSON и возвращает обновленную запись Car из тела ответа:

public async Task<Car> UpdateCarAsync(int id, Car entity)

{

  var response = await PutAsJson($"{_settings.Uri}{_settings.CarBaseUri}/{id}",

    JsonSerializer.Serialize(entity));

  response.EnsureSuccessStatusCode();

  return await response.Content.ReadFromJsonAsync<Car>();

}

Вызов HTTP-метода DELETE

Последний добавляемый метод предназначен для выполнения НТТР-метода DELETE. Шаблон соответствует остальным методам: использование вспомогательного метода и проверка ответа на предмет успешности. Он ничего не возвращает вызывающему коду, поскольку сущность была удалена. Ниже показан код метода:

public async Task DeleteCarAsync(int id, Car entity)

{

  var response = await DeleteAsJson($"{_settings.Uri}{_settings.CarBaseUri}/{id}",

    JsonSerializer.Serialize(entity));

  response.EnsureSuccessStatusCode();

}

Конфигурирование служб

Создайте в каталоге ApiWrapper проекта AutoLot.Service новый файл класса по имени ServiceConfiguration.cs. Приведите операторы using к следующему виду:

using Microsoft.Extensions.Configuration;

using Microsoft.Extensions.DependencyInjection;

Сделайте класс открытым и статическим, после чего добавьте открытый статический расширяющий метод для IServiceCollection:

namespace AutoLot.Services.ApiWrapper

{

  public static class ServiceConfiguration

  {

     public static IServiceCollection ConfigureApiServiceWrapper(

         this IServiceCollection services, IConfiguration config)

    {

      return services;

    }

  }

}

В первой строке расширяющего метода в контейнер DI добавляется ApiServiceSettings. Во второй строке в контейнер DI добавляется IApiServiceWrapper и регистрируется класс с помощью фабрики HTTPClient. Это позволяет внедрять IApiServiceWrapper в другие классы, а фабрика HTTPClient будет управлять внедрением и временем существования HTTPClient:

public static IServiceCollection ConfigureApiServiceWrapper(this IServiceCollection

services, IConfiguration config)

{

  services.Configure<ApiServiceSettings>(

      config.GetSection(nameof(ApiServiceSettings)));

  services.AddHttpClient<IApiServiceWrapper,ApiServiceWrapper>();

  return services;

}

Откройте файл Startup.cs и добавьте следующий оператор using:

using AutoLot.Services.ApiWrapper;

Перейдите к методу ConfigureServices() и добавьте в него показанную ниже строку:

services.ConfigureApiServiceWrapper(Configuration);

Построение класса CarsController

Текущая версия CarsController жестко привязана к хранилищам в библиотеке доступа к данным. Следующая итерация CarsController для связи с базой данных будет применять оболочку службы. Переименуйте CarsController в CarsDalController (включая конструктор) и добавьте в каталог Controllers новый класс по имени CarsController. Код этого класса является практически точной копией CarsController, но они хранятся по отдельности с целью прояснения разницы между использованием хранилищ и службы.

На заметку! При работе с одной и той же базой данных вам редко придется применять вместе уровень доступа к данным и оболочку службы. Здесь показаны оба варианта, чтобы вы смогли решить, какой из них лучше подходит в вашей ситуации.

Приведите операторы using к следующему виду:

using System.Threading.Tasks;

using AutoLot.Dal.Repos.Interfaces;

using AutoLot.Models.Entities;

using AutoLot.Services.ApiWrapper;

using AutoLot.Services.Logging;

using Microsoft.AspNetCore.Mvc;

using Microsoft.AspNetCore.Mvc.Rendering;

Далее сделайте класс открытым, унаследуйте его от Controller и добавьте атрибут Route. Создайте конструктор, который принимает экземпляры реализаций IAutoLotServiceWrapper и IAppLogging, после чего присвойте оба экземпляра переменным уровня класса. Вот начальный код:

namespace AutoLot.Mvc.Controllers

{

[Route("[controller]/[action]")]

public class CarsController : Controller

{

  private readonly IApiServiceWrapper _serviceWrapper;

  private readonly IAppLogging<CarsController> _logging;

  public CarsController(IApiServiceWrapper serviceWrapper,

      IAppLogging<CarsController> logging)

  {

    _serviceWrapper = serviceWrapper;

    _logging = logging;

  }

}

Вспомогательный метод GetMakes()

Вспомогательный метод GetMakes() строит экземпляр SelectList со всеми записями Make в базе данных. Он использует Id в качестве значения и Name в качестве отображаемого текста:

internal async Task<SelectList> GetMakesAsync()=>

  new SelectList(

    await _serviceWrapper.GetMakesAsync(),

    nameof(Make.Id),

    nameof(Make.Name));

Вспомогательный метод GetOneCar()

Вспомогательный метод GetOneCar() получает одиночную запись Car:

internal async Task<Car> GetOneCarAsync(int? id)

  => !id.HasValue ? null : await _serviceWrapper.GetCarAsync(id.Value);

Открытые методы действий

Единственное отличие между открытыми методами действий в этом контроллере и аналогичными методами в CarsDalController связано с доступом к данным, а также с тем,что все методы определены как асинхронные. Поскольку вы уже понимаете, для чего предназначено то или иное действие, ниже приведены остальные методы, изменения в которых выделены полужирным:

[Route("/[controller]")]

[Route("/[controller]/[action]")]

public async Task<IActionResult> Index()

  => View(await _serviceWrapper.GetCarsAsync());

[HttpGet("{makeId}/{makeName}")]

public async Task<IActionResult> ByMake(int makeId, string makeName)

{

  ViewBag.MakeName = makeName;

  return View(await _serviceWrapper.GetCarsByMakeAsync(makeId));

}

[HttpGet("{id?}")]

public async Task<IActionResult> Details(int? id)

{

  if (!id.HasValue)

  {

    return BadRequest();

  }

  var car = await GetOneCarAsync(id);

  if (car == null)

  {

    return NotFound();

  }

  return View(car);

}

[HttpGet]

public async Task<IActionResult> Create()

{

  ViewData["MakeId"] = await GetMakesAsync();

  return View();

}

[HttpPost]

[ValidateAntiForgeryToken]

public async Task<IActionResult> Create(Car car)

{

  if (ModelState.IsValid)

  {

    await _serviceWrapper.AddCarAsync(car);

    return RedirectToAction(nameof(Index));

  }

  ViewData["MakeId"] = await GetMakesAsync();

  return View(car);

}

[HttpGet("{id?}")]

public async Task<IActionResult> Edit(int? id)

{

  var car = await GetOneCarAsync(id);

  if (car == null)

  {

    return NotFound();

  }

  ViewData["MakeId"] = await GetMakesAsync();

  return View(car);

}

[HttpPost("{id}")]

[ValidateAntiForgeryToken]

public async Task<IActionResult> Edit(int id, Car car)

{

  if (id != car.Id)

  {

    return BadRequest();

  }

  if (ModelState.IsValid)

  {

    await _serviceWrapper.UpdateCarAsync(id,car);

    return RedirectToAction(nameof(Index));

  }

  ViewData["MakeId"] = await GetMakesAsync();

  return View(car);

}

На этой странице вы можете бесплатно читать книгу Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен бесплатно.

Оставить комментарий