Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC - How to maintain ModelState from a different controller?

I have a HomeController with an Index action that shows the Index.aspx view. It has a username/password login section. When the user clicks the submit button, it POSTs to a Login action in the AccountController.

        <% Html.BeginForm("Login", "Account", FormMethod.Post); %>

In that action, it tests for Username/Password validity and if invalid, sends the user back to the Login page with a message that the credentials were bad.

    [HttpPost]
    public ActionResult Login(LoginViewModel Model, string ReturnUrl)
    {
        User user = MembershipService.ValidateUser(Model.UserName, Model.Password);
        if (user != null)
        {
            //Detail removed here
            FormsService.SignIn(user.ToString(), Model.RememberMe);
            return Redirect(ReturnUrl);
        }
        else
        {
            ModelState.AddModelError("", "The user name or password provided is incorrect.");
        }
        // If we got this far, something failed, redisplay form
        return RedirectToAction("Index", "Home");  // <-- Here is the problem.  ModelState is lost.
    }

But here's the problem: the ValidationSummary is always blank because we're losing the Model when we RedirectToAction.

So the question is: How do I send the user to the action on a different controller without a Redirect?

like image 404
Rap Avatar asked Dec 23 '10 20:12

Rap


People also ask

Why ModelState IsValid is false in MVC?

That's because an error exists; ModelState. IsValid is false if any of the properties submitted have any error messages attached to them. What all of this means is that by setting up the validation in this manner, we allow MVC to just work the way it was designed.

How does ModelState work in MVC?

In short, the ModelState is a collection of name and value pairs that are submitted to the server during a POST. It also contains error messages about each name-value pair, if any are found. ModelState is a property of a Controller instance, and can be accessed from any class that inherits from Microsoft. AspNetCore.

How do you pass data from Controller model?

In Solution Explorer, right-click the Controllers folder and then click Add, then Controller. In the Add Scaffold dialog box, click MVC 5 Controller with views, using Entity Framework, and then click Add. Select Movie (MvcMovie. Models) for the Model class.


2 Answers

As others have said it's common to return the view if validation fails but as you are calling from your account controller you will want to specify the full path of your view

return View("~/Views/Home/Index.aspx", model);

Or

It is also common to have a seperate login page and redirect to that page if the login fails. Both pages will submit to the same login action. Facebook does this for example.

Or

As you only want to display an error message

return RedirectToAction("Index", "Home", new { LoginAttempts = 1 });

then in your Index action read the LoginAttempts parameter and choose to display the error message accordingly.

like image 139
David Glenn Avatar answered Oct 03 '22 17:10

David Glenn


Use TempData to save state between requests. Use special attributes for convenience as shown here.

Few moments to mention:

  • Don't return View directly from your POST-action, respect Post-Redirect-Get pattern.
  • Don't overuse TempData. It's only supposed to save model state right before redirect and to retrieve it right after being redirected.
like image 21
Vasiliy R Avatar answered Oct 03 '22 16:10

Vasiliy R