Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

User login in partial view with error display

I want to build a login form that displays in a sidebar across every page in my site. If the user enters an incorrect user/pass, I want the errors to be displayed above this form (with the rest of the page remaining as it was before), and if he logs in successfully, I want the form to change to a list of information about the user (again, with the rest of the page the same as before the login). I am using an MVC 3 web application project with the default Internet Application template. I have this:

_Layout.cshtml

@{ 
    if (User.Identity.IsAuthenticated)
    {
        Html.RenderAction("ShowUserInfo", "User");
    }
    else
    {
        Html.RenderAction("LogIn", "User");   
    }        
}

UserController

    [ChildActionOnly]
    public PartialViewResult ShowUserInfo()
    {
        // populate loggedInInfo from database based on
        // User.Identity.Name
        return PartialView("_LoggedInInfo", loggedInInfo);
    }

    private ActionResult RedirectToPrevious(string returnUrl)
    {
        if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
            && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
        {
            return Redirect(returnUrl);
        }
        else
        {
            return RedirectToAction("index", "");
        }
    }

    [ChildActionOnly]
    public PartialViewResult LogIn()
    {
        return PartialView("_LogInForm");
    }

    //
    // POST: /User/LogIn

    [HttpPost]
    public ActionResult LogIn(LogInModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            if (Membership.ValidateUser(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);

                return RedirectToPrevious(returnUrl);
            }
            else
            {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
        }

        return RedirectToPrevious(returnUrl);
    }

_LogInForm

@model MyProject.Models.LogInModel

<h2>Login</h2>
<p>
    Please enter your username and password. @Html.ActionLink("Register", "register", "user") if you don't have an account.<br />
    @Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.")
</p>

@using (Html.BeginForm("LogIn", "user")) {
   html stuff
}

This works almost as intended, except that when I enter a wrong username/password, the page just reloads with an empty form and no error is displayed. I have tried some other things too, but I either get errors about how I cannot issue a redirect from a partial view or I get the partial view (with the errors showing up) displayed as a whole view, so it shows up as a single page, separate from the rest of the site. If I log in correctly, everything works fine.

How can I get the errors to be correctly displayed above the form? I would rather not use any Ajax or JQuery to do this.

like image 432
IVlad Avatar asked Nov 04 '11 21:11

IVlad


1 Answers

The problem seem to be that you are doing a redirect rather than just returning the appropriet view.

After you've added a model error, you need to return the view instead of performing a redirect :

return View("LoginViewNameGoesHere")

So you do not want to return the partial view here, but the entire view.

like image 135
Filip Ekberg Avatar answered Nov 02 '22 12:11

Filip Ekberg