【问题标题】:Trouble with MVC Navbar Home button Get RequestMVC 导航栏主页按钮获取请求的问题
【发布时间】:2018-10-04 22:17:10
【问题描述】:

我的主页按钮没有在获取请求中添加标题时遇到此问题。我在 localStorage 中存储了一个令牌,并在我向 Controller 发出 get 请求时将其发送到标头中:Home Action: Index.据我所知,它不使用我的 jquery 并直接进入帐户/索引。

下面是“Views/Shared/_Layout.cshtml”文件的代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>@ViewData["Title"] - Chat</title>

        <environment include="Development">
            <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
            <link rel="stylesheet" href="~/css/site.css" />
        </environment>
        <environment exclude="Development">
            <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
                  asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
                  asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
            <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
        </environment>
        <script src="~/js/NavBarFunctions.js"></script>
    </head>
    <body>
        <nav class="navbar navbar-inverse navbar-fixed-top">
            <div class="container">
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                </div>
                <div class="navbar-collapse collapse">
                    <ul class="nav navbar-nav">
                        <li id="li_btnHome"><a asp-area="" asp-controller="Home" asp-action="Index">A Different Page</a></li>
                    </ul>
                </div>
            </div>
        </nav>

        <div class="container body-content">
            @RenderBody()
            <hr />
            <footer>
                <p>&copy; 2018 - Chat</p>
            </footer>
        </div>

        <environment include="Development">
            <script src="~/lib/jquery/dist/jquery.js"></script>
            <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
            <script src="~/js/site.js" asp-append-version="true"></script>
        </environment>
        <environment exclude="Development">
            <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"
                    asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
                    asp-fallback-test="window.jQuery"
                    crossorigin="anonymous"
                    integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT">
            </script>
            <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
                    asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
                    asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
                    crossorigin="anonymous"
                    integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
            </script>
            <script src="~/js/site.min.js" asp-append-version="true"></script>
        </environment>

        @RenderSection("Scripts", required: false)
    </body>
</html>

这是 javascript 文件“wwwroot/js/NavBarFunctions.js”:

    $("#li_btnHome a")[0].click(function (event) {
        alert("Called click")
        event.preventDefault();
        $.ajax({
            type: 'GET',
            contentType: 'application/json; charset=utf-8;',
            url: '@Url.Action("Index", "Home")',
            beforeSend: function (xhr) {
                xhr.setRequestHeader("Authorization", localStorage.getItem("token"));
            },
            success: function (response) {
                $("html").html(response);
            }
        });
    });
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Chat.Enums;
using Chat.Identity;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;

namespace _Chat.Controllers
{
    public class HomeController : Controller
    {
        private AuthenticateUser authenticateUser = new AuthenticateUser();

