Including the login form within the master layout

2019-07-10 15:54发布

问题:

I'm trying to include my log-in form in the _Layout.cshtml file, but I'm having a few problems with it.

First of all, when I provide an incorrect username and/or password, or the input fields don't pass validation, instead of displaying the error messages in the partial view, it makes the partial view take up the entire screen!

This is the partial view: http://i.imgur.com/oisCj85.png?1

This is the 'partial' view returned when something goes wrong with logging in: http://i.imgur.com/Uc5Sh2t.png?1

And secondly, when the log-in is successful, the user does get logged-in, the page 'reloads', but the Javascript in <body onload="loadPage();> in _Layout.cshtml does not execute (and as such I can't get the log-in bar to show up again because it's collapsed by default). EDIT: This problem is now solved, the JS didn't execute because there were errors in it. It referenced a button that only shows up when you are not logged in, obviously that broke the code when you are logged in :)

Here's my code:

_LogOn.cshtml:

@model project_blok_c_groep_13_webshop.Models.LogOnModel

@{
    if (Request.IsAuthenticated)
    {
    <div class="minicolumn">
        U bent ingelogd als: @User.Identity.Name
    </div>
    <div class="minicolumn miniborder">
        Click here to log out!
    </div>
    }
    else
    {
    <div class="minicolumn">
        @using (Html.BeginForm("_LogOn", "Account", new { ReturnUrl = Request.QueryString["ReturlUrl"] }))
        {
            <span style="color:red">@Html.ValidationSummary(true, "Incorrecte gebruikersnaam en/of wachtwoord.")</span>
            <fieldset>
                Gebruikersnaam:
                @Html.TextBoxFor(model => model.Username)
                @Html.ValidationMessageFor(model => model.Username)

                Wachtwoord:
                @Html.PasswordFor(model => model.Password)
                @Html.ValidationMessageFor(model => model.Password)

                <input type="submit" value="Log-in" />
            </fieldset>
        }
    </div>
    }
}

_Layout.cshtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
 <!-- saved from url=(0014)about:internet -->
 <head>
  <title>Webshop</title>
  <link href="@Url.Content("~/Content/Site.css")" type="text/css" rel="stylesheet" />
  <link href='http://fonts.googleapis.com/css?family=Merriweather+Sans' rel='stylesheet' type='text/css' />

  <script type="text/javascript">
      <!--lots of javascript omitted here-->
  </script>

 </head>

 <body onload="loadPage();">
  <div class="maindiv">
   <div class="topbar">
   </div>
   <div id="minibar">
    @Html.ActionLink("Log uit", "LogOff","Account")
    <a href="/">Home</a>
    <a href="#">Catalogus</a>
    <a href="#">Winkelwagen</a>
    <a href="#">Contact</a>
    <a onclick="displayBar();">Account</a>
    <div id="visbar">
        @Html.Action("_LogOn", "Account")
    </div>
   </div>
   <div class="content">
     <div class="sidebar">
        @Html.Action("_Menu", "Home")
     </div>


     <div class="center">
      <noscript>
       <p>
        For full functionality of this site it is necessary to enable JavaScript.
        Here are the <a href="http://www.enable-javascript.com/" target="_blank">
        instructions how to enable JavaScript in your web browser.</a>
       </p>
      </noscript>

      @RenderBody()

     </div>
    </div>
    <div class="footer">

    </div>
   </div>
 </body>
</html>

And lastly, AccountController:

    public class AccountController : Controller
    {
        private AuthDBController authDBController = new AuthDBController();

        public ActionResult LogOff()
        {
            FormsAuthentication.SignOut();

            return RedirectToAction("Index", "Home");
        }    

        /*
         * Voor de expandable bar.
         */
        public PartialViewResult _LogOn()
        {
            return PartialView();
        }

        [HttpPost]
        public ActionResult _LogOn(LogOnModel logOnModel, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                bool auth = authDBController.isAuthorized(logOnModel.Username, logOnModel.Password);

                if (auth)
                {
                    FormsAuthentication.SetAuthCookie(logOnModel.Username, false);
                    return Redirect(returnUrl ?? Url.Action("Index", "Home"));
                }
                else
                {
                    ModelState.AddModelError("loginfout", "Incorrecte gebruikersnaam en/of wachtwoord.");
                }
            }
            return PartialView(logOnModel);
        }

    }

These problems have me stumped, I've looked through a lot of other similar questions, but none had the answer. Any help would be greatly appreciated. I guess I'm not understanding how partial views, redirects and stuff works.

回答1:

I did similar functionality.

Controller action:

[AllowAnonymous]
    [HttpPost]
    public ActionResult LoginJs(LoginModel m, string returnUrl)
    {
        if(ModelState.IsValid)
        {
            if(ValidateUser(m))
            {
                FormsAuthentication.SetAuthCookie(m.Card, false);

                return Json(new { success = true, redirect = Url.IsLocalUrl(returnUrl) ? returnUrl : Url.Action("Summary") });
            }

            ModelState.AddModelError("", _invalidUser);
        }

        return Json(new { errors = GetErrorsFromModelState() });
    }

    private IEnumerable<string> GetErrorsFromModelState()
    {
        return ModelState.SelectMany(x => x.Value.Errors.Select(error => error.ErrorMessage));
    }

My _Layout.cshtml code:

@if (Request.IsAuthenticated)
{
   <div class="enter">
      U bent ingelogd als: @User.Identity.Name
      @Html.ActionLink("Log out", "Logoff", "Members", null, new { @class = "exit"     })
   </div>
}
else
{
    Html.RenderAction("LoginJsGet", "Members");
}

PartialView code:

@model LoginModel

@using(Html.BeginForm("Login", "Members", FormMethod.Post, new { id = "login", @class = "enter_form" }))
 {
     <span style="color:red">@Html.ValidationSummary(true, "Incorrecte gebruikersnaam en/of wachtwoord.")</span>
            <fieldset>
                Gebruikersnaam:
                @Html.TextBoxFor(model => model.Username)
                @Html.ValidationMessageFor(model => model.Username)

                Wachtwoord:
                @Html.PasswordFor(model => model.Password)
                @Html.ValidationMessageFor(model => model.Password)

                <input type="submit" value="Log-in" />
            </fieldset>
}

and JavaScript:

<script>
$(function () {
    $('#login').unbind('submit');

    $('#login')
        .attr('action', '/Members/LoginJs')
        .bind('submit', function () {
            var form = this;
            if ($("#login").valid()) {
                $.post($(form).attr('action'), $(form).serialize(), function (data) {
                    if (data.errors) {
                        makePopup(data.errors, 'error', 'Ошибка входа');
                    } else {
                        document.location = data.redirect;
                    }
                });
            }

            return false;
        });
});