C# — Как научиться создавать Web API (как пример CRUD)


Содержание

Использование 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, в котором определяется контроллер, как показано в примере ниже:

Это и все, что требуется для создания контроллера API. Контроллер API имеет пять методов действий, которые отображаются на функциональные возможности хранилища и предоставляют доступ через веб-службу к объектам Reservation.

Тестирование контроллера API

Вскоре будут даны пояснения, как работает контроллер API, но сначала необходимо выполнить простой тест. Запустите приложение. После того, как браузер загрузит корневой URL проекта, перейдите на URL вида /api/web. Результат, который будет получен, зависит от применяемого браузера. Если вы используете Internet Explorer, то получите предложение сохранить или открыть файл, содержащий данные JSON.

Если переход на упомянутый URL осуществлялся с помощью другого браузера, такого как Google Chrome, то браузер отобразит приведенные ниже XML-данные:

Здесь интересно отметить пару моментов. Первый заключается в том, что запрос URL вида /api/web производит список всех объектов модели вместе с их свойствами, из которого можно сделать вывод, что был вызван метод действия GetAllReservations() контроллера Reservation.

Второй момент касается того, что разные браузеры получают разные форматы данных. Если вы попробуете сделать это самостоятельно, то можете получить другие результаты, т.к. в более поздних версиях браузеров может измениться способ выдачи запросов, однако вы заметите, что одни результаты имеют формат JSON, а другие — формат XML. (Также должно стать понятно, почему в веб-службах формат JSON почти повсеместно заменил XML. Формат XML более многословен и труден в обработке, особенно в случае использования JavaScript.)

Разные форматы данных применяются из-за того, что Web API использует HTTP-заголовок Accept в запросе для определения, с каким типом данных клиент предпочитает работать. Браузер Internet Explorer получает данные JSON, поскольку отправляет следующий заголовок Accept:

Браузер указывает, что в первую очередь предпочитает содержимое text/html, а затем application/xhtml+xml. Последняя часть заголовка Accept выглядит как */* и означает, что браузер будет принимать любой тип данных, если первые два оказываются недоступными.

Средство Web API поддерживает форматы JSON и XML, но отдает предпочтение формату JSON, который и будет использоваться в ответ на часть */* заголовка Accept для Internet Explorer. А вот заголовок Accept, отправляемый браузером Google Chrome:

Важная часть заголовка выделена полужирным: браузер Google Chrome указывает, что предпочитает получать данные application/xml перед */*. Контроллер Web API учитывает это предпочтение и доставляет данные в формате XML. Об этом упоминается потому, что общей проблемой, связанной с Web API, является получение данных в нежелательном формате. Подобное происходит из-за того, что заголовок Accept выдает неожиданное предпочтение относительно формата или вообще отсутствует в запросе.

Работа контроллера API

Чтобы получить намного больше сведений о работе контроллера API, необходимо перейти на URL вида /api/web/3. Вы увидите следующие данные в формате XML (или в формате JSON, если применяется другой браузер):

На этот раз контроллер API возвратил детали объекта Reservation, значение свойства ReservationId которого соответствует последнему сегменту запрошенного URL. Формат и сегменты URL были описаны в статье Шаблоны URL, где объяснялась система маршрутизации ASP.NET MVC Framework.

Контроллеры API имеют собственную конфигурацию маршрутизации, полностью отделенную от остальных частей приложения. Для новых проектов Visual Studio создает стандартную конфигурацию в файле /App_Start/WebApiConfig.cs, содержимое которого приведено в примере ниже. Это один из файлов, которые Visual Studio добавляет в проект, если при его создании был отмечен флажок Web API.

Файл 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 к конфигурации приложения:

В результате приложение имеет два набора маршрутов: те, что используются для контроллеров 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 упростит управление этим.

Внедрение WEB API в проект MVC

Всем доброго времени суток! Имеется проект MVC. Суть: информационный сайт, с авторизацией, и возможностью CRUD операций. необходимо добавить API который выступал бы посредником между данными с базы и бизнес логикой сайта. Натолкните на мысль как осуществить?

1 ответ 1

Для того чтобы добавить Web API в проект MVC нужно провести ряд действий.

Установите библиотеки Web API через менеджер пакетов Nuget.

или используя консоль

В папку AppStart добавьте файл WebApiConfig.cs . В нем будет находится конфигурация Web API.

После этого в файл Global.asax.cs добавьте строчку GlobalConfiguration.Configure(WebApiConfig.Register) для регистрации Web API:

WebAPI Help (Опционально)

Вы можете включить также очень удобную автоматическую генерацию документации для вашего API. Для этого вам нужно установить еще один пакет через Nuget Microsoft.AspNet.WebApi.HelpPage .

Консоль: Install-Package Microsoft.AspNet.WebApi.HelpPage

Проверка работоспособности

Теперь можно создавать Web API Controller для проверки работоспособности кода.

C# — Как научиться создавать Web API (как пример CRUD)

Самым актуальный способом создать REST сервис в стеке технологий Майкрософт на сегодняшний день является ASP.NET Web API. До того эта технология значилась как WCF Web API и больше по названию тяготела к WCF. Но уже тогда там использовались сходные походы как в ASP.NET MVC, включая роутинг (routing). До нее существовали такие вещи как WCF 4 REST, WCF REST Starter Kit 3.5. Их все еще можно встретить на старых проектах и stackoverflow пестрит вопросами о них. Но то что ASP.NET Web API используется на новых проектах, а некоторые старые конвертируются, чтобы его использовать – радует. Так как предшественники были хуже как в плане технологии (приходилось писать много boilerplating code), удобства использования так и документации.

В предыдущих постах были рассмотрены некоторые теоретические аспекты REST – теперь создадим простой REST сервис с помощью Web API и рассмотрим ключевые элементы такого сервиса.
Начать стоит с подключения NuGet packages (и/или установки ASP.NET MVC):

  1. Web API, в случае если хостимся в ASP.NET:AspNetWebApi
  2. Self-hosted Web API:AspNetWebApi.Selfhost
  3. HttpClient включая XML и JSON форматеры:System.Net.Http.Formatting
  4. JsonValue для навигации и манипуляции JSON:System.Json

В нашем случае, мы создадим просто сервис, который хостится на ASP.NET MVC, а также посмотрим на принцип создания интеграционных тестов к нему, которые будут поднимать self-hosted REST сервис в тестовом контексте. Акцент на Data access layer делятся не будет, если в процессе вам необходимо прикрутить DAL, например, с использованием Entity Framework Code First, то я писал об одном из возможных подходов раньше.

Перед тем как создавать такой сервис необходимо также понимать что использовать Web API стоит если есть тесная связка с веб-клиентом, если сервис содержит логику выходящую за рамки CRUD операций. Если же у вас сервис по сути своей поставщик данных, т.е. операции в основном CRUD, то лучше использовать WCF Data Services, так как там много вещей из коробки генерится под базу — и CRUD операции и нормальная поддержка OData и IQuerable (в ASP.NET Web API она ограничена), которые позволяют делать запросы к сервису и данным с помощью Uri и специального OData синтаксиса.

Итак преступим. Для начала создадим новый проект ASP.NET MVC4:

Изображение 1
Естественно темплейт (шаблон) для MVC 4 нагенерит нам типичную структуру ASP.NET MVC проекта (файл ValuesController я уже успел переименовать на DocumentsController). Отличие в дополнительном контроллере для Web API. По умолчанию это ValuesController, естественно его необходимо переименовать.

В нашем случае он стал DocumentsController. Из темплейта этот контроллер содержит операции заглушки для Get, Post, Put, Delete. В просто случае переопределим эти операции для DocumentsController и ресурса Document. Получится вот такой вот контроллер:

Это простой вариант, и здесь не используются фильтры для обработки сообщений или dependency resolvers. В свою очередь IDocumentRepository реализовано как простая заглушка и если дальше развивать тему с нормальным доступом к данным то реализацию можно подставить любую.
Теперь проверим операции. Это сделать можно используя Fiddler и правильно сформировав запрос. Например операция получения всех документов, используем адрес http://127.0.0.1:81/api/documents/. Используется стандартный роутинг из коробки:

Итак, запрос на http://127.0.0.1:81/api/documents/ должен вызвать метод IEnumerable Get() :


Так и есть, нам вернулся список в виде XML из двух элементов. Теперь попробуем content negotiation из коробки в действии. К тому же самому вызову добавим HTTP заголовок – Accept:application/json. Итак запрос:

Ответ ожидаем в Json:

Из коробки идут два стандартных форматера – XML и Json, но есть возможность добавлять свои.

Аналогичным образом будут работать остальные операции. Единственное попробуем еще запросить документ с недействительным идентификатором. Будем вызывать метод Document Get(string id) по адресу http://127.0.0.1:81/api/documents/9505a3b549b54881b3ed83fc19510534, где 9505a3b549b54881b3ed83fc19510534 – недействительный идентификатор, изменили последнюю цифру.

Ожидается ответ 404 NotFound. Результат запроса:

Вот таким вот образом можно создать и протестировать на работоспособность простенький REST сервис на базе ASP.NET Web API.

Основные концепты — ApiController

Так как мы имеем дело с REST сервисом. То из всего этого добра нас интересуют на начальном этапе контроллеры и роутинг. Контроллеры для Web API REST сервиса наследуются от от класса ApiController, который в свою очередь от интерфейса IHttpController. И ApiController несет с собой много добра, кроме конечно того что она автоматом распознается и выполняется. Из всего этого добра самое интересное являются свойства Request и Configuration.

Основные концепты – Routing (Роутинг)

При вызове операций с контроллера важный момент играет routing. Именно routing позволяет подсистеме WebApi связать Uri адрес и конкретную операцию из контроллера. Причем есть несколько вариантов — либо операция-action помечается атрибутом, либо используется договоренность именовать операции с префиксом – Http Verb. Например, в методе PostDocument – именно префикс Post позволяет сказать Web Api что эта операция связанна с Uri и вызывается по соответствующему адресу с HTTP Verb – POST.
Еще одним вариантом для того, чтобы помочь выделить среди методов контроллера операции, которые связанны с URL – использование атрибутов — HttpGet, HttpPut, HttpPost, или HttpDelete, каждый из них соответствует такому же HTTP Verb – GET, PUT, POST, DELETE. Для того, чтобы навесить на операцию больше чем один HTTP Verb, или операцию отличную от 4 базовых (GET, PUT, POST, DELETE), используется атрибут – AcceptVerbs. Использование атрибутов также дает возможность отказаться от конвенции именования методов, когда префиксом выступает HTTP Verb.

А для того чтобы избежать мапинга (mapping) метода как action используется атрибут NonAction без параметров.
Есть еще способ роутинга, когда каждый мапинг делается по средством атрибутов на метод, а не глобальным роутингом через Global.asax.cs, но о нем позже, так как он не стандартный. Хотя на этапе WCF Web API использовался именно он.

Routing по-умолчанию в Web API устанавливается как в методе RegisterRoutes на изображении 5 ниже. При использовании такого routing необходимо придерживаться конвенции именования методов в контроллере, когда каждый метод начинается с HTTP Verb префикса.

Ну и естественно важная часть маппинга – routing в Global.asax.cs:

Соответственно под роутинг «api//» подпадают URLs и примерные имена методов:
Можно также сделать роутинг по имени action. Он не создается по-умолчанию темплейтом проекта. Например:
В случае с таким роутингом необходимо использовать атрибуты HttpGet, HttpPut, HttpPost, HttpDelete или AcceptVerbs чтобы указать на какие методы мапить . В WCF WebAPI использовался роутинг с помощью атрибутов, его тоже можно прикрутить, но об этом отдельно.

Основные концепты — HttpResponseMessage, HttpRequestMessage

По сути это два спец класса которые используются достаточно часто. Они нужны для того чтобы иметь возможность оперировать запросом и ответом. HttpRequestMessage можно получить через свойство Request от ApiController (Изображение 6). Tак как Web API контроллеры всегда наследуются от ApiController, то его можно получить в середине любого из наших контроллеров. HttpRequestMessage позволяет нам управлять запросом, например извлекать из него данные из HTTP Body либо HTTP Headers которые нам нужны.

HttpResponseMessage можно создать, чтобы вернуть результат, либо просто Response код (Изображение 7), либо еще и с нагрузкой, запаковав в его свойство Content, нужный нам HttpContent, например для бинарных данных подойдет наследник от HttpContent – StreamContent. Из свойства Request можно вычитать бинарные данные документа, который пришел с клиента:

Возврат ошибок — HttpResponseException

Вернуть ответ с ошибкой можно как с помощью HttpResponseMessage, указав код ошибки, так и с помощью специального класса HttpResponseException. Например, на изображении 7 на клиент возвращается ошибка InternalServerError = 500 с коротким описанием. Описание умеют читать далеко не все клиенты или клиентские библиотеки (были проблемы с iPad), в таком случае в тело сообщения с ошибкой можно писать объект более детально описывающий проблему, например свой кастомный объект с сообщением и кодом ошибки.

Цукерберг рекомендует:  Программирование - Android Studio, как правильно делать отладку приложения

Хостинг

Само собой разумеется, что Web API REST сервис может хоститься на IIS либо вместе с ASP.NET MVC клиентом либо раздельно. Также его можно легко захостить вместе с ASP.NET MVC Web Role в облаке на Windows Azure. Но интересно, что Web API также можно хостить у себя в приложении, в памяти. Это значительно расширяет круг сценариев, в которых Web API может использоваться. Например с self-hosted Web API можно легко делать интеграционные тесты, которые поднимут во время тестирования self-hosted Web API сервис.

Например, на изображение 8 ниже, показано как поднимается с self-hosted Web API сервис для интеграционного теста в методе BecauseOf.

Клиент

Клиентов к Web API REST может быть большое множество – есть куча библиотек под разные платформы для REST, можно обращаться к REST сервису c веб страницы по средством JavaScript и jQuery, можно использовать “старенький” класс WebClient для десктоп клиента. Вместе с Web API новым для .NET является также новый HttpClient, который очень легко использовать с десктоп клиента или тестового сценария (пример на изображении 8 метод should_make_tivial_get), и к тому же он изначально спроектирован асинхронным.

Грамотная клиент-серверная архитектура: как правильно проектировать и разрабатывать web API

Рассказывает Владимир, веб-разработчик Noveo

Большинству разработчиков сайтов, веб-сервисов и мобильных приложений рано или поздно приходится иметь дело с клиент-серверной архитектурой, а именно разрабатывать web API или интегрироваться с ним. Чтобы не изобретать каждый раз что-то новое, важно выработать относительно универсальный подход к проектированию web API, основываясь на опыте разработки подобных систем. Предлагаем вашему вниманию объединенный цикл статей, посвящённых этому вопросу.

Приближение первое: Действующие лица

В один прекрасный момент, в процессе создания очередного веб-сервиса, я решил собрать все свои знания и размышления на тему проектирования web API для обслуживания нужд клиентских приложений и оформить их в виде статьи или серии статей. Разумеется, мой опыт не претендует на абсолют, и конструктивная критика и дополнения более чем приветствуются.

Чтиво получилось больше философское, нежели техническое, но и для любителей технической части здесь будет над чем поразмыслить. Сомневаюсь, что скажу в этой статье что-то принципиально новое, то, о чем вы никогда не слышали, не читали и о чем не думали сами. Просто попытаюсь уложить все в единую систему, в первую очередь в своей собственной голове, а это уже дорогого стоит. Тем не менее, буду рад, если мои измышления будут вам полезны в вашей практике. Итак, поехали.

Клиент и сервер

Сервером в данном случае мы считаем абстрактную машину в сети, способную получить HTTP-запрос, обработать его и вернуть корректный ответ. В контексте данной статьи совершенно не важны его физическая суть и внутренняя архитектура, будь то студенческий ноутбук или огромный кластер из промышленных серверов, разбросанных по всему миру. Нам в той же мере совершенно неважно, что у него под капотом, кто встречает запрос у дверей, Apache или Nginx, какой неведомый зверь, PHP, Python или Ruby выполняет его обработку и формирует ответ, какое хранилище данных используется: Postgresql, MySQL или MongoDB. Главное, чтобы сервер отвечал главному правилу — услышать, понять и простить ответить.

Клиентом тоже может быть все, что угодно, что способно сформировать и отправить HTTP-запрос. До определенного момента в этой статье нам также не особо будут интересны цели, которые ставит перед собой клиент, отправляя этот запрос, как и то, что он будет делать с ответом. Клиентом может быть JavaScript-сценарий, работающий в браузере, мобильное приложение, злой (или не очень) демон, запущенный на сервере, или слишком поумневший холодильник (уже есть и такие).

По большей части мы будем говорить о способе общения между выше перечисленными двумя, таком способе, чтобы они друг друга понимали, и ни у одного не оставалось вопросов.

Философия REST

REST (Representational state transfer) изначально был задуман как простой и однозначный интерфейс для управления данными, предполагавший всего несколько базовых операций с непосредственным сетевым хранилищем (сервером): извлечение данных (GET), сохранение (POST), изменение (PUT/PATCH) и удаление (DELETE). Разумеется, этот перечень всегда сопровождался такими опциями, как обработка ошибок в запросе (корректно ли составлен запрос), разграничение доступа к данным (вдруг этого вам знать не следует) и валидация входящих данных (вдруг вы написали ерунду), в общем, всеми возможными проверками, которые сервер выполняет перед тем, как выполнить желание клиента.

Помимо этого REST имеет ряд архитектурных принципов, перечень которых можно найти в любой другой статье о REST. Пробежимся по ним кратко, чтобы они были под рукой, и не пришлось никуда уходить:

Независимость сервера от клиента — серверы и клиенты могут быть мгновенно заменены другими независимо друг от друга, так как интерфейс между ними не меняется. Сервер не хранит состояний клиента.
Уникальность адресов ресурсов — каждая единица данных (любой степени вложенности) имеет свой собственный уникальный URL, который, по сути, целиком является однозначным идентификатором ресурса.

Пример: GET /api/v1/users/25/name

Независимость формата хранения данных от формата их передачи — сервер может поддерживать несколько различных форматов для передачи одних и тех же данных (JSON, XML и т.д.), но хранит данные в своем внутреннем формате, независимо от поддерживаемых.

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

Чего нам не хватает

Классический REST подразумевает работу клиента с сервером как с плоским хранилищем данных, при этом ничего не говорится о связанности и взаимозависимости данных между собой. Все это по умолчанию целиком ложится на плечи клиентского приложения. Однако современные предметные области, для которых разрабатываются системы управления данными, будь то социальные сервисы или системы интернет-маркетинга, подразумевают сложную взаимосвязь между сущностями, хранящимися в базе данных. Поддержка этих связей, т.е. целостности данных, находится в зоне ответственности серверной стороны, в то время, как клиент является только интерфейсом для доступа к этим данным. Так чего же нам не хватает в REST?

Вызовы функций

Чтобы не менять данные и связи между ними вручную, мы просто вызываем у ресурса функцию и «скармливаем» ей в качестве аргумента необходимые данные. Эта операция не подходит под стандарты REST, для нее не существует особого глагола, что заставляет нас, разработчиков, выкручиваться кто во что горазд.

Самый простой пример – авторизация пользователя. Мы вызываем функцию login, передаем ей в качестве аргумента объект, содержащий учетные данные, и в ответ получаем ключ доступа. Что творится с данными на серверной стороне – нас не волнует.

Еще вариант – создание и разрыв связей между данными. Например, добавление пользователя в группу. Вызываем у сущности группа функцию addUser, в качестве параметра передаем объект пользователь, получаем результат.

А еще бывают операции, которые вообще не связаны напрямую с сохранением данных как таковых, например, рассылка уведомлений, подтверждение или отклонение каких-либо операций (завершение отчетного периода etc).

В одной из следующих статей я постараюсь классифицировать эти операции и предложить варианты возможных запросов и ответов, основываясь на том, с какими из них мне приходилось сталкиваться на практике.

Множественные операции

Часто бывает так, и разработчики клиентов поймут, о чем я, что клиентскому приложению удобнее создавать/изменять/удалять/ сразу несколько однородных объектов одним запросом, и по каждому объекту возможен свой вердикт серверной стороны. Тут есть как минимум несколько вариантов: либо все изменения выполнены, либо они выполнены частично (для части объектов), либо произошла ошибка. Ну и стратегий тоже несколько: применять изменения только в случае успеха для всех, либо применять частично, либо откатываться в случае любой ошибки, а это уже тянет на полноценный механизм транзакций.

Для web API, стремящегося к идеалу, тоже хотелось бы как-то привести подобные операции в систему. Постараюсь сделать это в одном из продолжений.

Статистические запросы, агрегаторы, форматирование данных

Частенько бывает так, что на основе хранимых на сервере данных нам нужно получить статистическую выжимку или данные, отформатированные особым образом: например, для построения графика на стороне клиента. По сути это данные, генерируемые по требованию, в той или иной мере на лету, и доступные только для чтения, так что имеет смысл вынести их в отдельную категорию. Одной из отличительных особенностей статистических данных, на мой взгляд, является то, что они не имеют уникального ID.

Уверен, что это далеко не все, с чем можно столкнуться при разработке реальных приложений, и буду рад вашим дополнениям и коррективам.

Разновидности данных

Объекты

Ключевым типом данных в общении между клиентом и сервером выступает объект. По сути, объект – это перечень свойств и соответствующих им значений. Мы можем отправить объект на сервер в запросе и получить в результат запроса в виде объекта. При этом объект не обязательно будет реальной сущностью, хранящейся в базе данных, по крайней мере, в том виде, в котором он отправлен или получен. Например, учетные данные для авторизации передаются в виде объекта, но не являются самостоятельной сущностью. Даже хранимые в БД объекты склонны обрастать дополнительными свойствами внутрисистемного характера, например, датами создания и редактирования, различными системными метками и флагами. Свойства объектов могут быть как собственными скалярными значениями, так и содержать связанные объекты и коллекции объектов, которые не являются частью объекта. Часть свойств объектов может быть редактируемой, часть системной, доступной только для чтения, а часть может носить статистический характер и вычисляться на лету (например, количество лайков). Некоторые свойства объекта могут быть скрыты, в зависимости от прав пользователя.

Коллекции объектов

Говоря о коллекциях, мы подразумеваем разновидность серверного ресурса, позволяющую работать с перечнем однородных объектов, т.е. добавлять, удалять, изменять объекты и осуществлять выборку из них. Помимо этого коллекция теоретически может обладать собственными свойствами (например, максимальное число элементов на страницу) и функциями (тут я в замешательстве, но такое тоже было).

Скалярные значения


В чистом виде скалярные значения как отдельная сущность на моей памяти встречались крайне редко. Обычно они фигурировали как свойства объектов или коллекций, и в этом качестве они могут быть доступны как для чтения, так и для записи. Например, имя пользователя может быть получено и изменено в индивидуальном порядке GET /users/1/name . На практике эта возможность пригождается редко, но в случае необходимости хотелось бы, чтобы она была под рукой. Особенно это касается свойств коллекции, например числа записей (с фильтрацией или без нее): GET /news/count .

В одной из следующих статей я постараюсь классифицировать эти операции и предложить варианты возможных запросов и ответов, основываясь на том, с какими из них мне приходилось сталкиваться на практике.

Приближение второе: Правильный путь

В этом приближении я хотел бы отдельно поговорить о подходах к построению уникальных путей к ресурсам и методам вашего web API и о тех архитектурных особенностях приложения, которые влияют на внешний вид этого пути и его компоненты.

О чем стоит подумать, стоя на берегу

Версионность

Рано или поздно любая действующая система начинает эволюционировать: развиваться, усложняться, масштабироваться, усовремениваться. Для разработчиков REST API это чревато в первую очередь тем, что необходимо запускать новые версии API при работающих старых. Здесь я говорю больше не об архитектурных изменениях под капотом вашей системы, а о том, что изменяется сам формат данных и набор операций с ними. В любом случае версионность нужно предусмотреть как в изначальной организации исходного кода, так и в принципе построения URL. Что касается URL, здесь существует два наиболее популярных способа указания версии API, которой адресован запрос. Префиксация пути example-api.com/v1/ и разведение версий на уровне субдомена v1.example-api.com . Использовать можно любой из них, в зависимости от потребности и необходимости.

Автономность компонентов

Web API сложных систем, поддерживающих несколько пользовательских ролей, зачастую требует разделения на части, каждая из которых обслуживает свой спектр задач. По сути, каждая часть может быть самостоятельным приложением, работать на разных физических машинах и платформах. В контексте описания API нам совершенно не важно, как сервер обрабатывает запрос и какие силы и технологии в этом замешаны. Для клиента API – система инкапсулированная. Тем не менее разные части системы могут обладать совершенно разной функциональностью, например, административная и пользовательская часть. И методология работы с одними и теми же, казалось бы, ресурсами может существенно отличаться. Поэтому такие части необходимо разделять на уровне домена admin.v1.example-api.com или префикса пути example-api.com/v1/admin/ . Это требование не является обязательным, и многое зависит от сложности системы и её назначения.

Формат обмена данными

Самым удобным и функциональным, на мой взгляд, форматом обмена данными является JSON, но никто не запрещает использовать XML, YAML или любой другой формат, позволяющий хранить сериализованные объекты без потери типа данных. При желании можно сделать в API поддержку нескольких форматов ввода/вывода. Достаточно задействовать HTTP заголовок запроса для указания желаемого формата ответа Accept и Content-Type для указания формата переданных в запросе данных. Другим популярным способом является добавление расширения к URL ресурса, например, GET /users.xml , но такой способ кажется менее гибким и красивым, хотя бы потому, что утяжеляет URL и верен скорее для GET-запросов, нежели для всех возможных операций.

Локализация и многоязычность

На практике многоязычность API чаще всего сводится к переводу сервисных сообщений и сообщений об ошибках на требуемый язык для прямого отображения конечному пользователю. Многоязычный контент тоже имеет место быть, но сохранение и выдача контента на разных языках, на мой взгляд, должна разграничиваться более явно, например, если у вас одна и та же статья существует на разных языках, то по факту это две разных сущности, сгруппированные по признаку единства содержания. Для идентификации ожидаемого языка можно использовать разные способы. Самым простым можно считать стандартный HTTP-заголовок Accept-Language . Я встречал и другие способы, такие, как добавление GET-параметра language=»en» , использование префикса пути example-api.com/en/ или даже на уровне доменного имени en.example-api.com . Мне кажется, что выбор способа указания локали зависит от конкретного приложения и задач, стоящих перед ним.

Внутренняя маршрутизация

Итак, мы добрались до корневого узла нашего API (или одного из его компонентов). Все дальнейшие маршруты будут проходить уже непосредственно внутри вашего серверного приложения, в соответствии с поддерживаемым им набором ресурсов.

Пути к коллекциям

Для указания пути к коллекции мы просто используем название соответствующей сущности, например, если это список пользователей, то путь будет таким /users . К коллекции как таковой применимы два метода: GET (получение лимитированного списка сущностей) и POST (создание нового элемента). В запросах на получение списков мы можем использовать множество дополнительных GET параметров, применяемых для постраничного вывода, сортировки, фильтрации, поиска etc, но они должны быть опциональными, т.е. эти параметры не должны передаваться как часть пути!

Элементы коллекции

Для обращения к конкретному элементу коллекции мы используем в маршруте его уникальный идентификатор /users/25 . Это и есть уникальный путь к нему. Для работы с объектом применимы методы GET (получение объекта), PUT/PATCH (изменение) и DELETE (удаление).

Уникальные объекты

Во множестве сервисов существуют уникальные для текущего пользователя объекты, например профиль текущего пользователя /profile , или персональные настройки /settings . Разумеется, с одной стороны, это элементы одной из коллекций, но они являются отправной точкой в использовании нашего Web API клиентским приложением, и к тому же позволяют намного более широкий спектр операций над данными. При этом коллекция, хранящая пользовательские настройки может быть вообще недоступна из соображений безопасности и конфиденциальности данных.

Свойства объектов и коллекций

Для того, чтобы добраться до любого из свойств объекта напрямую, достаточно добавить к пути до объекта имя свойства, например получить имя пользователя /users/25/name . К свойству применимы методы GET (получение значения) и PUT/PATCH (изменение значения). Метод DELETE не применим, т.к. свойство является структурной частью объекта, как формализованной единицы данных.

В предыдущей части мы говорили о том, что у коллекций, как и у объектов, могут быть собственные свойства. На моей памяти мне пригодилось только свойство count, но ваше приложение может быть более сложным и специфичным. Пути к свойствам коллекций строятся по тому же принципу, что и к свойствам их элементов: /users/count . Для свойств коллекций применим только метод GET (получение свойства), т.к. коллекция – это только интерфейс для доступа к списку.

Коллекции связанных объектов

Одной из разновидностей свойств объектов могут быть связанные объекты или коллекции связанных объектов. Такие сущности, как правило, не являются собственным свойством объекта, а лишь отсылками к его связям с другими сущностями. Например, перечень ролей, которые были присвоены пользователю /users/25/roles . По поводу работы с вложенными объектами и коллекциями мы подробно поговорим в одной из следующих частей, а на данном этапе нам достаточно того, что мы имеем возможность обращаться к ним напрямую, как к любому другому свойству объекта.

Функции объектов и коллекций

Для построения пути к интерфейсу вызова функции у коллекции или объекта мы используем тот же самый подход, что и для обращения к свойству. Например, для объекта /users/25/sendPasswordReminder или коллекции /users/disableUnconfirmed . Для вызовов функций мы в любом случае используем метод POST. Почему? Напомню, что в классическом REST не существует специального глагола для вызова функций, а потому нам придется использовать один из существующих. На мой взгляд, для этого больше всего подходит метод POST т.к. он позволяет передавать на сервер необходимые аргументы, не является идемпотентным (возвращающим один и тот же результат при многократном обращении) и наиболее абстрактен по семантике.

Надеюсь, что все более-менее уложилось в систему �� В следующей части мы поговорим подробнее о запросах и ответах, их форматах, кодах статусов.

Приближение третье: Запросы и ответы

В предыдущих приближениях я рассказал о том, как пришла идея собрать и обобщить имеющийся опыт разработки web API. В первой части я постарался описать, с какими видами ресурсов и операций над ними мы имеем дело при проектировании web API. Во второй части были затронуты вопросы построения уникальных URL для обращения к этим ресурсам. А в этом приближении я попробую описать возможные варианты запросов и ответов.

Универсальный ответ

Мы уже проговаривали, что конкретный формат общения сервера с клиентом может быть любым на усмотрение разработчика. Для меня наиболее удобным и наглядным кажется формат JSON, хотя в реальном приложении может быть реализована поддержка нескольких форматов. Сейчас же сосредоточимся на структуре и необходимых атрибутах объекта ответа. Да, все данные, возвращаемые сервером, мы будем оборачивать в специальный контейнер — универсальный объект ответа, который будет содержать всю необходимую сервисную информацию для его дальнейшей обработки. Итак, что это за информация:

Success — маркер успешности выполнения запроса

Для того, чтобы при получении ответа от сервера сразу понять, увенчался ли запрос успехом, и передать его соответствующему обработчику, достаточно использовать маркер успешности «success». Самый простой ответ сервера, не содержащий никаких данных, будет выглядеть так:

Error — сведения об ошибке

В случае, если выполнение запроса завершилось неудачей — о причинах и разновидностях отрицательных ответов сервера поговорим чуть позже, — к ответу добавляется атрибут «error», содержащий в себе HTTP-код статуса и текст сообщения об ошибке. Прошу не путать с сообщениями об ошибках валидации данных для конкретных полей. Правильнее всего, на мой взгляд, возвращать код статуса и в заголовке ответа, но я встречал и другой подход — в заголовке всегда возвращать статус 200 (успех), а детали и возможные данные об ошибках передавать в теле ответа.

Data — данные, возвращаемые сервером

Большинство ответов сервера призваны возвращать данные. В зависимости от типа запроса и его успеха ожидаемый набор данных будет разным, тем не менее атрибут«data» будет присутствовать в подавляющем большинстве ответов.

Пример возвращаемых данных в случае успеха. В данном случае ответ содержит запрашиваемый объект user.

Пример возвращаемых данных в случае ошибки. В данном случае содержит имена полей и сообщения об ошибках валидации.

Pagination — сведения, необходимые для организации постраничной навигации

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

Минимальный набор значений для пагинации состоит из:

  • общего числа записей;
  • числа страниц;
  • номера текущей страницы;
  • числа записей на странице;
  • максимального числа записей на странице, поддерживаемого серверной стороной.

Некоторые разработчики web API также включают в пагинацию набор готовых ссылок на соседние страницы, а также первую, последнюю и текущую.

Цукерберг рекомендует:  Rstudio - R язык программирования. Пара проблем новичка.

Работа над ошибками

Как уже упоминалось выше, не все запросы к web API завершаются успехом, но это тоже часть игры. Система информирования об ошибках является мощным инструментом, облегчающим работу клиента и направляющим клиентское приложение по правильному пути. Слово «ошибка» в этом контексте не совсем уместно. Здесь больше подойдёт слово исключение, так как на самом деле запрос успешно получен, проанализирован, и на него возвращается адекватный ответ, объясняющий, почему запрос не может быть выполнен.

Каковы же потенциальные причины получаемых исключений?

500 Internal server error — всё сломалось, но мы скоро починим

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

400 Bad request — а теперь у вас всё сломалось

Ответ прямо противоположный предыдущему. Возвращается в тех случаях, когда клиентское приложение отправляет запрос, который в принципе не может быть корректно обработан, не содержит обязательных параметров или имеет синтаксические ошибки. Обычно это лечится повторным прочтением документации к web API.

401 Unauthorized — незнакомец, назови себя

Для доступа к этому ресурсу требуется авторизация. Разумеется, наличие авторизации не гарантирует того, что ресурс станет доступным, но не авторизовавшись, вы точно этого не узнаете. Возникает, например, при попытке обратиться к закрытой части API или при истечении срока действия текущего токена.

403 Forbidden — вам сюда нельзя

Запрашиваемый ресурс существует, но у пользователя недостаточно прав на его просмотр или модификацию.

404 Not found — по этому адресу никто не живёт

Такой ответ возвращается, как правило, в трёх случаях: путь к ресурсу неверен (ошибочен), запрашиваемый ресурс был удалён и перестал существовать, права текущего пользователя не позволяют ему знать о существовании запрашиваемого ресурса. Например, пока просматривали список товаров, один из них внезапно вышел из моды и был удалён.

405 Method not allowed — нельзя такое делать


Эта разновидность исключения напрямую связана с использованным при запросе глаголом (GET, PUT, POST, DELETE), который, в свою очередь, свидетельствует о действии, которое мы пытаемся совершить с ресурсом. Если запрошенный ресурс не поддерживает указанное действие, сервер говорит об этом прямо.

422 Unprocessable entity — исправьте и пришлите снова

Одно из самых полезных исключений. Возвращается каждый раз, когда в данных запроса существуют логические ошибки. Под данными запроса мы подразумеваем либо набор параметров и соответствующих им значений, переданных методом GET, либо поля объекта, передаваемого в теле запроса методами POST, PUT и DELETE. Если данные не прошли валидацию, сервер в секции «data» возвращает отчет о том, какие именно параметры невалидны и почему.

Протокол HTTP поддерживает намного большее число различных статус-кодов на все случаи жизни, но на практике они используются редко и в контексте web API не несут практической пользы. На моей памяти мне не приходилось выходить за пределы вышеперечисленного списка исключений.

Запросы

Получение элементов коллекции

Одним из наиболее частотных запросов является запрос на получение элементов коллекции. Информационные ленты, списки товаров, различные информационные и статистические таблицы и многое другое клиентское приложение отображает посредством обращения к коллекционным ресурсам. Для осуществления этого запроса мы обращаемся к коллекции, используя метод GET и передавая в строке запроса дополнительные параметры. Как мы уже обозначили выше, в качестве ответа мы ожидаем получить массив однородных элементов коллекции и информацию, необходимую для пагинации — подгрузки продолжения списка или же конкретной его страницы. Содержимое выборки может быть особым способом ограничено и отсортировано с помощью передачи дополнительных параметров. О них и пойдёт речь далее.

Постраничная навигация

page — параметр указывает на то, какая страница должна быть отображена. Если этот параметр не передан, то отображается первая страница. Из первого же успешного ответа сервера будет ясно, сколько страниц имеет коллекция при текущих параметрах фильтрации. Если значение превышает максимальное число страниц, то разумнее всего вернуть ошибку 404 Not found.

perPage — указывает на желаемое число элементов на странице. Как правило, API имеет собственное значение по умолчанию, которое возвращает в качестве поля perPage в секции pagination, но в ряде случаев позволяет увеличивать это значение до разумных пределов, предоставив максимальное значение maxPerPage:

Сортировка результатов

Зачастую результаты выборки требуется упорядочить по возрастанию или убыванию значений определенных полей, которые поддерживают сравнительную (для числовых полей) или алфавитную (для строковых полей) сортировку. Например, нам нужно упорядочить список пользователей по имени или товары по цене. Помимо этого мы можем задать направление сортировки от A до Я или в обратном направлении, причём разное для разных полей.

sortBy — существует несколько подходов к передаче данных о сложной сортировке в GET параметрах. Здесь необходимо четко указать порядок сортировки и направление.

В некоторых API это предлагается сделать в виде строки:

В других вариантах предлагается использовать массив:

В целом оба варианта равносильны, так как передают одни и те же инструкции. На мой взгляд, вариант с массивом более универсален, но тут, как говорится, на вкус и цвет…

Простая фильтрация по значению

Для того, чтобы отфильтровать выборку по значению какого либо поля, в большинстве случаев достаточно передать в качестве фильтрующего параметра имя поля и требуемое значение. Например, мы хотим отфильтровать статьи по ID автора:

Усложнённые варианты фильтрации

Многие интерфейсы требуют более сложной системы фильтрации и поиска. Перечислю основные и наиболее часто встречаемые варианты фильтрации.

Фильтрация по верхней и нижней границе с использованием операторов сравнения from (больше или равно), higher (больше), to (меньше или равно), lower (меньше). Применяется к полям, значения которых поддаются ранжированию.

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

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

Именованные фильтры

В некоторых случаях, когда определенные наборы фильтрационных параметров часто употребимы и подразумеваются системой как нечто целостное, особенно если затрагивают внутреннюю, зачастую сложную механику формирования выборки, целесообразно сгруппировать их в так называемые именованные фильтры. Достаточно передать в запросе имя фильтра, и система построит выборку автоматически.

Именованные фильтры могут также иметь свои параметры.

В этом подразделе я постарался рассказать о наиболее популярных вариантах и способах получения требуемой выборки. Скорее всего, в вашей практике наберется намного больше примеров и нюансов касаемо этой темы. Если у вас есть, чем дополнить мой материал, я буду только рад. Тем временем пост уже разросся до солидных масштабов, так что другие виды запросов мы разберём в следующем приближении.

За перевод материала выражаем благодарность международной IT-компании Noveo.

Как разработать для не CRUD операций в Web API MVC4 в?

Я начинаю новый проект с использованием ASP.NET MVC4 и Visual Studio 2012. С точкой зрения дизайна API, большинство примеров сосредоточиться на основных операциях CRUD с помощью PUT, GET, POST и DELETE глаголов на лицах (как и следовало ожидать). Я читал следующее:

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

Это больше подхода в стиле RPC; из которых я вывод, что они рекомендуют два маршрута с двумя контроллерами, чтобы разделить каждую операцию:

Возможно, что-то вроде для родительского объекта CRUD:

и для дочернего объекта CRUD:

С точки зрения данных / это делает сырого общий смысл. Однако то , что о том, когда вы хотите , чтобы выполнить операцию , не Crud на лице (то есть, /User/NoahBawdy/SignIn или /User/NoahBawdy/ChangePassword )? Я мог видеть это быть PUT или действие POST, но это действительно требует это собственный контроллер? Это неправильный способ приблизиться к конструкции API для этих типов операций?

Любое понимание очень ценится как всегда.

Вы подняли некоторые интересные моменты в вашем посте. Я столкнулся с аналогичной проблемой на проект я работаю, и мой подход заключается в добавлении параметра действий по конфигурации маршрутизации.

С учетом этого изменения я мог бы добавить любой метод к контроллеру и вызвать его от клиента. Это позволяет избежать необходимости указывать несколько контроллеров для методов, которые концептуально принадлежит в том же контроллере.

Как за час создать сайт на ASP.NET

Что делать, если сайт нужен был вчера, но писать его еще даже не начали? Самое время воспользоваться ASP.NET Web Forms!

ASP.NET Web Forms позволяет даже новичку быстро создать простой сайт. Если не планировать очень широкий функционал, то вполне можно справиться и за час.

Рассказываем, как это сделать, шаг за шагом.

Создание проекта ASP.NET в Visual Studio

Для начала создайте проект ASP.NET:

Пишет о разработке сайтов, в свободное время создает игры. Мечтает открыть свою студию и выпускать ламповые RPG.

Затем укажите его имя:

А потом выберите модель Web Forms:

Как только Visual Studio подготовит шаблон проекта, его можно будет запустить, чтобы проверить. Для этого нажмите кнопку IIS Express:

Visual Studio скомпилирует все файлы, запустит сайт и откроет его в браузере по умолчанию. Если сайт не открылся, на него можно перейти самостоятельно. Для этого в трее найдите иконку IIS Express и посмотрите там адрес сайта. Он должен быть примерно таким: http://localhost:5000 (цифры в конце могут отличаться).

Вот как выглядит шаблон сайта:

Тут уже есть несколько страниц и немного стилей. Каждая страница состоит из трех файлов:

  • Page.aspx. Файл с HTML-кодом страницы.
  • Page.aspx.cs. Класс, который отвечает за логику работы страницы.
  • Page.aspx.designer.cs. Класс, который служит прослойкой между HTML и C#.

Вот как выглядит About.aspx этого проекта:

А вот класс, который занимается логикой:

В About.aspx находится только фрагмент готовой страницы. Остальная часть располагается в файле Site.Master или Site.Mobile.Master. Контент из тега (About.aspx) встраивается на место тега (Site.Master) с идентичным ID:

Так на одной странице может быть несколько таких плейсхолдеров с разными ID: MainContent, RelevantArticles, Comments и так далее. Это позволяет легко управлять отдельными блоками страницы (как при использовании функции include() в PHP).

Как создать страницу в ASP.NET Web Forms

Чтобы создать другие страницы, нажмите правой кнопкой на название проекта и в контекстном меню выберите Add —> Web Form:

Будет создана страница с таким кодом:

Как добавить ссылку в меню


Меню находится в Site.Master:

В начале ссылки ставится знак «

», а название файла указывается без расширения.

Обратите внимание, что в других файлах знак тильды в начале ставить не нужно.

Как вставить HTML-код в страницу

Допустим, есть такая строка:

Если ее вывести, то пользователь увидит текст «Hello, World!», а не жирный шрифт. Чтобы передать в HTML-код строку вместе с тегом, нужно использовать не обычный тип string, а HtmlString:

Получение данных из URL

Дальше нужно получить данные из URL. Например, в ссылке /Article? >

Получить это свойство можно с помощью статического класса Request (в нем хранятся и другие данные о запросе пользователя):

Перед тем как использовать значение, нужно проверить, существует ли оно, а потом привести его к необходимому типу:

Теперь значение можно использовать, чтобы открывать статьи по ссылке.

Вывод информации из базы данных

Описанного выше достаточно, чтобы добавить возможность получать и выводить статьи из базы данных. Для этого создайте класс Article:

Затем добавьте таблицу в базе данных с идентичными полями:

Теперь можно создать класс для получения данных из СУБД:

Теперь можно перейти в код страницы и добавить получение и вывод статей в методе Page_OnLoad():

Вот как это работает:

Заключение

Вот так примерно за час создается простой сайт с подключением к базе данных и выводом статей. Основная логика готова, но, чтобы выложить его в сеть, нужно еще позаботиться:

  • о внешнем виде;
  • ограничении количества выводимых статей;
  • админской панели;
  • наполнении страниц и других важных вещах.

Если вы хотите научиться создавать более сложные сайты с помощью ASP.NET, записывайтесь на курс «Профессия C#-разработчик», на котором вы освоите C# и ASP.NET, а также соберете портфолио из проектов для компьютеров и веб-проектов.

Профессия С#-разработчик

130 часов — и вы научитесь писать программы на языке, созданном Microsoft. В ы создадите 5 проектов для портфолио, даже если до этого никогда не программировали. После обучения — гарантированное трудоустройство.

C# с нуля

Просьба людям, которые хоть как-то знакомы с программированием пройти мимо этого поста.

Данный пост не сделает из вас профессионального программиста, он просто подскажет вам с чего начать.

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

В конце каждой строки должен стоять знак ;

Каждая кавычка и скобка должна быть закрыта.

И начнем мы обучение сразу с переменных. Что такое переменная? Это область памяти в которой хранится какое-то значение. Сегодня я расскажу только о 4 типах переменных.

Переменная Int может хранить любое (на самом деле нет) число без дробной части.

Переменная string хранит любой текст. Он обязательно должен быть указан в двойных кавычках.

Переменная char может хранить в себе любой символ, но только один. Должен быть указан в одинарных кавычках.

И переменная bool может хранить в себе только значения true или false.

Любую строку написанную ниже можно условно разделить на 3 части:

Тип переменной (ниже выделена синим), ее название (выделено белым)(может быть почти любым и выбирается вами, но не может повторяться) и значение переменной (в данном случае указано после знака равно).

Все строки подчеркнуты зеленым, из-за того, что у нас они нигде не используются.

Переменная может быть инициализирована (ей может быть присвоено значение) сразу (как на изображении выше) или уже после ее создания (смотрим ниже).

В первой строчке мы создаем переменную (объявляем ее). Пока что она не несет в себе никакой информации. Во второй и последующих мы меняем ее значения.

Чем отличается = от ==? = — это знак присвоения, а == — знак сравнения.

В первом случае мы присваиваем переменной num значение 5 (если переменная была равна 40, то теперь она равняется 5), а во втором случае мы проверяем не равна ли переменная num 5 (если до этого она была равна 40, то она и останется такой же).

Условные операторы (if else)

text = «Переменная равна 2»;

text = «Переменная не равна 2»;

Т.е на русском конструкция с if else имеет вид

Если выполняется (какое-то условие)<

то происходит что-то

если не выполняется <

то происходит что-то другое

Вернемся к операторам сравнения:

if(num!=4) если num не равно 4(равно чему угодно кроме 4).

Сразу привыкайте к тому, что вам очень много придется пользоваться гуглом.

Сейчас мы сделаем первое приложение — счетчик нажатий (ничего проще я придумать не смог)

Вновь возвращаемся в первую вкладку. Про окно №3 можете забыть, оно вам на первое время не пригодится. Окно 5 разделено на 2 части. Слева названия, справа значения. Нажав на название, мы можем увидеть в окне 6 описание свойства. Если мы хотим запустить наше приложение, нажимаем кнопку 4. Сейчас нужно открыть панель инструментов (2).

Добавляем кнопку (button) и надпись (label) (просто перетягиваем их). В окне свойств находим название этих элементов (название и текст — это не одно и то же (но в нашем случае они совпадают)). Итак, нам нужно детально продумать, то будет делать наше приложение. Оно должно менять текст надписи на число нажатий по кнопке. Для этого нам нужно как-то обработать нажатие на кнопку. Представим, что мы не знаем, как это сделать. Идем в гугл. Пишем вопрос «c# как обработать нажатие на кнопку», нажимаем на первую же ссылку и.

Дважды наживаем на кнопку и видим, что у нас появился новый метод. Нам нужно получить количество нажатий. Количество — это число, значит нам нужно создать новую переменную int. Если мы ее создадим в методе button1_click, то у нас она будет создаваться каждый раз заново при клике на кнопку. Значит нужно создать переменную за пределами методов (если мы создадим ее в любом другом методе, то она будет доступна только в нем) и сразу присвоить значение 0, потому что при запуске программы, сразу пользователем не будет сделано ни одного клика. При клике на кнопку значение должно увеличиваться на 1, значит этот код нужно написать в методе button1_click, и значение должно сразу выводиться в label1. Как это сделать? Используем гугл. Для вывода текста мы можем использовать только тип переменной string. Но так, как у нас тип int нам нужно его преобразовать. Опять обращаемся к гуглу. Еще раз повторяю , что цель этого поста не обучить вас программированию, а указать вам, с чего начать.

Если вы хотите быстро научиться программировать, что следует сразу начать создавать какую-нибудь программу. Если она будет достаточно сложной, то за время ее создания вы узнаете почти всю информацию, которую вы могли бы узнать из книг и уроков по программированию, но при этом потратите значительно меньше времени.

C#, обращение к REST API¶


Пример online-переводчика, который использует класс WebRequest для обращения к API Яндекс.Переводчика.

Для удобства в программе используется простой GUI интерфейс.

Введение¶

Онлайн переводчик, в первую очередь, это программа, позволяющая переводить текст с иностранного языка и наоборот, в режиме онлайн. Перевод может быть абсолютно разным, будь-то это фраза, словосочетание, либо большой и длинный литературный текст. Также онлайн переводчик может служить помощником в переписке с зарубежными друзьями или коллегами, в переводе каких-либо иностранных статей. В конце концов, переводчик может быть полезен в том случае, когда Вы пытаетесь что-то кому-то сказать на иностранном языке.

Описание¶

Для создания программы-переводчика использовалось приложение Visual Studio 2013 , а также дополнительный фреймворк Json.NET .

Приложение написано на WindowsForms , на языке C# . Для создания дизайна приложения была использована программа Adobe Photoshop CS5.

С помощью данного приложения можно перевести текст на 9 различных языков: Английский, Русский, Иврит, Испанский, Итальянский, Китайский, Немецкий, Французский, Японский. Перевод осуществляется с помощью веб-запросов к API Яндекс.Переводчика.

Для перевода текста достаточно ввести исходный текст в первое окно, указать начальный язык, а также требуемый язык перевода во всплывающих боксах. Для быстрой смены выбранных языков между собой можно воспользоваться центральной кнопкой в виде двух стрелок. Как только Вы выбрали нужные языки и ввели необходимый текст, нажмите кнопку «Перевод». Переведенный текст отобразится во втором окне.

Получение OAuth ключа¶

Чтобы работать с API Яндекс Переводчика, потребовалось получить API-ключ(OAuth токен доступа).

OAuth-токен ― это специальный код, разрешающий доступ к данным конкретного пользователя. Для каждого пользователя (логина в Яндекс.Директе, от имени которого осуществляются запросы к API) необходимо получить отдельный токен, который следует указывать при вызове методов.

Разработка приложения¶

Расположение объектов приложения было произведено при помощи WindowsForms, а затем оформлено при помощи изображений, созданных в Adobe Photoshop CS5. Код приложения написан на языке программирования C#.

Приложение состоит из трех классов: Form1, Translate и Translation.

Form1¶

В классе Form1 описаны объекты приложения и действия над ними. Приложение состоит из двух кнопок, реализованных через pictureBox; Двух текстбоксов, а также трех комбобоксов (всплывающие списки). В двух комбобоксах пользователь осуществляет выбор необходимого языка для перевода. Еще один комбобокс не отображается на экране, а служит лишь для осуществления быстрой смены двух выбранных языков между собой.

При нажатии на кнопку «Перевод» (pictureBox1) происходит вызов функции TranslateText, которая посылает веб-запрос. Однако, при отправлении запроса, требуется указать коды языков для перевода, например(“ru-en” или “it-ru”). Для этого была написана структура switch-case, которая, исходя из выбранных языков в комбобоксах, составляет необходимую нам строку с кодами языков.

Translate¶

Класс Translate описывает веб-запрос к серверам Яндекс.Переводчика и десериализацию JSON полученного ответа. Запрос к API переводчика содержит ряд обязательных параметров – это:

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

Так как ответ приходит в виде структуры данных JSON, требуется его распарсить. Для этого был установлен дополнительный фреймворк Json.NET и подключена библиотека Newtonsoft.Json .

Translation¶

Данных класс описывает структуру JSON-ответа на запрос к API переводчика.

BestProg

Пример создания Web -приложения в C#

Содержание

Условие задачи

Дано три стороны треугольника: a , b , c .

Используя формулу Герона, разработать приложение, которое находит площадь треугольника. Приложение реализовать как Web-application .

Цукерберг рекомендует:  Error - Помогите решить проблему с запуском Android Studio на Ubuntu

Формула Герона имеет вид:

где p – полупериметр:

a, b, c – длина сторон треугольника.

Выполнение

1. Запустить MS Visual Studio

Пример создания приложения в MS Visual Studio по шаблону Windows Forms Application подробно описывается в теме:

2. Создание Web-приложения

Приложения типа Web могут вызываться из любого компьютера, подключенного к сети Internet. Для открытия такого приложения используется Web -браузер (например Opera , Google Chrome , Internet Explorer и другие).

Ниже указаны два способа создания Web -приложения в MS Visual Studio .

2.1. Создание Web-приложения (способ № 1)

Для этого способа, чтобы создать Web -приложение, нужно сначала вызвать команду (рис. 1):

Рис. 1. Команда создания нового веб-сайта

В открывшемся окне (рис. 2), нужно выбрать шаблон « C#» и вложение « ASP .NET Empty Web Site «. Можно также указать путь, где будут созданы рабочие файлы приложения (кнопка « Browse… «).

Например, в нашем случае, файлы будут сохраняться в папке

Место расположения файлов указывается в поле « Web-location» . Доступны три способа размещения файлов:

  • файловая система ( File system );
  • http -соединение;
  • ftp -соединение.

Выбираем « File system «. В этом случае файлы приложения будут размещаться на локальном сервере ( localhost ), который создается системой. Это означает, что программа-клиент (наше приложение) и программа-сервер (условно отдаленный компьютер в сети) размещены на одном и том же (домашнем) компьютере. Фактически localhost – это IP -адрес, с помощью которого компьютер может обратиться в сети к самому себе, независимо от наличия или вида компьютерной сети.

Рис. 2. Создание Web-сайта

2.2. Создание Web-приложения (способ № 2)

Существует также и другой способ создания Web -приложения с помощью команды (рис. 3)

Рис. 3. Команда создания нового проекта

После этого откроется окно (рис. 4), в котором нужно выбрать шаблон « Visual C# » и тип проекта « ASP .NET Web Application «.

Рис. 4. Команда создания Web-приложения

3. Создание приложения как веб-сайта

Для решения задачи выбираем первый способ.


После выполненных операций создается решение ( Solution ), в котором есть один проект типа веб-сайт (рис. 5).

Рис. 5. Окно « Solution Explorer » после создания веб-сайта

Если запустить на выполнение данный проект, то внизу в правой части экрана ( SySTray ) отобразится окно загруженного локального сервера (рис. 6).

Рис. 6. Загрузка локального сервера для выполнения приложения

Следующим отобразится окно, изображенное на рисунке 7. В этом окне нужно подтвердить на кнопке « ОК «, чтобы модифицировать файл « Web.config » таким образом, чтобы можно было выполнять наше приложение.

Рис. 7. Запрос к модификации файла « Web.config «

В результате запуска, в активном веб-браузере откроется страница с приблизительно таким текстом (рис. 8):

Рис. 8. Текст, который выводится в веб-браузере

Для завершения работы приложения, нужно в MS Visual Studio вызвать команду « Stop Debugging » из меню « Debug «.

4. Добавление формы к приложению

Добавим новую форму к Web -приложению.

Для этого нужно выделить название приложения в Solution Explorer , сделать клик правой кнопкой «мыши» и в контекстном меню выбрать команду « Add New Item… » (рис. 9).

Рис. 9. Команда « Add New Item… «

Существует и другой способ добавления формы – вызов команды « Add New Item… » из меню « Website «.

В результате откроется окно « Add New Item «. В этом окне нужно выбрать шаблон « Visual C# » и элемент « Web Form » (рис. 10). Имя формы ( Name ) оставляем без изменений « Default.aspx «.

Рис. 10. Добавление новой формы

После добавления, в Solution Explorer можно увидеть дополнительные два файла (рис. 11):

  • « Default.aspx » – файл формы в терминологии HTML языка разметки гипертекста;
  • « Default.aspx.c s» – файл формы, который отвечает программному коду на языке C# .

С помощью этих двух файлов можно изменять внешний вид формы и организовывать работу в ней.

Рис. 11. Файлы формы « Default.aspx » и « Default.aspx.cs «

С помощью кнопок Design и Source можно переключаться между режимом проектирования и режимом кода страницы Default.aspx (рис. 12).

Рис. 12. Режимы проектирования ( Design ) и кода ( Source )

5. Конструирование формы

Согласно с условием задачи, форма должна содержать следующие элементы управления:

  • три поля ввода для ввода значений a , b , с ;
  • текстовые строки для вывода сообщений;
  • кнопку для задания начала вычисления;
  • текстовую строку, выводящую результат вычисления.

5.1. Изменение размеров формы

Переходим в режим проектирования с помощью кнопки « Design » (рис. 12).

С помощью «мышки» увеличиваем размер формы, как показано на рисунке 13 (необязательно).

Рис. 13. Изменение размеров формы в режиме проектирования

5.2. Формирование информационных сообщений и вывод на форму элементов управления

С помощью «мышки» можно выносить на форму различные элементы управления. Работа с Web -формой есть точно такая же как и с формой типа Windows Forms . Текст на форме можно вносить непосредственно.

Для нашей задачи нужно вынести на форму следующие элементы управления:

  • три элемента управления типа Label для обозначения « а = «, « b = «, « c = «;
  • один элемент управления типа Button ;
  • три элемента управления типа TextBox ;
  • один элемент управления типа Label для вывода результата.

При вынесении элемента управления в правой нижней части экрана (окно Properties ) можно изменять свойства элементов управления (рис. 14).

Рис. 14. Изменение свойств элементов управления Web -формы

В целом, после построения, форма приложения должна иметь вид как показано на рисунке 15.

Рис. 15. Форма приложения в режиме проектирования

6. Программирование события клика на кнопке « Calculate «

Последним шагом есть программирование события, которое будет генерироваться при клике на кнопке « Calculate «. Для Web -приложений это осуществляется стандартным для MS Visual Studio способом. Программный код обработки события будет сформирован в файле « Default.aspx.cs «.

Таким образом, выделяем элемент управления Button1 . В списке свойств Properties переходим к вкладке Events . В вкладке Events делаем двойной клик «мышкой» напротив названия события « OnClick «. Система откроет файл « Default.aspx.cs » со следующим кодом:

В обработчик события Button1_Click(…) вводим код расчета площади треугольника по трем сторонам. В целом текст модуля « Default.aspx.cs » будет иметь вид.

После запуска приложения на выполнение можно проконтролировать его работу в Web -браузере (рис. 16).

Рис. 16. Выполнение Web -приложения в браузере Opera

После этого можно выносить приложение на Web-сервер. Но это уже другая тема.

Основы API. Создание собственного API

Введение

Работая с API, можно испытывать одновременно радость и разочарование. С одной стороны, взаимодействуя с другими приложениями, вы можете сильно увеличить охват аудитории и «вау-эффект» вашего приложения. С другой, это включает в себя чтения тонны документации, изучение стратегий аутентификации и разбор неинформативных (или даже отсутствующих) сообщений об ошибках.

Прежде всего, если вы до сих пор не до конца понимаете, что же такое API (Application Programming Interface — интерфейс программирования приложений), прочтите объяснение от Skillcrush, а затем первую часть этой статьи, чтоб наверстать упущенное.

«API» невероятно обширная концепция — каждый раз, когда ваше приложение «общается» с другим приложением, это происходит через некий API. Компоненты внутри вашего собственного приложения, вроде разных частей Rails, также общаются друг с другом через API. Они являются более или менее независимыми субприложениями, которые передают данные, необходимые каждому из них для выполнения собственных специфических задач. В мире приложений все является API!

Когда вы создаете приложения с более динамической фронтенд-функциональностью (как одностраничные Javascript-приложения, так и простые приложения с отдельными AJAX-вызовами), они будут общаться с Rails-бэкендом через ваш собственный API, который в действительности просто дополнительная пара-тройка строк кода, говорящая вашим контроллерам, как отдать JSON или XML вместо HTML.

В этом уроке вы изучите как создать свой собственный API. В последующих уроках мы осветим как взаимодействовать с API других приложений. Уроки должны стать хорошим трамплином для изучения этой темы, но вряд ли смогут полностью охватить все случаи. Большая часть работы с API — это умение читать их документацию и разбираться, чего они от вас хотят.

Пункты для размышления

Просмотрите вопросы и проверьте, знаете ли на них ответы. Проверьте себя снова после выполнения задания.


  • Как Rails понимает, какой тип файла вы ожидаете в ответ, когда посылаете HTTP-запрос.
  • В чем заключается цель метода #respond_to ?
  • Как вернуть объект пользователя (User), при этом указать атрибуты, которые не хотите включать в этот объект (то есть, вы не можете просто вернуть User.first )?
  • Назовите 2 шага, выполняемых «за кулисами» метода #to_json .
  • Как указать действию контроллера, что требуется рендерить лишь сообщение об ошибке?
  • Как создать свое собственное сообщение об ошибке?
  • Почему вы не можете использовать методы аутентификации контроллера, основанные на сессиях, если хотите позволить программно подключаться к вашему API?
  • Что такое «Сервис-ориентированная архитектура»?

Основы API

Ваше Rails-приложение на самом деле уже является API, хотя вы могли не думать о нем как об API. Веб-браузер, запускаемый вашими пользователями, также является программой, так что он фактически отправляет API-запрос вашему Rails-приложению, когда пользователь открывает новую страницу. Мы привыкли так думать потому, что рендеринг HTML-шаблонов настолько распространенная задача, что мы просто зашиваем этот функционал в наши серверные программы в качестве стандартного типа ответа, и все остальное считаем чем-то необычным.

Однако, часто вы хотите сделать запрос, который не требует переживать все головные боли от использования браузера. Вас может не заботить структура страницы (HTML), но взамен вы хотите получить чистые данные. Допустим, вы хотите получить список всех пользователей. Вы можете запросить что-то вроде http://yourapplication.com/users , что наверняка запустит действие #index и отрендерит список всех пользователей приложения.

Но зачем заморачиваться со всей этой лишней информацией, если все чего вы хотите — это получить список пользователей? Самым простым вариантом будет отправить запрос на тот же самый URL, указав ожидание JSON или XML ответа взамен. Если вы правильно настроите ваш Rails-контроллер, назад вы получите простой JSON объект-массив, содержащий всех пользователей. Прекрасно!

Тот же самый принцип применяется, когда вы общаетесь с внешним API. Скажем, вы хотите получить недавние «твиты» пользователя из Twitter. Вам потребуется лишь сообщить вашему Rails-приложению как взаимодействовать с API Twitter’а (т.е. аутентифицировать себя), отправить запрос и обработать набор «твитов», который будет возвращен.

Создание API

Вы можете захотеть сделать ваше Rails-приложение чистым бэкенд API для фронтенд веб-страниц, или просто захотите научиться посылать JSON, когда фронтенд запрашивает его. Этот раздел не осветит как создавать полноценные RESTful API с функциями аутентификации. Это плавное введение в обращение с вашим приложением как с API.

Основы

Если вы хотите, чтобы ваше Rails-приложение возвращало JSON вместо HTML, вам потребуется сказать вашему контроллеру, чтобы он это делал. Самое замечательное то, что одно и то же действие контроллера может возвращать различные типы в зависимости от того, делает ли ваш пользователь обычный запрос из браузера или обращается к API через командную строку. Это определяет какой тип запроса был сделан, основываясь на расширении запрашиваемого файла, например, example.xml или example.json .

Вы можете проверить, что Rails «думает» об ожидаемом вами типе файла, проверив серверный лог:

Первая строка говорит вам какой URL был запрошен, а вторая сообщает куда он был направлен и как Rails его обрабатывает. Если бы вы использовали расширение .json , то это выглядело бы так:

Если у вас есть запущенное тестовое приложение, попробуйте запросить различные URL. Если ваш контроллер не умеет их обрабатывать, то вы можете получить ошибку, но все равно должны видеть, что Rails понимает под вашими запросами.

Рендеринг JSON или XML

Когда вы решите, что хотите отвечать на запросы с помощью JSON или XML, вам потребуется сообщить вашему контроллеру, что нужно рендерить JSON или XML вместо HTML. Один из способов сделать это — использовать метод #respond_to :

В данном случае, #respond_to передает в блок объект формата, к которому вы можете приложить соответствующий вызов рендеринга. Если вы ничего не сделаете, будет рендериться html с использованием стандартного Rails-шаблона (в этом примере app/views/index.html.erb ).

Функция #render достаточно умна, чтобы понять, как рендерить широкий спектр форматов. Когда вы передаете ей ключ :json , она вызовет #to_json на значении, в данном примере на @users . Это преобразует ваш(и) Ruby-объект(ы) в JSON-строки, которые будут переданы запрашивающему приложению.

Таким образом, вы получаете свой API. Конечно, создание API может быть немного более сложным, если вы захотите делать какие-то необычные вещи, но все держится на основах.

Указание возвращаемых атрибутов

Допустим, вы хотите убедиться, что не возвращаете email-адрес пользователя вместе с объектом пользователя (User). В этом случае, вы захотите изменить атрибуты, которые будут возвращаться, модифицируя то, что делает метод #to_json .

Раньше вы бы просто переопределили метод #to_json своей версией, но теперь вам это не понадобится — в действительности, вы взамен переопределите метод #as_json . Метод #as_json используется в методе #to_json , так что его модификация неявно изменён результат #to_json , но довольно специфическим способом.

#to_json делает 2 вещи: запускает #as_json и получает хэш атрибутов, которые будут отрендерены в JSON. Затем он проводит рендеринг в JSON, используя ActiveSupport::json.encode . Так что, модифицируя #as_json , вы более конкретно указываете ту часть метода #to_json , которую в действительности хотите изменить.

В нашем случае, мы делаем это модифицируя #as_json в нашей модели так, чтобы возвращать лишь необходимые нам атрибуты:

Затем, в нашем контроллере лишь потребуется отрендерить JSON как обычно (в примере ниже всегда будет возвращаться JSON, независимо от того, был ли отправлен HTML-запрос или нет):

Заметьте, что вам не нужно самостоятельно вызывать #to_json , когда вы используете #render — он сделает это за вас.

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

Рендер ошибок или пустого ответа

Иногда вы хотите просто отправить код HTTP-ошибки без какого-либо тела ответа. Интернет-сообщество постоянно спорит о том, что является лучшей практикой на этот счет (посмотрите этот более старый блог для одного подхода и этот ответ на StackOverflow для другого направления ответов). Вот простой пример (мы просто рендерим ошибки в любой ситуации):

Создание динамических страниц ошибок

Вы можете создавать собственные страницы ошибок. Посмотрите этот пост блога.

Иногда Heroku может потребовать дополнительные шаги для корректного отображения ваших страниц с ошибками. Посмотрите их документацию по страницам ошибок здесь. Вам может потребоваться сперва удалить статичные страницы из директории app/public .

Обеспечение безопасности извне

Допустим, вы хотите позволить обращаться к API только если пользователь залогинен. Ваша существующая аутентификация в контроллере уже делает эту работу — просто убедитесь, что у вас установлен правильный #before_action (например, before_action :require_login ). Может потребоваться функционал, когда и залогиненный и не залогиненный пользователи могут просматривать страницу, но каждый должен видеть различные данные. Вы не хотите, чтобы незалогиненные пользователи имели возможность делать запросы к API для получения важных данных. Аналогично, вы не хотите давать возможность посещать определенные HTML-страницы неавторизованным пользователям.

Если вы хотите обрабатывать запросы из приложения, которое не является браузером (например, из командной строки), вы не можете полагаться на браузерные «куки» для аутентификации. Вот почему большинство API использует собственные токены как часть процесса аутентификации. Мы поговорим чуть больше о токенах в следующем уроке.

Следующие шаги

Теперь у вас есть навыки использования вашего Rails-приложения для отдачи не только HTML, но и любого другого формата. Если вы хотите пойти дальше и позволить другим разработчикам создавать что-то с использованием вашей платформы (например, чтобы они могли делать программные запросы вместо аутентификации в качестве пользователя), вам понадобится сделать вашу API-систему намного более надежной. Мы не будем освещать все это здесь, но посмотрите следующие материалы:

  • Статья Building Awesome Rails APIs содержит описание множества лучших подходов для движения от игрушечного приложения в сторону стандартов промышленных API.

Сервис-ориентированная архитектура

Пришло время представить архитектурный подход под именем «Сервис-ориентированная архитектура» (Service-Oriented Architecture, SOA). Основная идея заключается в том, что ваше приложение будет состоять из множества сервисов, вроде системы оплаты, регистрации пользователей, модуля рекомендаций и т.д. Вместо того, чтобы создавать все это внутри одного главного приложения, вы разбиваете подсистемы на полностью независимые кусочки, которые взаимодействуют друг с другом, используя внутренние API-интерфейсы.

Это хорошо по многим причинам. Благодаря тому, что каждый кусочек вашего приложения не заботится о том, как работают другие части, и знает только как запросить данные через их API, вы можете делать значительные изменения в коде сервиса, и все остальное приложение будет работать, как и прежде. Вы можете полностью заменить один сервис на другой, и, пока он взаимодействует, используя те же API-методы, это пройдет очень гладко. Вы можете использовать внешние API как часть вашего приложения (например, платежные системы) вместо написания собственного. Вы можете создать PHP-приложение, взаимодействующее с Python-приложением, взаимодействующим с Rails-приложением, и все будет работать, ведь они общаются между собой с помощью API.

Как правило, стараться делать максимально независимой каждую часть вашего приложения — хорошая идея. Концепция СОА подталкивает вас мыслить в рамках того, какие именно методы вы хотите предоставлять другим частям вашего приложения, и заодно это сделает ваш код лучше. Вдобавок, предполагая, что каждый крупный компонент вашего приложения независим, вы также сможете намного легче выделять проблемы и обрабатывать ошибки более осмысленно.

Использовать сервис-ориентированную архитектуру для целого приложения — это что-то вроде разбиения гигантского сложного Ruby-скрипта на изящные классы и методы, только в большем масштабе.

Одним из наиболее известных случаев перехода на сервис-ориентированную архитектуру является Amazon.com. Однажды в 2002 году, Джефф Безос прямо заявил, что все рабочие группы должны перейти на СОА, или будут уволены. Печально известный пост из блога сотрудника Google, предназначенный внутрикорпоративных целей, но случайно ставший открытым для публики, рассказывал о мощи Amazon с использованием СОА. Это отличное чтиво, так что обязательно его оцените, но основные тезисы письма Безоса вынесены в следующие цитаты из поста:

1) Все команды отныне предоставляют свои данные и функциональность через интерфейсы сервисов.

2) Команды должны взаимодействовать друг с другом посредством этих интерфейсов.

3) Иные формы межпроцессного взаимодействия запрещены: никаких прямых ссылок, никакого непосредственного чтения данных другой команды, никаких моделей общей памяти, никаких «бэкдоров» и тому подобного. Единственный разрешенный способ взаимодействия — обращение к интерфейсу сервисов через сеть.

4) Неважно какую технологию они используют. HTTP, Corba, Pubsub, собственные протоколы — без разницы. Безоса это не волнует.

5) Все интерфейсы сервисов, без исключения, должны быть изначально спроектированы с возможностью управления извне. То есть, команда должна планировать и проектировать так, чтобы быть в состоянии предоставить интерфейс разработчикам вне компании. Никаких исключений.

6) Любой проигнорировавший эти требования будет уволен.

СОА — это серьезное дело. Несомненно, есть много проблем, которые всплывают при ее использовании — посмотрите этот пост о «извлеченных уроках» Amazon — но она имеет невероятно много преимуществ.

Вы, наверняка, не будете сильно беспокоиться о СОА, пока создаете «игрушечные» приложения для самих себя, но этот вопрос определенно встанет перед вами, когда вы начнете работать на ИТ компанию, поэтому знакомство с ней — это хорошая практика.

Ваша цель

  1. Прочитайте раздел 7 руководства Rails по контроллерам, чтобы изучить рендеринг JSON и XML.
  2. Они не обязательны к просмотру (потому что они идут немного дальше, чем мы сейчас подготовлены), но, если вам интересно, взгляните на Railscasts в разделе Дополнительных ресурсов внизу урока, чтобы больше узнать о преимуществах API.

Заключение

Мы плотнее поработаем с вашим приложением как с API во время курса по Javascript. В этом курсе вы создадите несколько полноценных (фулл-стэк) приложений, использующих AJAX-вызовы для лучшего пользовательского интерфейса, что по факту включает в себя рендеринг XML или JSON данных взамен полноценной HTML-страницы. Затем вы создадите несколько одностраничных Javascript-приложений, которые полагаются на API, предоставляемом вашим Rails-приложением, для получения всех необходимых данных из БД, а во всем остальном работающих на стороне клиента (в браузере).

Лучший способ разобраться с API — создать и взаимодействовать с ним, на чем мы сфокусируемся в наших проектах.

В следующем уроке мы осветим процесс работы с API других разработчиков, что даст дополнительную «огневую мощь» вашему собственному приложению.

Дополнительные ресурсы

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

Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих