Web API
Web API представляет способ построения приложения в стиле REST (Representation State Transfer или «передача состояния представления»). REST-архитектура предполагает применение следующих методов или типов запросов HTTP для взаимодействия с сервером:
- GET (получение данных)
- POST (добавление данных)
- PUT (изменение данных)
- DELETE (удаление данных)
Для реализации подобной архитектуру фреймворк ASP.NET Core предоставляет ряд встроенных методов, которые как и метод Map() реализованы как методы расширения для типа Microsoft.AspNetCore.Routing.IEndpointRouteBuilder (а соответственно и для типа WebApplication). Эти методы также встраивают в конвейер обработки запроса конечные точки , которые обрабатывают определенные типы запросов:
- MapGet (запрос GET)
- MapPost (запрос POST)
- MapPut (запрос PUT)
- MapDelete (запрос DELETE)
Рассмотрим, как мы можем реализовать с помощью этих методов простейший API.
Создание сервера
Вначале определим веб-приложение на ASP.NET Core, которое и будет собственно представлять Web API:
// начальные данные List users = new List < new() < Name = "Tom", Age = 37 >, new() < Name = "Bob", Age = 41 >, new() < Name = "Sam", Age = 24 >>; var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.UseDefaultFiles(); app.UseStaticFiles(); app.MapGet("/api/users", ()=> users); app.MapGet("/api/users/", (string id) => < // получаем пользователя по id Person? user = users.FirstOrDefault(u =>u.Id == id); // если не найден, отправляем статусный код и сообщение об ошибке if (user == null) return Results.NotFound(new < message = "Пользователь не найден" >); // если пользователь найден, отправляем его return Results.Json(user); >); app.MapDelete("/api/users/", (string id) => < // получаем пользователя по id Person? user = users.FirstOrDefault(u =>u.Id == id); // если не найден, отправляем статусный код и сообщение об ошибке if (user == null) return Results.NotFound(new < message = "Пользователь не найден" >); // если пользователь найден, удаляем его users.Remove(user); return Results.Json(user); >); app.MapPost("/api/users", (Person user)=>< // устанавливаем id для нового пользователя user.Id = Guid.NewGuid().ToString(); // добавляем пользователя в список users.Add(user); return user; >); app.MapPut("/api/users", (Person userData) => < // получаем пользователя по id var user = users.FirstOrDefault(u =>u.Id == userData.Id); // если не найден, отправляем статусный код и сообщение об ошибке if (user == null) return Results.NotFound(new < message = "Пользователь не найден" >); // если пользователь найден, изменяем его данные и отправляем обратно клиенту user.Age = userData.Age; user.Name = userData.Name; return Results.Json(user); >); app.Run(); public class Person < public string Id < get; set; >= ""; public string Name < get; set; >= ""; public int Age < get; set; >>
Разберем в общих чертах этот код. Вначале создается список объектов Person — те данные, с которыми будет работать пользователь:
var users = new List < new() < Name = "Tom", Age = 37 >, new() < Name = "Bob", Age = 41 >, new() < Name = "Sam", Age = 24 >>;
Стоит обратить внимание, что каждый объект Person имеет свойство Id, которое в качестве значения получает Guid — уникальный идентификатор, например «2e752824-1657-4c7f-844b-6ec2e168e99c».
Для упрошения данные определены в виде обычного списка объектов, но в реальной ситуации обычно подобные данные извлекаются из какой-нибудь базы данных.
Далее после создания объекта WebApplication подключаем функциональность статических файлов:
app.UseDefaultFiles(); app.UseStaticFiles();
Затем с помощью методов MapGet/MapPost/MapPut/MapDelete определяется набор конечных точек, которые будут обрабатывать разные типы запросов.
Вначале добавляется конечная точка, которая обрабатывает запрос типа GET по маршруту «api/users»:
app.MapGet("/api/users", () => users);
Запрос GET предполагает получение объектов, и в данном случае отправляем выше определенный список объектов Person.
Когда клиент обращается к приложению для получения одного объекта по id в запрос типа GET по адресу «api/users/», то срабатывает другая конечная точка:
app.MapGet("/api/users/", (string id) => < // получаем пользователя по id Person? user = users.FirstOrDefault(u =>u.Id == id); // если не найден, отправляем статусный код и сообщение об ошибке if (user == null) return Results.NotFound(new < message = "Пользователь не найден" >); // если пользователь найден, отправляем его return Results.Json(user); >);
Здесь через параметр id получаем из пути запроса идентификатор объекта Person и по этому идентификатору ищем нужный объект в списке users. Если объект по Id не был найден, то возвращаем с помощью метода Results.NotFound() статусный код 404 с некоторым сообщением в формате JSON. Если объект найден, то с помощью метода Results.Json() отправляет найденный объект клиенту.
При получении запроса типа DELETE по маршруту «/api/users/» срабатывает другая конечная точка:
app.MapDelete("/api/users/", (string id) => < // получаем пользователя по id Person? user = users.FirstOrDefault(u =>u.Id == id); // если не найден, отправляем статусный код и сообщение об ошибке if (user == null) return Results.NotFound(new < message = "Пользователь не найден" >); // если пользователь найден, удаляем его users.Remove(user); return Results.Json(user); >);
Здесь действует аналогичная логика — если объект по Id не найден, отправляет статусный код 404. Если же объект найден, то удаляем его из списка и посылаем клиенту.
При получении запроса с методом POST по адресу «/api/users» срабатывает следующая конечная точка:
app.MapPost("/api/users", (Person user)=>< // устанавливаем id для нового пользователя user.Id = Guid.NewGuid().ToString(); // добавляем пользователя в список users.Add(user); return user; >);
Запрос типа POST предполагает передачу приложению отправляемых данных. Причем мы ожидаем, что клиент отправит данные, которые соответствуют определению типа Person. И поэтому инфраструктура ASP.NET Core сможет автоматически собрать из них объект Person. И этот объект мы сможем получить в качестве параметра в обработчике конечной точки.
После получения данных устанавливаем у нового объекта свойство Id, добавляем его в список users и отправляем обратно клиенту.
Если приложению приходит PUT-запрос по адресу «/api/users», то аналогичным образом получаем отправленные клиентом данные в виде объекта Person и пытаемся найти подобный объект в списке users. Если объект не найден, отправляем статусный код 404. Если объект найден, то изменяем его данные и отправляем обратно клиенту:
app.MapPut("/api/users", (Person userData) => < // получаем пользователя по id var user = users.FirstOrDefault(u =>u.Id == userData.Id); // если не найден, отправляем статусный код и сообщение об ошибке if (user == null) return Results.NotFound(new < message = "Пользователь не найден" >); // если пользователь найден, изменяем его данные и отправляем обратно клиенту user.Age = userData.Age; user.Name = userData.Name; return Results.Json(user); >);
Таким образом, мы определили простейший API. Теперь добавим код клиента.
Определение клиента
Теперь создадим в проекте новую папку wwwroot , в которую добавим новый файл index.html

Определим в файле index.html следующим код для взаимодействия с сервером ASP.NET Core:
METANIT.COM td buttonСписок пользователей
Имя:
Возраст:
| Имя | Возраст |
|---|
Основная логика здесь заключена в коде javascript. При загрузке страницы в браузере получаем все объекты из БД с помощью функции getUsers() :
async function getUsers() < // отправляет запрос и получаем ответ const response = await fetch("/api/users", < method: "GET", headers: < "Accept": "application/json" >>); // если запрос прошел нормально if (response.ok === true) < // получаем данные const users = await response.json(); const rows = document.querySelector("tbody"); // добавляем полученные элементы в таблицу users.forEach(user =>rows.append(row(user))); > >
Для добавления строк в таблицу используется функция row() , которая возвращает строку. В этой строке будут определены ссылки для изменения и удаления пользователя.
Ссылка для изменения пользователя с помощью функции getUser() получает с сервера выделенного пользователя:
async function getUser(id) < const response = await fetch(`/api/users/$`, < method: "GET", headers: < "Accept": "application/json" >>); if (response.ok === true) < const user = await response.json(); document.getElementById("userId").value = user.id; document.getElementById("userName").value = user.name; document.getElementById("userAge").value = user.age; >else < // если произошла ошибка, получаем сообщение об ошибке const error = await response.json(); console.log(error.message); // и выводим его на консоль >>
И выделенный пользователь добавляется в форму над таблицей. Эта же форма применяется и для добавления объекта. С помощью скрытого поля, которое хранит id пользователя, мы можем узнать, какое действие выполняется — добавление или редактирование. Если id не установлен (равен пустой строке), то выполняется функция createUser, которая отправляет данные в POST-запросе:
async function createUser(userName, userAge) < const response = await fetch("api/users", < method: "POST", headers: < "Accept": "application/json", "Content-Type": "application/json" >, body: JSON.stringify(< name: userName, age: parseInt(userAge, 10) >) >); if (response.ok === true) < const user = await response.json(); document.querySelector("tbody").append(row(user)); >else < const error = await response.json(); console.log(error.message); >>
Если же ранее пользователь был загружен на форму, и в скрытом поле сохранился его id, то выполняется функция editUser, которая отправляет PUT-запрос:
async function editUser(userId, userName, userAge) < const response = await fetch("api/users", < method: "PUT", headers: < "Accept": "application/json", "Content-Type": "application/json" >, body: JSON.stringify(< id: userId, name: userName, age: parseInt(userAge, 10) >) >); if (response.ok === true) < const user = await response.json(); document.querySelector(`tr[data-rowid='$']`).replaceWith(row(user)); > else < const error = await response.json(); console.log(error.message); >>
И функция deleteUser() посылает на сервер запрос типа DELETE на удаление пользователя, и при успешном удалении на сервере удаляет объект по id из списка объектов Person.
Теперь запустим проект, и по умолчанию приложение отправит браузеру веб-страницу index.html , которая загрузит список объектов:

После этого мы сможем выполнять все базовые операции с пользователями — получение, добавление, изменение, удаление. Например, добавим нового пользователя:
Использование Web API

Средство Web API основано на добавлении в приложение ASP.NET MVC Framework контроллера специального вида. Эта разновидность контроллеров, которая называется , обладает двумя характеристиками:
- Методы действий возвращают объекты моделей, а не объекты типа ActionResult.
- Методы действий выбираются на основе HTTP-метода, используемого в запросе.
Объекты моделей, возвращаемые методом действия контроллера API, кодируются в формате JSON и отправляются клиенту. Контроллеры API предназначены для доставки веб-служб данных, поэтому они не поддерживают представления, компоновки или любые другие средства, которые применялись для генерации HTML-разметки в примере созданного приложения.
Отсутствие возможности у контроллера API генерировать HTML-разметку из представлений является причиной, по которой в одностраничных приложениях комбинируются стандартные приемы ASP.NET MVC Framework с Web API. Инфраструктура ASP.NET MVC Framework выполняет шаги, требуемые для доставки HTML-содержимого пользователю (включая аутентификацию, авторизацию, выбор и визуализацию представления). После того, как HTML-содержимое доставлено в браузер, запросы Ajax, генерируемые содержащимся внутри кодом JavaScript, будут обрабатываться контроллером Web API.
Как демонстрировалось ранее, в обычных контроллерах можно создавать методы действий, которые возвращают данные JSON для поддержки Ajax, но контроллер API предлагает альтернативный подход. Этот подход предусматривает отделение действий, относящихся к данным, от действий, связанных с представлением, и делает создание универсальных приложений Web API быстрым и простым.
Создание контроллера Web API
Добавление средства Web API к приложению осуществляется исключительно просто. Частично это объясняется тем, что создается элементарная веб-служба, но также и интеграцией с лежащей в основе инфраструктурой ASP.NET MVC Framework. В папке Controllers проекта создается файл класса по имени WebController.cs, в котором определяется контроллер, как показано в примере ниже:
using System; using System.Collections.Generic; using System.Web.Http; using WebServices.Models; namespace WebServices.Controllers < public class WebController : ApiController < private ReservationRepository repo = ReservationRepository.Current; public IEnumerableGetAllReservations() < return repo.GetAll(); >public Reservation GetReservation(int id) < return repo.Get(id); >public Reservation PostReservation(Reservation item) < return repo.Add(item); >public bool PutReservation(Reservation item) < return repo.Update(item); >public void DeleteReservation(int id) < repo.Remove(id); >> >
Это и все, что требуется для создания контроллера API. Контроллер API имеет пять методов действий, которые отображаются на функциональные возможности хранилища и предоставляют доступ через веб-службу к объектам Reservation.
Тестирование контроллера API
Вскоре будут даны пояснения, как работает контроллер API, но сначала необходимо выполнить простой тест. Запустите приложение. После того, как браузер загрузит корневой URL проекта, перейдите на URL вида /api/web. Результат, который будет получен, зависит от применяемого браузера. Если вы используете Internet Explorer, то получите предложение сохранить или открыть файл, содержащий данные JSON.
Если переход на упомянутый URL осуществлялся с помощью другого браузера, такого как Google Chrome, то браузер отобразит приведенные ниже XML-данные:
Петр Отель 1 Вася Библиотека 2 Игорь Столовая 3
Здесь интересно отметить пару моментов. Первый заключается в том, что запрос URL вида /api/web производит список всех объектов модели вместе с их свойствами, из которого можно сделать вывод, что был вызван метод действия GetAllReservations() контроллера Reservation.
Второй момент касается того, что разные браузеры получают разные форматы данных. Если вы попробуете сделать это самостоятельно, то можете получить другие результаты, т.к. в более поздних версиях браузеров может измениться способ выдачи запросов, однако вы заметите, что одни результаты имеют формат JSON, а другие — формат XML. (Также должно стать понятно, почему в веб-службах формат JSON почти повсеместно заменил XML. Формат XML более многословен и труден в обработке, особенно в случае использования JavaScript.)
Разные форматы данных применяются из-за того, что Web API использует HTTP-заголовок Accept в запросе для определения, с каким типом данных клиент предпочитает работать. Браузер Internet Explorer получает данные JSON, поскольку отправляет следующий заголовок Accept:
Accept: text/html, application/xhtml+xml, */*
Браузер указывает, что в первую очередь предпочитает содержимое text/html, а затем application/xhtml+xml. Последняя часть заголовка Accept выглядит как */* и означает, что браузер будет принимать любой тип данных, если первые два оказываются недоступными.
Средство Web API поддерживает форматы JSON и XML, но отдает предпочтение формату JSON, который и будет использоваться в ответ на часть */* заголовка Accept для Internet Explorer. А вот заголовок Accept, отправляемый браузером Google Chrome:
Accept:text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8
Важная часть заголовка выделена полужирным: браузер Google Chrome указывает, что предпочитает получать данные application/xml перед */*. Контроллер Web API учитывает это предпочтение и доставляет данные в формате XML. Об этом упоминается потому, что общей проблемой, связанной с Web API, является получение данных в нежелательном формате. Подобное происходит из-за того, что заголовок Accept выдает неожиданное предпочтение относительно формата или вообще отсутствует в запросе.
Работа контроллера API
Чтобы получить намного больше сведений о работе контроллера API, необходимо перейти на URL вида /api/web/3. Вы увидите следующие данные в формате XML (или в формате JSON, если применяется другой браузер):
Игорь Столовая 3
На этот раз контроллер API возвратил детали объекта Reservation, значение свойства ReservationId которого соответствует последнему сегменту запрошенного URL. Формат и сегменты URL были описаны в статье Шаблоны URL, где объяснялась система маршрутизации ASP.NET MVC Framework.
Контроллеры API имеют собственную конфигурацию маршрутизации, полностью отделенную от остальных частей приложения. Для новых проектов Visual Studio создает стандартную конфигурацию в файле /App_Start/WebApiConfig.cs, содержимое которого приведено в примере ниже. Это один из файлов, которые Visual Studio добавляет в проект, если при его создании был отмечен флажок Web API.
using System; using System.Collections.Generic; using System.Linq; using System.Web.Http; namespace WebServices < public static class WebApiConfig < public static void Register(HttpConfiguration config) < config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api//", defaults: new < >); > > >
Файл WebApiConfig.cs содержит маршруты, используемые контроллерами API, и применяет другие классы, отличающиеся от обычных маршрутов MVC, которые определены в файле RouteConfig.cs. Средство Web API реализовано как автономная функциональная возможность ASP.NET и может применяться за пределами инфраструктуры ASP.NET MVC Framework. Это означает, что в Microsoft продублировали ряд ключевых функций ASP.NET MVC Framework в пространстве имен System.Web.Http, чтобы обеспечить раздельное существование средств MVC и Web API. (При написании приложения ASP.NET MVC Framework такое дублирование выглядит странным, однако оно имеет смысл, т.к. в Microsoft пытаются ориентировать на использование средства Web API также и разработчиков, не применяющих шаблон MVC.)
Среда Visual Studio также помещает в метод Application_Start() класса Global.asax вызов Configure(), который добавит маршруты Web API к конфигурации приложения:
using System; using System.Web; using System.Web.Mvc; using System.Web.Routing; using System.Web.Http; namespace WebServices < public class Global : HttpApplication < void Application_Start(object sender, EventArgs e) < AreaRegistration.RegisterAllAreas(); GlobalConfiguration.Configure(WebApiConfig.Register); RouteConfig.RegisterRoutes(RouteTable.Routes); >> >
В результате приложение имеет два набора маршрутов: те, что используются для контроллеров ASP.NET MVC Framework, и те, что применяются для контроллеров Web API.
Выбор действия контроллером API
Стандартный маршрут Web API, который был показан в примере выше, имеет статический сегмент api, а также переменные сегментов controller и id, являющиеся необязательными. Ключевое отличие от обычного маршрута MVC состоит в том, что переменная сегмента action отсутствует — именно здесь формируется поведение контроллеров API.
Когда в приложение поступает запрос, соответствующий маршруту Web API, действие определяется на основе метода HTTP, используемого для выдачи запроса. При тестировании контроллера API путем запроса в браузере URL вида /api/reservation браузер укажет HTTP-метод GET.
Класс ApiController, который является базовым для контроллеров Web API, выясняет необходимый контроллер на основе маршрута и применяет метод HTTP для поиска подходящих методов действий.
Соглашение по именованию методов действий контроллера API предусматривает снабжение имени метода действия префиксом в виде поддерживаемого им HTTP-метода и включение ссылки на тип модели, с которым метод действия работает. Однако это просто соглашение, т.к. Web API будет обеспечивать соответствие любому методу действия, имя которого содержит метод HTTP, используемый для выполнения запроса.
В рассматриваемом примере запрос GET приведет в результате к выбору между GetAllReservations() и GetReservation(), но также бы подошли имена методов наподобие DoGetReservation() или даже ThisIsTheGetAction().
Чтобы принять решение, какой из этих двух методов действий выбрать, контроллер просматривает аргументы, которые они принимают, и с помощью переменных маршрутизации находит наилучшее соответствие. В случае запроса URL вида /api/reservation нет никаких переменных маршрутизации за исключением controller, поэтому выбирается метод GetAllReservations(), т.к. он не принимает аргументов.
При запросе URL вида /api/reservation/3 предоставляется значение для необязательной переменной сегмента id, что приведет к выбору метода GetReservation(), потому что он принимает аргумент id. Остальные действия в контроллере API ориентированы на другие HTTP-методы: POST, DELETE и PUT. Это основа для стиля средства Web API, чаще называемого службой, поддерживающей REST, когда операция указывается путем комбинирования URL и метода HTTP, используемого для ее запрашивания.
REST — это стиль API-интерфейса, а не хорошо определенная спецификация, поэтому существуют разногласия относительно того, какие в точности признаки делают веб-службу поддерживающей REST. Один из предметов спора связан с тем, что сторонники чистоты определений не считают веб-службы, которые возвращают данные в формате JSON, поддерживающими REST. Как и при любых разногласиях, касающихся архитектурного шаблона, претензии зачастую произвольны и неконкретны. Я стараюсь быть прагматичным в отношении применяемых шаблонов, поэтому считаю службы JSON поддерживающими REST.
Отображение методов HTTP на методы действий
Ранее было указано, что базовый класс ApiController использует метод HTTP для выяснения, на какие методы действий направлять запросы. Это хороший подход, но он означает применение неестественных имен методов, которые не соответствуют соглашениям об именовании, используемым в остальных частях приложения. Например, метод PutReservation() мог бы иметь более естественное имя UpdateReservation(). Мало того, что имя UpdateReservation() делает очевидным назначение этого метода (обновить заявку на бронирование), но оно может также обеспечить более прямое отображение между действиями в контроллере и методами в хранилище.
У вас может возникнуть соблазн унаследовать класс хранилища от ApiController и открыть методы хранилища напрямую как Web API. Настоятельно рекомендуется не поступать так, а создавать отдельный контроллер, даже если он настолько же прост, как в рассматриваемом примере. В какой-то момент методы, которые вы хотите предоставлять через Web API, станут идти вразрез с возможностями хранилища, и наличие отдельного класса контроллера API упростит управление этим.
Пространство имен System.Web.Http содержит набор атрибутов, которые можно использовать, чтобы указать, для каких методов HTTP должно применяться то или иное действие. В примере ниже демонстрируется применение двух таких атрибутов для получения более естественного набора имен методов:
using System; using System.Collections.Generic; using System.Web.Http; using WebServices.Models; namespace WebServices.Controllers < public class WebController : ApiController < private ReservationRepository repo = ReservationRepository.Current; public IEnumerableGetAllReservations() < return repo.GetAll(); >public Reservation GetReservation(int id) < return repo.Get(id); >[HttpPost] public Reservation CreateReservation(Reservation item) < return repo.Add(item); >[HttpPut] public bool UpdateReservation(Reservation item) < return repo.Update(item); >public void DeleteReservation(int id) < repo.Remove(id); >> >
Здесь можно заметить дублирование средств ASP.NET MVC Framework и Web API. Атрибуты HttpPost и HttpPut, использованные в примере, имеют то же самое назначение, что и аналогично именованные атрибуты в MVC, но только они определены в пространстве имен System.Web.Http, а не System.Web.Mvc. Помимо дублирования имен, эти атрибуты функционируют точно таким же образом, и в конечном итоге получаются более удобные имена для методов, которые по-прежнему будут работать с HTTP-методами POST и PUT. (Разумеется, атрибуты предусмотрены для всех методов HTTP, включая GET, DELETE и т.д.)
14) Интервью Asp.Net Web API: вопросы и ответы
WebAPI – это фреймворк, который помогает вам создавать / разрабатывать HTTP-сервисы.
2) Почему требуется веб-API? Можно ли использовать сервисы RESTful с использованием WCF?
Да, мы все еще можем разрабатывать RESTful-сервисы с WCF. Однако есть две основные причины, побуждающие пользователей использовать веб-API вместо служб RESTful.
- Web API расширяет подход TDD (Test Data Driven) при разработке сервисов RESTful.
- Если мы хотим разрабатывать сервисы RESTful в WCF, вам, безусловно, понадобится много настроек конфигурации, шаблонов URI, контрактов и конечных точек для разработки сервисов RESTful с использованием веб-API.
3) Зачем выбирать веб-API?
- Он используется для создания простых HTTP-сервисов, не основанных на SOAP
- Это также простой метод для создания с помощью веб-API. С WCF REST Services
- Он основан на HTTP и прост в определении, представлении и использовании в режиме REST.
- Это легкая архитектура и идеально подходит для устройств с ограниченной пропускной способностью, таких как смартфоны.
4) Правильно ли, что ASP.NET Web API заменил WCF?
Совсем не правда, что ASP.NET Web API заменил WCF. Фактически это еще один способ создания сервисов, не основанных на SOAP, т. Е. Простой XML или строки JSON.
5) Каковы преимущества веб-API?
- OData
- фильтры
- Согласование контента
- Self-хостинг
- Маршрутизация
- Привязки моделей
6) Какие основные типы возвращаемых данных поддерживаются в Web API?
Действие контроллера Web API может возвращать следующие значения:
- Void – вернет пустой контент
- HttpResponseMessage – преобразует ответ в сообщение HTTP.
- IHttpActionResult – внутренне вызывает ExecuteAsync для создания HttpResponseMessage
- Другие типы – вы можете записать сериализованное возвращаемое значение в тело ответа
7) Веб-API поддерживает какой протокол?
Веб-приложение поддерживает протокол HTTP.
8) Какая платформа .NET поддерживает веб-API?
NET 4.0 и выше версия поддерживает веб-API.
9) Веб-API использует какую из следующих библиотек с открытым исходным кодом для сериализации JSON?
Web API использует библиотеку Json.NET для сериализации JSON.
10) По умолчанию Web API отправляет HTTP-ответ с каким из следующих кодов состояния для всех необработанных исключений?
внутренняя ошибка сервера 500
11) Что является самым большим недостатком «Другие типы возврата» в веб-API?
Самым большим недостатком этого подхода является то, что вы не можете напрямую вернуть код ошибки, например 404 error.
12) Как вы строите HtmlResponseMessage?
Ниже приведен способ сделать это,
public class TestController : ApiController < public HttpResponseMessage Get() < HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, "value"); response.Content = new StringContent("Testing", Encoding.Unicode); response.Headers.CacheControl = new CacheControlHeaderValue() < MaxAge = TimeSpan.FromMinutes(20) >; return response; > >
13) Что такое маршрутизация через веб-интерфейс?
Маршрутизация – это сопоставление с образцом, как в MVC.
Все маршруты зарегистрированы в таблицах маршрутов.
Routes.MapHttpRoute( Name: "ExampleWebAPIRoute", routeTemplate: “api// defaults: new < > 14) Что такое SOAP?
SOAP – это формат сообщений XML, используемый во взаимодействиях веб-служб. Это позволяет отправлять сообщения через HTTP или JMS, но могут использоваться и другие транспортные протоколы. Это также протокол обмена сообщениями на основе XML для обмена информацией между компьютерами.
15) В чем преимущество использования REST в веб-API?
REST is used to make fewer data transfers between client and server which make it an ideal for using it in mobile apps. Web API also supports HTTP protocol. Therefore, it reintroduces the traditional way of the HTTP verbs for communication.
16) How can we use Web API with ASP.NET Web Form?
Web API can be used with ASP.NET Web Form
It can be performed in three simple steps:
- Create a Web API Controller,
- Add a routing table to Application_Start method of Global.sax
- Then you need to make a jQuery AJAX Call to Web API method and get data.
17) How to you can limit Access to Web API to Specific HTTP Verb?
Attribute programming plays a important role. It is easy to restrict access to an ASP.NET Web API method to be called using a particular HTTP method.
18) Can you use Web API with ASP.NET Web Form?
Yes, It is possible to use Web API with ASP.Net web form. As it is bundled with ASP.NET MVC framework. However, it can be used with ASP.NET Web Form.
19) How Can assign alias name for ASP.NET Web API Action?
We can give alias name for Web API action same as in case of ASP.NET MVC by using “ActionName” attribute as follows:
[HttpPost] [ActionName(«SaveStudentInfo»)] public void UpdateStudent(Student aStudent)
20) What is the meaning of TestApi?
TestApi is a utility library of APIs. Using this library tester developer can create testing tools and automated tests for a .NET application using data-structure and algorithms.
21) Explain exception filters?
It will be executed when exceptions are unhandled and thrown from a controller method. The reason for the exception can be anything. Exception filters will implement “IExceptionFilter” interface.
22) How can we register exception filter from the action?
We can register exception filter from action using following code:
[NotImplExceptionFilter] public TestCustomer GetMyTestCustomer(int custid) < //write the code >
23) How you can return View from ASP.NET Web API method?
No, we can’t return a view from ASP.NET Web API Method. Web API creates HTTP services that render raw data. However, it’s also possible in ASP.NET MVC application.
24) How to register exception filter globally?
It is possible to register exception filter globally using following code-
25) Объясните, что такое ОТДЫХ и ОТДЫХ?
REST представляет REpresentational State Transfer; это совершенно новый аспект написания веб-приложения.
RESTFUL: термин, написанный с применением архитектурных концепций REST, называется RESTful-сервисами. Основное внимание уделяется системным ресурсам и тому, как состояние ресурса должно передаваться по протоколу HTTP.
26) Дайте мне один пример Web API Routing?
Config.Routes.MapHttpRoute( name: "MyRoute,"//route name routeTemplate: "api///",//as you can see "API" is at the beginning. defaults: new < >);
27) Как вы можете обрабатывать ошибки в веб-API?
В Web API доступно несколько классов для обработки ошибок. Это HttpError, Фильтры исключений, HttpResponseException и Регистрация фильтров исключений.
28) Какие новые функции входят в ASP.NET Web API 2.0?
Последние возможности ASP.NET Web API framework v2.0:
- Маршрутизация атрибутов
- Обмен ресурсами между источниками
- Внешняя аутентификация
- Открытый веб-интерфейс NET
- HttpActionResult
- OData веб-API
29) Как можно ограничить методы доступа конкретными HTTP-глаголами в Web API?
С помощью атрибутов (например, HTTP-глаголов) можно реализовать ограничения доступа в веб-API.
Можно определить глаголы HTTP как атрибут для ограничения доступа. Пример:
[HttpPost] public void Method1(Class obj) < //logic
30) Как вы можете передать несколько сложных типов в веб-API?
Два способа передачи сложных типов в веб-API –
Использование массивов ArrayList и Newtonsoft
31) Написать код для передачи ArrayList в веб-API?
ArrayList paramList = new ArrayList(); Category c = new Category < CategoryId = 1, CategoryName =“MobilePhones”>; Product p = new Product < Productcode = 1, Name = “MotoG”, Price = 15500, CategoryID = 1 >; paramList.Add(c); paramList.Add(p);
32) Назовите инструменты или API для разработки или тестирования веб-API?
Инструменты тестирования для веб-сервисов для REST API включают в себя:
33) Что такое ОТДЫХ?
ОТДЫХ – архитектурный стиль. Он определил руководящие принципы для создания сервисов, которые являются масштабируемыми. REST используется с протоколом HTTP, используя его глаголы GET, PUT, POST и DELETE.
34) Как выполнить модульное тестирование веб-API?
Мы можем выполнить модульное тестирование, используя инструменты Web API, такие как Fiddler.
Вот некоторые настройки, которые необходимо выполнить, если вы используете
Fiddler –Compose Tab -> Введите заголовки запроса -> Введите тело запроса и выполните
35) Как мы можем ограничить доступ к методам с конкретными HTTP-глаголами в Web API?
Программирование атрибутов широко используется для этой функциональности. Веб-API также позволяет ограничивать доступ к вызывающим методам с помощью определенных HTTP-глаголов. Также можно определить HTTP-глаголы как атрибуты по методу.
36) Что такое использование DelegatingHandler?
DelegatingHandler используется в Web API для представления обработчиков сообщений перед маршрутизацией.
37) Как мы можем зарегистрировать фильтр исключений из действия?
Мы можем зарегистрировать фильтр исключений из действия, используя следующий код
[NotImplExceptionFilter] public TestCust GetMyTestCust (int custno) < //write the code >
38) Подскажите фрагмент кода, чтобы показать, как мы можем вернуть 404 ошибки из HttpError?
Код для возврата ошибки 404 из HttpError
string message = string.Format («TestCustomer не найден», customerid);
return Request.CreateErrorResponse (HttpStatusCode.NotFound, message);
39) Объясните фрагмент кода для регистрации фильтров исключений из контроллера?
[NotImplExceptionFilter] public class TestCustController : Controller < //Your code goes here >
40) Какой протокол поддерживает веб-API?
Веб-приложение поддерживает протокол HTTP
41) Какой из следующих .NET Framework поддерживает Web API?
Web API поддерживается версией NET 4.0
42) Какая библиотека использует веб-API для сериализации JSON?
Web API использует библиотеку Json.NET для сериализации JSON.
43) По умолчанию Web API отправляет HTTP-ответ с каким из следующих кодов состояния для всех необработанных исключений?
внутренняя ошибка сервера 500
44) Объясните метод для обработки ошибок, используя HttpError в веб-API?
В WEB API HttpError используется для выдачи информации об ошибке в теле ответа. Метод «CreateErrorResponse» также может использоваться вместе с этим, который является методом расширения, определенным в «HttpRequestMessageExtension».
45) Как мы можем зарегистрировать фильтр исключений глобально?
Мы можем зарегистрировать фильтр исключений глобально, используя следующий код:
GlobalConfiguration.Configuration.Filters.Add (new MyTestCustomerStore.NotImplExceptionFilterAttribute());
46) Как обрабатывать ошибки в веб-API?
В Web API доступно несколько классов для обработки ошибок. Это HttpError, HttpResponseException, фильтры исключений, регистрация фильтров исключений.
47) В чем преимущество WebAPI перед WCF?
Службы WCF используют протокол SOAP, а HTTP никогда не использует протокол SOAP. Вот почему сервисы WebAPI легки, поскольку SOAP не используется. Это также уменьшает данные, которые передаются для возобновления обслуживания. Более того, ему никогда не нужно слишком много настроек. Следовательно, клиент может взаимодействовать со службой с помощью HTTP-глаголов.
48) Различия в состоянии между MVC и WebAPI
MVC Framework используется для разработки приложений, которые имеют пользовательский интерфейс. Для этого представления могут быть использованы для создания пользовательского интерфейса.
WebAPI используется для разработки HTTP-сервисов. Другие приложения также могут называться методами WebAPI для получения этих данных.
49) Кто может использовать WebAPI?
WebAPI может использоваться любым клиентом, который поддерживает HTTP-глаголы, такими как GET, PUT, DELETE, POST. Поскольку сервисы WebAPI не нуждаются в какой-либо конфигурации, их очень легко использовать любому клиенту. Вред, даже портативные устройства, такие как мобильные устройства, могут легко потреблять WebAPI, что, безусловно, является самым большим преимуществом этой технологии.
50) Как мы можем убедиться, что Web API возвращает только данные JSON?
Чтобы заставить Web API сериализовать возвращаемый объект в формат JSON и возвращать только данные JSON. Для этого вы должны добавить следующий код в класс WebApiConfig.cs в любом проекте MVC Web API:
//JsonFormatter //MediaTypeHeaderValue Config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json")); 1 2 3 //JsonFormatter //MediaTypeHeaderValue Config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"))
Шаблон приложения Asp .Net Core 6 Web API с предустановкой и настройкой необходимых инструментов
Обычно моя работа связана с разработкой функционала REST веб-сервисов. Чаще всего, разработка эта ведется на базе уже существующих приложений, созданных и настроенных ранее по шаблону Web API в VisualStudio. Создавать новые приложения приходится не часто, последнее созданное мной, было еще на .NET Core 3.1, поэтому, когда возникает подобная задача, приходится тратить время на повторное изучение технологий первоначальной настройки приложения, чтобы оно отвечало всем требованиям бизнес-процесса компании, в которой я работаю. Столкнулся с этой задачей накануне, решил создать шаблон приложения (ссылка на репозиторий GitHub), в котором уже все настроено и готово. Краткое описание процесса привожу в этой статье. Постарался разбить сам процесс на независимые блоки, чтобы для реализации одного из них не приходилось изучать другие. Намеренно подробно освящаю настройку базовых функции, не вдаваясь в описание принципа работы той или иной функции - для более глубокого понимания привожу ссылки на документацию, по которой учился сам. Статья моя будет полезна для новичков в качестве отправной точки для изучения тех или иных функций .Net Core 6, а так же для специалистов, которые как и я, сосредоточены на реализации бизнес-логики приложения и требуется сократить время восстановления в памяти технологии его первоначальной настройки.
Функционал, который требуется настроить
- Журналирование в файл с репликацией лога
- Хранение и передачу настроек приложения посредством механизма внедрения зависимостей
- Настройка CORS политик для доступа к API посредством кросс-доменных запросов
- Настройка Kestrel на прослушивание определенного порта TCP в режиме публикации селф-хостинг
- Публикация приложения в качестве службы Windows
Создание сборки
Сборка, в соответствии с документацией, должна включать в себя два приложения:
- Приложение внешнего слоя - собственно сам Web API с контроллерами и всеми настройками. Это приложение в VisualStudio создается по шаблону "Asp .Net Core Web API" с установкой опций "Use controllers" и "Enable Open API support". Последняя добавляет в проект автодокументацию на swagger - невероятно полезная штука для отладки
- Приложение уровня ядра для реализации бизнес-логики. Представляет собой библиотеку классов, созданную по шаблону "Class Library"
Настройка работы Kestrel для прослушивания определенного порта в приложении aspnetcore 6
В файле конфигурации appsettings.json
Используется для указания TCP порта встроенному веб-серверу Kestrel при публикации приложения. Добавить параметр Urls:
. "Urls": "http://*:5005" .
В файле конфигурации запуска приложения Properties\launchSettings.json
Используется для запуска Swagger в режиме отладки. Изменить порт в параметре applicationUrl профиля для запуска приложения в режиме селф-хост:
. "profiles": < "WebApiTemplate": < "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "swagger", "applicationUrl": "http://localhost:5005", "environmentVariables": < "ASPNETCORE_ENVIRONMENT": "Development" >>, .
После этих настроек, приложение можно запустить в режиме отладки и убедиться, что swagger доступен на порту 5005 и запрос на созданный по умолчанию метод Get в контроллере WeatherForecast доступен и выполняется на 5005 порту:

