2015-02-28 3 views
10

Я очень новичок в MVC-шаблоне проектирования, а также в Framework. Я также не очень хорошо разбираюсь в основах форм ASP.NET. Тем не менее, я понимаю основы веб-разработки и HTTP-сообщения и GET.Понимание [HttpPost], [HttpGet] и сложных параметров Actionmethod в MVC

Теперь я проходил несколько учебных руководств MVC, и я, хотя я хорошо разбирался в том, как работает MVC, а также о том, как работает «Маршрутизатор». И вдруг я наткнулся на код, который выглядит как folloing:

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 Index (MyViewModel модель)?"

Поскольку NyViewModel является сложным типом, вы не можете передать его как часть URL-адреса. Как вы можете это назвать?

  • Почему этот второй метод украшен [HttpPost], когда первый метод не требует каких-либо атрибутов? Существуют ли какие-либо рекомендации по использованию атрибутов [Http], а когда нет?

Я думаю, что в головоломке отсутствует большой кусочек, и оба вопроса взаимосвязаны. Тем не менее, нужна помощь в осмыслении с отношениями

ответ

12

Атрибут [HttpPost] указывает механизму маршрутизации отправлять любые POST-запросы этому методу действий одному методу над другим. Это тип перегрузки.

Почему этот второй метод украшен [HttpPost], когда первый метод не требует каких-либо атрибутов?

По умолчанию для метода является [HttpGet]. Из-за этого атрибут не требуется.

Есть ли какие-либо указания относительно того, когда следует использовать атрибуты [Http], а когда нет?

В идеале атрибуты должны быть на каждом методе, чтобы избежать путаницы. По мере того как вы узнаете, как все работает, вы часто будете использовать ярлыки (как и все остальное) и опускать их, когда знаете, что они не нужны.

С MyViewModel является сложным типом, вы не можете передать его как часть URL-адреса. Как вы можете это назвать?

Данные будут преобразованы в модель по данным в теле запроса. Это может быть либо как объект JSON, либо как данные формы. (Есть трюки, чтобы получить объект, инициализированный из URL-адреса, но они могут быть немного сложными и передовыми.)

+2

Мне нравится этот ответ, потому что он напрямую отвечает на вопросы, а также исправляет ошибочное представление о том, что сложные объекты не могут быть переданы через URL. Привязка модели .NET на самом деле довольно надежная! Вот хороший пример того, почему @krillgar говорит, что он может усложниться (I.E. weird!) Http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/ – Vassi

+0

Хорошее объяснение. Но, не имеет значения, не используем ли мы [HttpPost] код выше? –

+0

@ AntiMafia Я не уверен, что вы имеете в виду. '[HttpGet]' является единственным, который является необязательным, поскольку GET является стандартным методом HTTP. Каждый раз, когда вы хотите сделать POST, вам нужно украсить действие атрибутом. – krillgar

1

Best Practice - обработка запросов

Это лучшая практика, чтобы использовать только открытые методы в контроллере, которые собираются обслуживаться либо с целью или с JSON. Для всех общедоступных методов в вашем контроллере наилучшей практикой является либо отметить их [HttpGet], либо [HttpPost], либо один из других типов, которые я не буду накрывать, так как они являются более сложными сценариями на грани.

Эти атрибуты Http ограничивают метод только обслуживанием тех конкретных запросов. Хотя по умолчанию [HttpGet], я обнаружил, что не маркировка [HttpGet] во всех сценариях может иногда приводить к неожиданному поведению при конфликтах именования.

Best Practice - PRG

Post-Redirect-Get является шаблоном, который по существу предусматривает, что в любое время вы собираетесь посылать ответ, который пришел из запроса POST, вы должны перенаправить на ГЭТ чтобы отправить ответ. Это защищает от нескольких сценариев, в том числе не публикуется снова, если используется кнопка «Назад».

Перенаправление обычно происходит в виде [HttpPost] ActionResult с использованием return RedirectToAction("MyHttpGetAction");.

проводки сложные модели

Есть несколько способов, которые вы можете отправить сложную модель. Основное различие заключается в том, что если вы используете запрос GET, он находится в URL-адресе, и если вы используете запрос POST, он находится в заголовках запроса. Если вы используете ajax, то разница становится размытой, поскольку вы почти всегда будете отправлять ее в тело.

3

Как правило, сложные объекты передаются в теле 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.

Смежные вопросы