Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен
Вызов 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);
}
Откройте для себя мир чтения на siteknig.com - месте, где каждая книга оживает прямо в браузере. Здесь вас уже ждёт произведение Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен, относящееся к жанру Программирование. Никаких регистраций, никаких преград - только вы и история, доступная в полном формате. Наш литературный портал создан для тех, кто любит комфорт: хотите читать с телефона - пожалуйста; предпочитаете ноутбук - идеально! Все книги открываются моментально и представлены полностью, без сокращений и скрытых страниц. Каталог жанров поможет вам быстро найти что-то по настроению: увлекательный роман, динамичное фэнтези, глубокую классику или лёгкое чтение перед сном. Мы ежедневно расширяем библиотеку, добавляя новые произведения, чтобы вам всегда было что открыть "на потом". Сегодня на siteknig.com доступно более 200000 книг - и каждая готова стать вашей новой любимой. Просто выбирайте, открывайте и наслаждайтесь чтением там, где вам удобно.


