Как контроллер получает параметры для методов HttpPost?

#asp.net-mvc #asp.net-mvc-3

#asp.net-mvc #asp.net-mvc-3

Вопрос:

Возьмите этот фрагмент из контроллера, например:

 public ActionResult Login()
{
    if (User.Identity.IsAuthenticated)
    {
        return RedirectToAction("Index", "Home");
    }
    else
    {
        return View();
    }
}

//
// POST: /User/Login

[HttpPost]
public ActionResult Login(LoginModel lm, string returnUrl)
{
    if (ModelState.IsValid)
    {
        if (Membership.ValidateUser(lm.UserName, lm.Password))
        {
            FormsAuthentication.SetAuthCookie(lm.UserName, lm.RememberMe);
            if (Url.IsLocalUrl(returnUrl) amp;amp;
                returnUrl.Length > 0 amp;amp;
                returnUrl.StartsWith("/") amp;amp;
                !returnUrl.StartsWith("//") amp;amp;
                !returnUrl.StartsWith("/\"))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }
        }
        else
        {
            ModelState.AddModelError("", "Username and Password combination is incorrect");
        }
    }

    return View();
}
 

Мой вопрос заключается в том, что с перегруженным методом Login() (для HTTP POST), что вызывает этот метод с первым параметром в качестве LoginModel класса, а вторым параметром в качестве string ? В моем представлении Login.cshtml используется кнопка отправки, поэтому мне любопытно, как эти параметры передаются Login() методу? Что помешает мне добавить третий параметр? И как будет передан этот параметр??

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

Ответ №1:

Этот процесс называется привязкой модели, в нем много ресурсов…Я бы начал с того, как реализовать пользовательский, потому что из этого вы поймете, как и почему работает процесс.

http://buildstarted.com/2010/09/12/custom-model-binders-in-mvc-3-with-imodelbinder/
http://bradwilson.typepad.com/blog/2010/10/service-location-pt9-model-binders.html

Редактировать:

Существует связующее устройство модели по умолчанию, которое принимает элементы из коллекции post, такие как данные формы и параметры url, и пытается сопоставить их с элементами, которые вы сказали контроллеру ожидать. Это работает примерно так…

Приходит запрос, MVC решает, какой контроллер должен получить запрос, затем MVC просматривает метод HTTP, был ли это GET или POST? Если это был post, то он ищет действие контроллера с атрибутом HttpPost, затем MVC просматривает параметры, которые вы определили…

В вашем случае он говорит, что у меня есть LoginModel и returnUrl; MVC теперь доволен — он знает, как обстоят дела, поэтому теперь он просматривает то, что вы отправили… Он просматривает ваши данные post (поля формы и параметры строки запроса) Один за другим он просматривает их имена, а затем пытается найти соответствие в параметрах вашего контроллера.

Он находит поле имени пользователя в данных формы, просматривает ваши параметры и спрашивает, есть ли имя пользователя? Нет, ну, может быть, имя пользователя — это свойство LoginModel…it затем просматривает LoginModel. Ага, там написано, нашел один. Затем MVC создает экземпляр LoginModel и присваивает свойству Username значение, которое вы опубликовали.

Этот процесс продолжается для каждой вещи, которую он находит в вашей форме и строке запроса. Существует множество правил, которым он следует, но вы понимаете картину — это соответствие является частью «соглашения о настройке» красоты MVC.

Весь этот процесс над ним моделирует привязку, и поскольку MVC реализует это поведение по умолчанию, вы не видите, что оно записано в Global.asax или что-то еще, это просто часть MVC.

Комментарии:

1. Я не уверен, что полностью понимаю это. Я прочитал обе статьи, и, глядя на мое приложение, у меня нет класса, который бы его реализовывал IModelBinder , и в моем методе нет кода Application_Start() , который вызывается ModelBinders.Binders.Add() . Я что-то упускаю из виду? Все еще не вижу этого и как представление сознательно передает два параметра.

2. 1 отличное объяснение, определенно понимаю, что вы говорите. Наверное, я больше привык к «конфигурации вместо соглашения», поэтому я пытаюсь доказать себе, почему все происходит. Ах, красота поведения по умолчанию! Теперь я знаю. Спасибо, @keithwarren7.

3. Еще один вопрос к тебе, Кит. В <input /> моей разметке есть элемент управления. При нажатии на это он публикует сообщения, но откуда returnUrl они берутся?? Это просто параметр, позволяющий захватывать данные на кнопке отправки?

4. returnUrl фактически добавляется фильтром безопасности. Вы запросили доступ к ресурсу, который текущий пользователь не имеет права запрашивать. Фильтр безопасности распознал это и предназначен для отправки вас на страницу входа, чтобы вы могли войти в систему. Он добавляет параметр returnUrl (который содержит URL-адрес страницы, которую вы изначально запрашивали), чтобы после входа в систему он мог отправить вас обратно в то место, которое вы сначала запросили.

Ответ №2:

Взгляните на ваше представление входа в систему, именно здесь метод post получает параметр returnUrl

Html.BeginForm(«LogOn», «Account», new { returnUrl = @Request.Строка запроса[«returnUrl»] }