Coesy
Coesy

Reputation: 936

Passing an object to controller in mvc

I am in the middle of learning MVC and it's such a different way of thinking, I have taken a simple login form as an example but the one thing that confuses me is how I tie up the submit button to the Action and pass the object. Let me give you the example.

Here is the Model

public class ExternalUser
    {

        [Display(Name = "User Name")]
        [MaxLength(50)]
        public string UserName { get; set; }
        [Display(Name = "Password")]

        public string Password { get; set; }
        [Display(Name = "Remember Me")]

        public bool RememberMe { get; set; }
        public bool IsValid()
        {
            return true;
        }
    }

Here is the View

@model ExternalUser
@{
    ViewBag.Title = "Login";    
}
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true, "Login failed. Check your login details.");
    <div>
        <fieldset>
            <legend>Login</legend>
            <div class="editor-label">
                @Html.LabelFor(u => u.UserName)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(u => u.UserName)
                @Html.ValidationMessageFor(u => u.UserName)
            </div>
            <div class="editor-label">
                @Html.LabelFor(u => u.Password)
            </div>
            <div class="editor-field">
                @Html.PasswordFor(u => u.Password)
                @Html.ValidationMessageFor(u => u.Password)
            </div>
            <div class="editor-label">
                @Html.CheckBoxFor(u => u.RememberMe)
                @Html.LabelFor(u => u.RememberMe)
            </div>
            <input type="submit" value="Log In" />
        </fieldset>
    </div>
}

Here is the Controller

 public class UserController : Controller
    {
        // GET: /User/
        public ActionResult Index()
        {
            return View();
        }

        [HttpGet]
        public ActionResult Login()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Login(ExternalUser user)
        {
            if (ModelState.IsValid)
            {
                if (user.IsValid())
                {
                    FormsAuthentication.SetAuthCookie(user.UserName, user.RememberMe);
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    ModelState.AddModelError("", "Login data is incorrect!");
                }
            }
            return View(user);
        }
        public ActionResult Logout()
        {
            FormsAuthentication.SignOut();
            return RedirectToAction("Index", "Home");
        }
    }

When I click the Login button, it's going to the first overload of public ActionResult Login() and not the Second overload of public ActionResult Login(ExternalUser user) which is what I would expect, can you tell me what I'm missing as to why it's not hitting the correct method?

Thanks

Upvotes: 0

Views: 90

Answers (2)

Coesy
Coesy

Reputation: 936

I realised that I had put in an extra <form> tag in the /Shared/SiteLayout.cshtml, therefore causing two <forms> to placed on the page, after removing the one in the shared folder it now fires the right method! I hope this helps someone in the future.

Upvotes: 0

Sai Puli
Sai Puli

Reputation: 971

Can't think of a reason why it would not work. But, none the less check the HTML generated in the browser using inspect element option. If the <form> tag has action attribute value set to 'GET' or if the action attribute is missing altogether, try explicitly specifying it as post.

Html.BeginForm("Login", "User", FormMethod.Post)

Upvotes: 4

Related Questions