Понимание параметров [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, то разница становится размытой, поскольку вы почти всегда будете отправлять ее в тело.