Ну и давайте еще по теме контроллера подсвечу, какие есть нюансы при работе с моделями и контроллерами в нашем .NET.
Многие, наверное, знают про три ключевые вещи, которые делают из любого класса контроллер - это наследование от класса ControllerBase, имя класса, заканчивающееся на Controller, и использование атрибута [ApiController]
Но что, если я Вам скажу, что ни один из этих моментов не является обязательным. С именем все просто, при старте приложения фреймворк просто собирает все классы по соглашению с таким названием и пытается именно из них зарегистрировать контроллер. Собственно, вы можете любой класс явно указать, что его стоит рассмотреть как контроллер, повесив атрибут [Controller].
ControllerBase - использование этого класса встречается во всех книгах, гайдах и туториалах, да и в реальных приложениях тоже. Но, что интересно, он тоже не является обязательным. Да, он сильно упрощает жизнь за счет доступа к контексту и использованиие готовых реализаций IActionResult типа Ok(), NotFound(), BadRequest() и т.д. Но вы можете его и не наследовать, а просто добавить свойство в свой класс
[ControllerContext]
public ControllerContext Context { get; set; }
И все, вы можете снова использовать контекст в привычном виде
if (!Context.ModelState.IsValid)
{ return new BadRequestObjectResult(Context.ModelState); }
Тогда, наверное [ApiController] является обязательным? Нет, и он тоже не является обязательным. Также как и с прошлым примером, использование данного атрибута упрощает процесс, например за счет автоматической валидации модели. Если вы где-то видите внутри контроллера if (!ModelState.IsValid)
То там скорее всего как раз отказались от автоматической валидации (об этом планирую отдельно написать, если интересно будет) Ну и дополнительно это умный биндинг (долой [FromBody] или [FromQuery]), ну и кое что другое. В итоге, полноценный работающий контроллер может выглядеть так
[Controller]
[Route("api/hello")]
public class MySimpleHandler
{
[HttpGet]
public string SayHello() => "Hello, World!";
}
Многие, наверное, знают про три ключевые вещи, которые делают из любого класса контроллер - это наследование от класса ControllerBase, имя класса, заканчивающееся на Controller, и использование атрибута [ApiController]
Но что, если я Вам скажу, что ни один из этих моментов не является обязательным. С именем все просто, при старте приложения фреймворк просто собирает все классы по соглашению с таким названием и пытается именно из них зарегистрировать контроллер. Собственно, вы можете любой класс явно указать, что его стоит рассмотреть как контроллер, повесив атрибут [Controller].
ControllerBase - использование этого класса встречается во всех книгах, гайдах и туториалах, да и в реальных приложениях тоже. Но, что интересно, он тоже не является обязательным. Да, он сильно упрощает жизнь за счет доступа к контексту и использованиие готовых реализаций IActionResult типа Ok(), NotFound(), BadRequest() и т.д. Но вы можете его и не наследовать, а просто добавить свойство в свой класс
[ControllerContext]
public ControllerContext Context { get; set; }
И все, вы можете снова использовать контекст в привычном виде
if (!Context.ModelState.IsValid)
{ return new BadRequestObjectResult(Context.ModelState); }
Тогда, наверное [ApiController] является обязательным? Нет, и он тоже не является обязательным. Также как и с прошлым примером, использование данного атрибута упрощает процесс, например за счет автоматической валидации модели. Если вы где-то видите внутри контроллера if (!ModelState.IsValid)
То там скорее всего как раз отказались от автоматической валидации (об этом планирую отдельно написать, если интересно будет) Ну и дополнительно это умный биндинг (долой [FromBody] или [FromQuery]), ну и кое что другое. В итоге, полноценный работающий контроллер может выглядеть так
[Controller]
[Route("api/hello")]
public class MySimpleHandler
{
[HttpGet]
public string SayHello() => "Hello, World!";
}