Понимание параметров [HttpPost], [HttpGet] и сложных параметров Actionmethod в MVC
Я очень новичок в MVC - шаблоне дизайна, а также Framework. Я также не очень хорошо разбираюсь в основах форм ASP.NET. Однако я понимаю основы веб-разработки и HTTP-сообщения и GET.
Теперь, я проходил несколько учебных руководств MVC, и я, хотя я хорошо разбираюсь в том, как работает MVC, а также как работает "Маршрутный движок". Затем неожиданно я натолкнулся на код, который выглядит следующим образом:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyViewModel());
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return Content("Thanks", "text/html");
}
}
У меня есть несколько вопросов, на которые он смотрит:
- Мое понимание механизма маршрутизации состояло в том, что элемент управления передается конкретному ActionMethod на основе URL-адреса, и обычно URL-адрес - это в основном тип Controller/ActionMethod/Id, где параметр menthod - скорее примитивные типы. В этом примере выше, какой URL-адрес потребуется для вызова "
общедоступный индекс ActionResult (модель MyViewModel)? "
Так как NyViewModel является сложным типом, вы не можете передать его как часть URL-адреса. Как вы можете это назвать?
- Почему этот второй метод украшен [HttpPost], когда первый метод не требует каких-либо атрибутов? Существуют ли какие-либо рекомендации о том, когда использовать атрибуты [Http], а когда нет?
Я думаю, что в головоломке отсутствует большой кусочек, и оба вопроса взаимосвязаны. Тем не менее, нужна помощь в понимании отношений
Ответы
Ответ 1
Атрибут [HttpPost]
указывает механизму маршрутизации отправлять любые POST-запросы этому методу действий одному методу поверх другого. Это тип перегрузки.
Почему этот второй метод украшен [HttpPost]
, когда первый метод не требует каких-либо атрибутов?
Значение по умолчанию для метода [HttpGet]
. Из-за этого атрибут не требуется.
Существуют ли какие-либо рекомендации по использованию атрибутов [Http]
, а когда нет?
В идеале атрибуты должны быть для каждого метода, чтобы избежать путаницы. По мере того как вы узнаете, как все работает, вы часто будете использовать ярлыки (как и все остальное) и опускать их, когда знаете, что они не нужны.
Так как MyViewModel
является сложным типом, вы не можете передать его как часть URL-адреса. Как вы можете это назвать?
Данные будут преобразованы в модель из данных в теле запроса. Это может быть либо как объект JSON, либо как данные формы. (Есть трюки, чтобы получить объект, инициализированный из URL-адреса, но они могут быть немного сложными и передовыми.)
Ответ 2
Как правило, сложные объекты передаются в теле HTTP с помощью глаголов, которые поддерживают его, таких как POST и PUT. Содержимое тела должно пройти проверку привязки модели. Это в основном означает, что если это запрос POST с Content-Type: application/json, он должен десериализоваться из JSON в MyViewModel. Если содержимое является XML, оно должно десериализоваться как XML.
Общее соглашение состоит в том, чтобы иметь все примитивные типы, которые могут быть найдены в URL-адресе, запросе и заголовках, а затем один сложный тип из тела POST (или PUT) после этого. Я считаю, что можно поместить сложные типы в другое место, но тогда вы попадаете в преобразователи типов и пользовательские атрибуты, которые вы, вероятно, должны удержать, если вы новичок.
Почему этот второй метод украшен [HttpPost], когда первый метод не требует каких-либо атрибутов? Существуют ли какие-либо рекомендации по использованию атрибутов [Http], а когда нет?
"[HttpPost]" сообщает движку маршрутизации, что этот метод перегрузки доступен только через HTTP POST. Попытка PUT/home/index с телом не сработает с 404 Not Found, в этом случае. Беспараметрическая версия Index() не требует этого, поскольку она может работать с любым HTTP-глаголом, включая GET, POST и PUT.
Ответ 3
Лучшая практика - обработка запроса
Лучше всего использовать только общедоступные методы в контроллере, которые будут обслуживаться либо с представлением, либо с помощью json. Для всех общедоступных методов в вашем контроллере лучше всего либо отмечать их с помощью [HttpGet]
, либо [HttpPost]
, либо одного из других типов, которые я не буду использовать, поскольку они являются более сложными сценариями.
Эти атрибуты Http
ограничивают метод только обслуживанием тех конкретных запросов. Хотя по умолчанию это [HttpGet]
, я обнаружил, что не маркировка [HttpGet]
во всех сценариях иногда может привести к неожиданному поведению при конфликтах именования.
Лучшая практика - PRG
Post-Redirect-Get - это шаблон дизайна, который в основном предусматривает, что в любое время, когда вы собираетесь отправлять ответ, полученный из запроса POST, вы должны перенаправить на получение, чтобы отправить ответ. Это защищает от нескольких сценариев, в том числе не проводку снова, если используется кнопка "Назад".
Переадресация обычно происходит в форме [HttpPost]
ActionResult с помощью return RedirectToAction("MyHttpGetAction");
.
Проводка сложных моделей
Существует несколько способов, которыми вы можете отправить сложную модель. Основное различие заключается в том, что если вы используете запрос GET, он находится в URL-адресе, и если вы используете запрос POST, он находится в заголовках запроса. Если вы используете ajax, то разница становится размытой, поскольку вы почти всегда будете отправлять ее в тело.