Привязка модели

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7

Последнее обновление: 29.11.2019

Привязка модели или Model binding представляет механизм сопоставления значений из HTTP-запроса с параметрами метода контроллера. При этом параметры могут представлять как простые типы (int, float и т.д.), так и более сложные типы данных, например, объекты классов.

Чтобы понять смысл привязки, посмотрим на примере. Пусть у нас есть следующий метод:

public class HomeController : Controller
{
	public IActionResult Index(string name)
	{
		// ...
	}
}

Допустим, на сервер приходит запрос http://localhost:8000/home/index?name=volga.

Для обслуживания данного запроса будет выбран метод Index контроллера Home. Поскольку данный метод принимает параметр с именем name, то механизм привязки по этому имени будет искать в среди пришедших данных значение с ключом name.

Чтобы найти и сопоставить данные из запроса с параметрами метода используется привязчик модели (model binder), который представляет объект интерфейса IModelBinder.

Для поиска значений привязчик модели используется следующие источники в порядке приоритета:

  • Данные форм. Хранятся в объекте Request.Form

  • Данные маршрута, то есть те данные, которые формируются в процессе сопоставления строки запроса маршруту. Хранятся в объекте RouteData.Values

  • Данные строки запроса. Хранятся в объекте Request.Query

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

То есть в нашем случае, когда на сервер придет запрос http://localhost:8000/home/index?name=volga, привязчик модели последовательно будет просматривать в поиске значения для параметра name следующие пути:

  • Request.Form["name"]

  • RouteData.Values["name"]

  • Request.Query["name"]

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

То есть, к примеру, пусть у нас есть следующая модель:

public class Phone
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Company Manufacturer { get; set; }
    public decimal Price { get; set; }
}
public class Company
{
	public int Id { get; set; }
    public string Name { get; set; }
}

И пусть метод принимает в качестве параметра объект данной модели:

public IActionResult Index(Phone myPhone)
{
	// ...
}

В этом случае привязчик модели последовательно будет просматривать те же источники в поиске значений для свойств объекта myPhone. Например, чтобы найти значение для свойства Name, привязчик будет искать значение по следующим ключам:

  • Request.Form["myPhone.Name"]

  • RouteData.Values["myPhone.Name"]

  • Request.Query["myPhone.Name"]

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

Для таких типов как коллекции привязчик модели ищет значения с ключами имя_параметра[index] или просто по индексу [index]. Если параметр представляет объект Dictionary, то привязчик модели также ищет в источниках запроса значения с ключами имя_параметра[ключ] или просто ищет по ключу: [ключ].

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

Когда значение для параметра метода найдено, привязчик модели прекращает поиск значений для этого параметра и переходит к поиску значений для следующего параметра. Вполне возможна ситуация, когда привязчик не найдет требуемое значение или найденное значение не сможет быть сконвертировано в нужный тип. Если параметр представляет ссылочный тип, свойство ModelState.IsValid в этом случае возвратит false. Это будет значить, что привязка завершилась с ошибкой, и полноценно параметры метода мы использовать не сможем.

Однако если же параметр представляет значимый тип (например, int), то ему присваивается значение по умолчанию. И даже если ему явным образом не передано значение, то ModelState.IsValid возвратит true

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850