        public async Task<IActionResult> Index()
        {
            var request = Request;
            var headers = request.Headers;

            StringValues token;
            if (headers.TryGetValue("Authorization", out token))
            {
                var result = await this.authenticateUser.ValidateToken(token);
                if (result.Result == AuthenticateResult.Success)
                {
                    return View();
                }
                else
                {
                    return RedirectToAction("Index", "Account");
                }
            }

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

编辑:出于某种奇怪的原因,看起来在我的页面从登录重定向到主页后,所有脚本/javascript 都停止工作了。

这是验证登录的代码。位于“Controllers/AccountController”:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Chat.Models;
using Chat.DatabaseAccessObject;
using Chat.Identity;
using Chat.DatabaseAccessObject.CommandObjects;
using System.Linq.Expressions;
using System.Net.Mime;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Authentication;
using Microsoft.IdentityModel.Tokens;

namespace Chat.Controllers
{
    public class AccountController : Controller
    {
        private const string SECRET_KEY = "CHATSECRETKEY";
        public static SymmetricSecurityKey SIGNING_KEY = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SECRET_KEY));
        private ServerToStorageFacade serverToStorageFacade = new ServerToStorageFacade();
        private AuthenticateUser authenticateUser = new AuthenticateUser();

        public IActionResult Index()
        {
            return View();
        }

        // Post: /login/
        [HttpPost]
        public async Task<IActionResult> Login([FromBody]LoginModel loginModel)
        {
            if (ModelState.IsValid)
            {
                var mapLoginModelToUser = new MapLoginModelToUser();
                var user = await mapLoginModelToUser.MapObject(loginModel);

                // If login user with those credentials does not exist
                if(user == null)
                {
                    return BadRequest();
                }

                else
                {
                    var result = await this.authenticateUser.Authenticate(user);

                    if(result.Result == Chat.Enums.AuthenticateResult.Success)
                    {
                        // SUCCESSFUL LOGIN
                        // Creating and storing cookies

                        var token = Json(new
                        {
                            data = this.GenerateToken(user.Email, user.PantherID),
                            redirectUrl = Url.Action("Index","Home"),
                            success = true
                        });
                        return Ok(token);
                    }
                    else
                    {
                        // Unsuccessful login
                        return Unauthorized();
                    }
                }
            }

            return BadRequest();
        }

        private string GenerateToken(string email, string pantherId)
        {
            var claimsData = new[] { new Claim(ClaimTypes.Email, email), new Claim(ClaimTypes.Actor, pantherId) };

            var signInCredentials = new SigningCredentials(SIGNING_KEY, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(
                issuer: "localhost",
                audience: "localhost",
                expires: DateTime.Now.AddDays(7),
                claims: claimsData,
                signingCredentials: signInCredentials
            );

            return new JwtSecurityTokenHandler().WriteToken(token);
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public async Task<IActionResult> Error() => View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
    }

    public class MapLoginModelToUser
    {
        private ServerToStorageFacade serverToStorageFacade;

        public MapLoginModelToUser()
        {
            serverToStorageFacade = new ServerToStorageFacade();
        }


        public async Task<User> MapObject(LoginModel loginModel)
        {
            Expression<Func<User, bool>> expression = x => x.Email == loginModel.inputEmail;

            var user = await this.serverToStorageFacade.ReadObjectByExpression(new User(Guid.NewGuid()), expression);

            if(user == default(Command))
            {
                return null;
            }

            return new User(user.ID)
            {
                Email = loginModel.inputEmail,
                Password = loginModel.inputPassword,
                FirstName = user.FirstName,
                LastName = user.LastName,
                PantherID = user.PantherID,
                ClassDictionary = user.ClassDictionary,
                UserEntitlement = user.UserEntitlement
            };
        }
    }
}

还有呈现页面的代码。位于“wwwroot/js/Login.js”:

$(document).ready(function () {
    $("#formSubmit").submit(function (event) {
        event.preventDefault();
        var email = $("#inputEmail").val();
        var password = $("#inputPassword").val();
        var remember = $("#rememberMe").val();
        var loginModel = {
            inputEmail: email,
            inputPassword: password,
            rememberMe: remember
        };

        $.ajax({
            type: 'POST',
            url: 'Account/Login',
            data: JSON.stringify(loginModel),
            contentType: 'application/json; charset=utf-8;',
            success: function (response) {
                var token = response.value.data;
                localStorage.setItem("token", token);
                alert("You have successfully logged in.");
                setHeader();
                redirect(response.value.redirectUrl);
            }
        });
    });

    function setHeader() {
        $.ajaxSetup({
            beforeSend: function (xhr) {
                xhr.setRequestHeader('Authorization', localStorage.getItem("token"));
            }
        });
    }

    function redirect(redirectUrl) {
        $.ajax({
            type: 'GET',
            contentType: 'application/json; charset=utf-8;',
            url: redirectUrl,
            success: function (response) {
                $("html").html(response);
            }
        });    
    }
});

我刚刚注意到,当没有任何脚本(或任何 javascript)工作时,会出现问题。我相信它可能会被$("html").html(response); 触发。 AccountController/Login 返回一个视图,这是我知道的唯一显示视图的方法。

这是加载新的 html 页面后收到的错误:

【问题讨论】:

  • 如果您将以下属性添加到您的 ajax 请求中,它会起作用吗? headers: { "Authorization": localStorage.getItem("token").toString(); }。这就是我通常添加/修改请求标头的方式。
  • 是的,这行得通,当我点击 &lt;li id="li_btnHome"&gt;&lt;a asp-area="" asp-controller="Home" asp-action="Index"&gt;A Different Page&lt;/a&gt;&lt;/li&gt; 时,NavBarFunctions.js 中指定的点击函数不起作用

标签: javascript c# jquery html asp.net-core-mvc


【解决方案1】:

NavBarFunctions.js 在您的布局中的位置存在问题。您正在加载 JS 并尝试在创建 li_btnHome 元素之前绑定 click 事件。您还尝试在页面上加载 JQuery 之前执行此操作。

从页眉中取出脚本并将其移到底部,靠近脚本的 RenderSection。

【讨论】:

  • 我将 NavBarFunction 脚本直接移到了 RenderSection 上方,但它不起作用。单击它时我没有收到警报。
【解决方案2】:

您将click 处理程序与jQuery 绑定的方式不正确:

$("#li_btnHome a")[0].click(function(event){
    // ...
})

$(selector) 将返回匹配元素的集合。 但是,$(selector)[0] 不是一个 jQuery 对象,而是一个普通的 DOM 元素因此您不能使用 .click(function(event){/* ... */}) 绑定 onclick 事件处理程序

还有,

  1. 可以return false;
  2. 正如@I. R. R 所说,您应该将令牌转换为字符串。
  3. 正如@Lyons所说,你应该在jQuery加载后执行代码

要正确绑定 onclick 处理程序,请将您的代码更改如下:

$("#li_btnHome a")[0].onclick=function(event){
    event.preventDefault();
    alert("called click");
    var tokenObj = localStorage.getItem("token");
    var tokenStr = tokenObj==null ? "what_about_tokenObj_is_null?": tokenObj.toString();
    $.ajax({
        type: 'GET',
        contentType: 'application/json; charset=utf-8;',
        url: '@Url.Action("Index", "Home")',
        beforeSend: function (xhr) {
            xhr.setRequestHeader("Authorization",tokenStr);
        },
        success: function (response) {
            alert(1);
            $("html").html(response);
        }
    });
    return false;
};

【讨论】:

  • 我这样做了,它仍然没有使用点击事件。我没有收到任何警报。它使用属于锚标记的 asp-controller 和 asp-action 将我重定向到 Home/Index。我将您的代码直接复制到了渲染脚本部分上方的脚本中。
  • @OneEyedTurkey 它在我的电脑上完美运行。奇怪的是它不适合你。我想知道您在此处未提及的那些代码中是否还有其他错误。能否请您按F12 看看是否有什么奇怪的地方,比如脚本没有加载,或者在这个脚本执行之前还有其他错误?或者如果可能的话,你能把完整的项目上传到 GitHub 吗?
  • 当我从 Chrome 检查控制台时,它并不表示有任何错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多