Внедрение зависимостей в приложении aspnetcore 6
- Статья на сайте Metanit , спасибо ребятам за толковую документацию
- В Program.cs вносим в коллекцию служб приложения требуемый тип. Добавляем строку в любом месте файла между объявлением builder и вызовом его метода сборки Web приложения var app = builder.Build(); :
builder.Services.AddTransient();
Различные варианты жизненных циклов внедряемых зависимостей отлично описаны в документации, приведу только одну, не очевидную, на первый взгляд, ситуацию. Если требуется создать singleton, то такое объявление:
builder.Services.AddSingleton();
не приведет к незамедлительному созданию экземпляра класса, он будет создан только тогда, когда произойдет первое создание экземпляра другого класса, который ссылается зависимостью на этот. Для того, чтобы синглтон создавался незамедлительно при старте приложения, объявлять его нужно так:
builder.Services.AddSingleton(new SomeClass());
Но тут могут возникнуть трудности, если конструктор класса имеет параметры и тоже требует внедрения зависимостей. Все эти зависимости можно при желании получить из builder .
Передача настроек appsettings.json через внедрение зависимостей в приложении aspnetcore 6
- Статья на сайте Metanit , спасибо ребятам за толковую документацию
- Создаем класс для настроек ( ApplicationSettings )
- Подключаем настройки в Program.cs. Добавляем строку в любом месте файла между объявлением builder и вызовом его метода сборки Web приложения var app = builder.Build(); :
builder.Services.Configure(builder.Configuration);
- В классе, где требуется экземпляр объекта настроек, получаем значение через внедрение зависимостей:
- при помощи NuGet, ставим пакет Microsoft.Extensions.Options
- объявляем readonly поле:
private readonly ApplicationSettings _settings;
- внедряем зависимость через конструктор:
public WebApiService(IOptions options)
Настройка NLog в приложении aspnetcore 6
В нашей компании так заведено, что все функции журналирования реализованы с использованием пакета NLog. Эта традиция живет у нас со времен .Net Framework, возможно, в данный момент, в функции журналирования .NET Core уже встроены все преимущества NLog, но мне это не известно, поэтому в данной статье рассматривается именно такой способ.
- Быстрый запуск
- Конфигурация
- Подключаем NLog в Program.cs. Добавляем строки в любом месте файла между объявлением builder и вызовом его метода сборки Web приложения var app = builder.Build(); :
// NLog: Setup NLog for Dependency injection builder.Logging.ClearProviders(); builder.Host.UseNLog();
- В классе, где требуется журналирование, устанавливаем нужные пакеты, внедряем логгер, зависимость, назначив ему соответствующую категорию:
- при помощи NuGet, если требуется, ставим пакет Microsoft.Extensions.Logging.Abstractions
- объявляем readonly поле:
private readonly ILogger _logger; //здесь "WebApiService" - категория журнала, тип, от имени которого будут поступать сообщения
- внедряем зависимость через конструктор:
public WebApiService(ILogger logger)
- Запись в журнал:
_logger.LogDebug($", значение параметра из настроек: ");
- Настраиваем цели для журналирования, категории, репликацию лог файлов, в конфигурации nlog.config. Размещенный в репозитории файл конфигурации уже содержит настройку репликации, при которой хранятся лог-файлы за последние 10 дней. Запись лога в файл настроена так, чтобы не забивало журнал сообщениями используемых библиотек Microsoft.
- Проверка. Запускаем приложение, вызываем метод http://localhost:5005/WeatherForecast. Результат работы приложения из приведенного выше репозитория из файла журнала:
2023-01-06 13:10:45.2375 | INFO | Microsoft.AspNetCore.Hosting.Diagnostics | Request starting HTTP/1.1 GET http://localhost:5005/WeatherForecast - - | 2023-01-06 13:10:45.3266 | DEBUG | WebApiTemplate.Controllers.WeatherForecastController | Проверяем внедрение зависимостей, значение параметра из настроек: Some value | 2023-01-06 13:10:45.3266 | DEBUG | WebApiTemplate.Core.Services.WebApiService | Проверяем работу сервиса уровня ядра, значение параметра из настроек: Some value | 2023-01-06 13:10:45.3266 | INFO | WebApiTemplate.Controllers.WeatherForecastController | Action status: Ok | 2023-01-06 13:10:45.3945 | INFO | Microsoft.AspNetCore.Hosting.Diagnostics | Request finished HTTP/1.1 GET http://localhost:5005/WeatherForecast - - - 200 - application/json;+charset=utf-8 157.2347ms |
В журнале видно поступление запроса на контроллер, начало выполнения метода WebApiTemplate.Controllers.WeatherForecastController.Get , вызов метода сервиса WebApiTemplate.Core.Services.WebApiService.SomeAction , результат работы этого метода и отчет о завершении запроса.
Настройка CORS политик в приложении aspnetcore 6
- Статья на сайте Metanit по конфигурации CORS , спасибо ребятам за толковую документацию
- Статья на сайте Metanit по настройке политик CORS , спасибо ребятам за толковую документацию
Для моих производственных нужд обычно требуется два набора политик: для отладки (разрешено все) и для публикации (разрешено только то, что требуется)
- В appsettings.json создаем свойство AllowedOrigins :
- добавляем параметр в объект настроек
/// /// Настройки приложения /// public class ApplicationSettings < . /// /// Разрешенные домены - источники запросов для политики CORS /// public string[] AllowedOrigins < get; set; >>
- Так как потребуется получение настроек, в Program.cs создаем экземпляр объекта настроек в любом месте файла между объявлением builder и вызовом его метода сборки Web приложения var app = builder.Build(); :
var settings = builder.Configuration.Get() ?? throw new ArgumentNullException("ApplicationSettings", "Конфигурация не получена");
- В Program.cs объявляем CORS политики до вызова builder.Build()
builder.Services.AddCors(options => options.AddPolicy("AllowAny", builder => builder .AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod()) ); builder.Services.AddCors(options => options.AddPolicy("AllowSome", builder => builder .WithOrigins(settings.AllowedOrigins) .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials()) );
- В зависимости от типа запуска приложения (Debug или Release), подключаем ту или иную политику в файле Program.cs между var app = builder.Build(); и app.Run(); :
#if DEBUG app.UseCors("AllowAny"); #else app.UseCors("AllowSpecURLs"); #endif
Настройка публикации приложения aspnetcore 6 в качестве службы Windows
Если попытаться запустить приложение, как службу, менеджер служб WIndows, ожидая статус запуска из параметров stdout, не получив этот статус, выдаст ошибку "Ошибка 1053 Служба не ответила на запрос своевременно". Для устранения этой ошибки требуется дополнительная настройка приложения.
- Статья MSDN на русском
- Устанавливаем пакет Microsoft.Extensions.Hosting.WindowsServices
- в Program.cs создаем объект настроек и передаем его в конструктор builder взамен строки var builder = WebApplication.CreateBuilder(args);
var options = new WebApplicationOptions < Args = args, ContentRootPath = WindowsServiceHelpers.IsWindowsService() ? AppContext.BaseDirectory : default >; var builder = WebApplication.CreateBuilder(options);
- Публикуем приложение и размещаем его на сервере Windows любым способом
- На сервере любым доступным способом регистрируем и запускаем службу