Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
Привязка модели представляет получение данных из HTTP-запроса для создания объекта, передаваемого в качестве аргумента в метод контроллера. Для WebApi есть два способа привязки: привязка по параметрам и собственно привязка модели. С обоими способами привязки мы можем столкнуться уже в стандартном приложении WebApi.
Например, в приложении по умолчанию определен один маршрут, который принимает параметр id:
config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } );
И в контроллере определен такой метод, обрабатывающий запросы get:
public string Get(int id) { return "value"; }
При обращении по запросу api/values/4 приложение будет сопоставлять последний сегмент строки запроса с параметром id.
Теперь добавим в файл WebApiConfig.cs новый маршрут:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "TwoParamRoute", routeTemplate: "api/{controller}/{action}/{num1}/{num2}" ); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } }
Здесь добавлен новый маршрут, который принимает пять сегментов: слово "api", название контроллера, метода и два параметра.
Определим в стандартном контроллере ValuesController соотстветсвующий данному маршруту метод:
public int GetValue(int num1, int num2) { return num1 + num2; }
Если мы обратимся к методу по запросу /api/values/getvalue/2/3, то приложение свяжет два последние сегмента с параметрами num1 и num2 и в ответ отправит сумму этих чисел.
Привязка по параметрам используется, когда параметры методов представляют примитивные типы: int, string, char, bool, uint, byte, sbyte, short, ushort, long, ulong, float, double и decimal. Либо параметры должны представлять простые типы: TimeSpan, DateTime, Guid.
Значения для параметров берутся из сегментов маршрута, либо из строки запроса. Так, вместо выше использованного запроса мы могли бы обратиться к ресурсу с помощью следующей строки запроса: api/values/getvalue?num1=2&num2=3
Привязка модели используется для параметров, представляющих сложные типы данных. Если у нас есть метод, который получает в качестве параметра модель Book, то передача параметров через сегменты маршрута или строку запроса уже работать не будут. В этом случае нам надо будет оправить запрос POST со всеми данными, и тогда стандартные механизмы WebApi попробуют связать отправленные в теле запроса данные со свойствами модели Book:
public Book Post(Book b) { return b; }
Чтобы связать данные с моделью, применяется один из привязчиков моделей. В Web Api в пространстве имен System.Web.Http.ModelBinding.Binders
определено пять привязчиков моделей, которые покрывают большинство случаев, где необходима привязка:
ArrayModelBinder: используется для привязки к массивам
CollectionModelBinder: устанавливает привязку для строго типизированных коллекций
DictionaryModelBinder: устанавливает привязку для строго типизированных объектов Dictionary
MutableObjectModelBinder: связывает объекты
TypeConverterModelBinder: связывает объекты, применяя преобразование типов
Каждый привязчик моделей с помощью поставщиков значений берет из запроса данные и по ним создает объект модели. Сам процесс привязки разбивается на два этапа:
С помощью конструктора без параметров создается объект модели
Присвоение свойствам модели значений, полученных от поставщиков значений
Пространство имен System.Web.Http предоставляет нам ряд атрибутов, с помощью которых мы можем настроить механизм привязки.
Атрибут FromUri позволяет связать параметры с данным из строки запроса. Так, в предыдущем примере нам надо было отправить запрос POST для передачи на сервер данных о книге. Теперь же используем запрос GET и атрибут FromUri:
public Book GetValue([FromUri]Book b) { return b; }
Определим в WebApiConfig.cs соответствующий маршрут:
config.Routes.MapHttpRoute( name: "BookRoute", routeTemplate: "api/{controller}/{action}/{id}/{name}/{price}" );
Последние три сегмента маршрута называются также, как и свойства в модели Book, благодаря чему они могут быть автоматически сопоставлены.
Чтобы передать данные для параметра, мы можем отправить такой запрос: api/values/getvalue/4/чайка/200. В итоге браузер нам выдаст следующую информацию:
{ "Id": 4, "Name": "чайка", "Price": 200 }
Использование данного атрибута позволяет посылать серверу более сложные данные. Например, изменим метод следующим образом:
public string GetValue([FromUri]Book b, [FromUri]Author a) { return b.Name + " ("+a.AuthorName+")"; }
Теперь метод получает еще и автора, который может быть представлен следующей моделью:
public class Author { public int AuthorId { get; set; } public string AuthorName { get; set; } public int Year { get; set; } }
Изменим выше определенный маршрут:
config.Routes.MapHttpRoute( name: "BookRoute", routeTemplate: "api/{controller}/{action}/{id}/{name}/{price}/{authorid}/{authorname}/{year}" );
Важно, чтобы имена свойств обеих моделей не совпадали. И теперь мы можем обратиться к методу по запросу: api/values/getvalue/4/чайка/200/5/чехов/1860
Для привязки параметров к значениям, переданным в теле POST-запроса, используется атрибут FromBody. Хотя в большинстве случае он является избыточным.