How does the controller receive parameters on Http

2019-06-18 14:38发布

问题:

Take this snippet out of a controller, for example:

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) &&
                returnUrl.Length > 0 &&
                returnUrl.StartsWith("/") &&
                !returnUrl.StartsWith("//") &&
                !returnUrl.StartsWith("/\\"))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }
        }
        else
        {
            ModelState.AddModelError("", "Username and Password combination is incorrect");
        }
    }

    return View();
}

My question is, with the overloaded method of Login() (for the HTTP POST), what calls this method with the first parameter as a LoginModel class, and the second parameter as a string? My Login.cshtml view uses a submit button, so I am curious as to how these parameters get passed to the Login() method? What's to stop me from adding a third parameter? And how would that parameter get passed??

I know this is a basic question, I'm just trying to understanding the connecting piece between Views and Controllers.

回答1:

This process is called Model Binding, lots of resources on it...I would start with How to implement a custom one because from that you will then understand how and why the process works.

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

EDIT:

There is a default model binder which exists which takes items in the post collection like form data and url parameters and tries to match them up with items which you have told the controller to expect. It works something like this...

Request comes in, MVC decides which controller should get the request MVC then looks at the HTTP Method, was it a GET or POST? If it was a post then it looks for the controller action with the HttpPost attribute MVC then looks at the parameters you have defined...

In your case it says I have a LoginModel and a returnUrl; MVC now is happy - it knows where things are going so now it looks at what you sent... It looks at your post data (the form fields and query string parameters) One by one it looks at their names and then tries to find a match in your controller parameters.

It finds a Username field in the form data, it takes a look at your parameters and asks if there is a Username? No, well maybe Username is a property of LoginModel...it then looks through LoginModel. Aha it says, found one. MVC then creates an instance of LoginModel and sets the Username property to the value you posted.

This process continues for each of the things it finds in your form and query string. There are a bunch of rules it follows but you get the picture - this matching is part of the 'convention over configuration' beauty of MVC.

This whole process above it model binding and since MVC implements this default behavior you do not see it written out in the Global.asax or anything, it is just part of MVC.



回答2:

Take a look at your LogOn view, this is where the post method gets the returnUrl parameter

Html.BeginForm("LogOn", "Account", new { returnUrl = @Request.QueryString["ReturnUrl"] }