无法读取未定义的属性 [英] Cannot Read Property Undefined

查看:64
本文介绍了无法读取未定义的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的 .NET Core MVC 项目中创建了一个端点.

我的 API 是:

[HttpGet("/api/notifications")]公共异步任务通知(){var user = await GetCurrentUserAsync();//获取当前登录的用户.如果(用户==空)返回状态代码(401);var 通知 = _notificationService.GetUserNotifications(user.Id);var serialized = JsonConvert.SerializeObject(notifications);返回确定(序列化);}

我正在使用 SignalR 来发送数据库更改通知

[HttpPost]公共异步任务CreateNotification(NotificationModel 模型){var 通知 = 新通知(){NotificationTitle = model.NotificationTitle,NotificationBody = model.NotificationBody,日期时间 = 日期时间.UtcNow};_notificationService.Create(notification);//通知和用户之间的多对多关系//多对多表看起来像 =>通知 ID |用户 ID |是读//所以在这个动作中,因为通知是第一次创建的,//NotifyUsers 方法将'isRead' 属性设置为false._notificationService.NotifyUsers(notification, model.userIds);//这里用SignalR通知客户端!等待 _notificationHubContext.Clients.All.SendAsync("initSignal", "message");return RedirectToAction("PublishedNotification", "Portal");}

最后,我有一个 Javascript 文件,我在其中使用 SignalR 控制来自 api 的数据.

notification.js

window.onload = () =>通知用户();var connection = new signalR.HubConnectionBuilder().withUrl("/NotificationHub").build();connection.on("initSignal", () => notifyUser());connection.start().catch(function (err) {返回 console.error(err.toString());});const endPoint = "http://{my-site}.com/api/notifications";异步函数 getNotifications() {尝试 {var response = await fetch(endPoint);var 通知 = 等待 response.json();//过滤 isRead 属性为false"的通知var unreadNotifications = notification.filter(notification => !notification.isRead);返回{通知,未读通知};}赶上(e){控制台错误(e);}}函数通知用户(){var ul = document.getElementById("通知列表");ul.innerHTML = "";var notificationDropdownBtn = document.getElementById("notification-dropdown");var initialNotificationLimit = 2;notificationDropdownBtn.onclick = () =>{通知用户();}getNotifications().then(notifications => {让 { unreadNotifications = [] } = 通知;如果 (unreadNotifications.length > 0) {var notificationControl = document.getElementById("notification-control");notificationControl.textContent = unreadNotifications.length;unreadNotifications.forEach((notification, index) => {如果(索引>initialNotificationLimit){返回;}ul.insertAdjacentHTML("beforeend", (createNotificationListItem(notification)));});var loadBtn = document.getElementById("load-more");loadBtn.onclick = () =>{ul.innerHTML = "";初始通知限制 += 3;unreadNotifications.slice(0, initialNotificationLimit).forEach(notification =>ul.insertAdjacentHTML("beforeend", (createNotificationListItem(notification))));}} 别的 {ul.insertAdjacentHTML("beforeend", "<span class='text-muted'>您没有任何未读通知!</span>");}});}函数 createNotificationListItem(notification) {var { NotificationId, NotificationBody, NotificationTitle, DateTime } = notification.Notification;return `<li class="media"><div class="mr-3 position-relative"><img src="" width="36" height="36" class="rounded-circle" alt="">

<div class="media-body"><div class="media-title">//在这条路线中,它转到我的 .NET Core 中的公告操作,//这会将 isRead 属性设置为True"<a href="/announcement/${NotificationId}"><span class="font-weight-semibold">${NotificationTitle}</span><span class="text-muted float-right font-size-sm">${DateTime}</span></a>

<span class="text-muted">${NotificationBody.substring(0, 25)}...</span>

`}

好的,这是我的项目通知部分.

**错误/问题**

当我使用 FTP 发布我的网站时,出现控制台错误.

但主要的问题是,直到我的朋友告诉我通知有错误和控制台错误,我才真正知道有错误.因为在我的电脑上一切正常,我在另一台朋友的电脑上试过,也能工作,但其他人告诉我,在他们的电脑上,他们遇到了这个错误.

错误是,

无法读取未定义的属性 'unreadNotifications' =>通知.js

我试图告诉他们删除浏览器缓存历史记录,对他们中的一些人来说它有效,而对他们中的一些人来说却没有..

我真的被困在这里,我不知道如何谷歌......

注意:供您参考,我的端点有数据,我的操作或我的 ef 方法都可以正常工作...

代码在其他计算机上的工作方式如何不同,而且我不知道如何Google这个问题,正如你所理解的,我不是专家......

注意:我的 Cors 设置的最后一件事是:

services.AddCors(o => o.AddPolicy("MyPolicy", builder =>{builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();}));

EDIT :正如我上面提到的,我尝试在不同的计算机上以同一用户身份登录,当我在我的电脑和其他一些电脑上输入http://{my-site}/api/notifications"时,我得到了 JSON 对象(到目前为止有 3 个通知.),但在其他电脑上这个端点 返回一个空数组 => []

第二次当我在浏览器上调试我的 js 文件时,这是我的响应,它无法访问设置为 HttpOnlycookies>,我尝试使用 credentials:same-origin 获取,但实际上没有用.

response = Response {type: "cors", url: "{mysite}.com/account/login?ReturnUrl=%2Fapi%2Fnotifications", 重定向: true, status: 200, ok: true, ...}

解决方案

用AJAX解决,

错误是我从 js 文件中获取 API,无法访问我的Cookies"并返回

options.AccessDeniedPath = "/account/accessdenied";

services.ConfigureApplicationCookie.

当我调试我的 notification.js response 对象是

response = Response {type: "cors", url: "{mysite}.com/account/login?ReturnUrl=%2Fapi%2Fnotifications", 重定向: true, status: 200, ok: true, ...}

如果您将 Cookies 设置为 HttpOnly=true,那么您将无法从 客户端 端脚本访问它们.

因此,我在 script 标记中的 .cshtml 下直接进行了 Ajax 调用,我的 Ajax 调用是:

function notifyUser() {var ul = document.getElementById("通知列表");ul.innerHTML = "";var notificationDropdownBtn = document.getElementById("notification-dropdown");var initialNotificationLimit = 2;notificationDropdownBtn.onclick = () =>{通知用户();}$.ajax({类型:获取",//在这里我直接使用我的控制器和动作.url: "@Url.Action("通知", "门户")",内容类型:应用程序/json",数据类型:json",成功:功能(通知){var unreadNotifications = notification.filter(notification => !notification.isRead);如果 (unreadNotifications.length > 0) {...} 别的 {...},错误:函数(请求,状态,错误){控制台错误(错误);}});}

I have created an endpoint in my .NET Core MVC project.

My Api is:

[HttpGet("/api/notifications")]
public async Task<IActionResult> Notifications()
{
      var user = await GetCurrentUserAsync(); // Gets the current logged user.

      if (user == null)
            return StatusCode(401);

      var notifications = _notificationService.GetUserNotifications(user.Id);

      var serialized = JsonConvert.SerializeObject(notifications);

      return Ok(serialized);
}

And I'm using SignalR for Database Change Notifications

[HttpPost]
public async Task<IActionResult> CreateNotification(NotificationModel model)
{
    var notification = new Notification()
    {
          NotificationTitle = model.NotificationTitle,
          NotificationBody = model.NotificationBody,
          DateTime = DateTime.UtcNow
    };

    _notificationService.Create(notification);

    // Many to many relationship between Notifications and Users
    // Many to Many table looks like => NotificationId | UserId | isRead
    // So in this action, because of the notification is created for the first time, 
    // NotifyUsers method will set 'isRead' property to false.
    _notificationService.NotifyUsers(notification, model.userIds);

    //Here Notify the Clients with SignalR!
    await _notificationHubContext.Clients.All.SendAsync("initSignal", "message");

    return RedirectToAction("PublishedNotification", "Portal");

 }

and at last, I have a Javascript file where I'm controlling the data comes from api with SignalR.

notification.js

window.onload = () => notifyUser();

var connection = new signalR.HubConnectionBuilder().withUrl("/NotificationHub").build();

connection.on("initSignal", () => notifyUser());

connection.start().catch(function (err) {
    return console.error(err.toString());
});

const endPoint = "http://{my-site}.com/api/notifications";

async function getNotifications() {
    try {
        var response = await fetch(endPoint);

        var notifications = await response.json();

        // Filters notifications where isRead properties are "false"
        var unreadNotifications = notifications.filter(notification => !notification.isRead);

        return { notifications, unreadNotifications };
    } catch (e) {
        console.error(e);
    }
}

function notifyUser() {
    var ul = document.getElementById("notification-list");
    ul.innerHTML = "";
    var notificationDropdownBtn = document.getElementById("notification-dropdown");    
    var initialNotificationLimit = 2;

    notificationDropdownBtn.onclick = () => {
        notifyUser();
    }

    getNotifications().then(notifications => {
        let { unreadNotifications = [] } = notifications;

        if (unreadNotifications.length > 0) {

            var notificationControl = document.getElementById("notification-control");

            notificationControl.textContent = unreadNotifications.length;

            unreadNotifications.forEach((notification, index) => {
                if (index > initialNotificationLimit) {
                    return;
                }
                ul.insertAdjacentHTML("beforeend", (createNotificationListItem(notification)));                
            });

            var loadBtn = document.getElementById("load-more");
            loadBtn.onclick = () => {
                ul.innerHTML = "";
                initialNotificationLimit += 3;
                unreadNotifications.slice(0, initialNotificationLimit).forEach(notification =>
                    ul.insertAdjacentHTML("beforeend", (createNotificationListItem(notification))));
            }

        } else {
            ul.insertAdjacentHTML("beforeend", "<span class='text-muted'>You don't have any unread notifications!</span>");
        }
    });
}

function createNotificationListItem(notification) {
    var { NotificationId, NotificationBody, NotificationTitle, DateTime } = notification.Notification;

    return `<li class="media">
                <div class="mr-3 position-relative">
                    <img src="" width="36" height="36" class="rounded-circle" alt="">
                </div>
                <div class="media-body">
                    <div class="media-title">

                       //In this route, which goes to my Announcement Action in my .NET Core,
                       // which will set isRead property to "True"
                        <a href="/announcement/${NotificationId}">
                            <span class="font-weight-semibold">${NotificationTitle}</span>
                            <span class="text-muted float-right font-size-sm">${DateTime}</span>
                        </a>
                    </div>
                    <span class="text-muted">${NotificationBody.substring(0, 25)}...</span>
                </div>
            </li>`
}

Ok, so this is my projects notifications part.

**ERROR / PROBLEMS **

When I published my site with FTP, a Console error appeared.

But the main problem is, till my friend told me that there is an error with notifications, and a console error, I didnt actually know that there was an error. Because on my computer everything was working, and I tried on another friends computer, and also working, but the others told me that on their computer, they got this error.

Error was,

Cannot read property undefined  'unreadNotifications'  => notification.js

I tried to told them to remove browser cache history, for some of them it worked, and for some of them it didn't..

I really got stuck in here, I don't know how to google it...

NOTE: For your information, my endpoint has the data, and my actions or my ef methods are all working fine...

How can a code works differently in other computers, and also I didn't know how to Google this problem, and as you can understand I'm not an expert...

NOTE: Last thing my Cors setup is:

services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
{
       builder.AllowAnyOrigin()
              .AllowAnyMethod()
              .AllowAnyHeader();
}));

EDIT : I've tried to log in as the same user on different computers, as I've mentioned above, when I type "http://{my-site}/api/notifications", on my computer and some others , I got the JSON object (3 notifications so far.), but on the other computers this endpoint return an empty array => []

Second EDIT : When I debugged my js file on browser, this is my response, it cant access the cookies which are set to HttpOnly, I tried to fetch with credentials:same-origin, didn't actually worked.

response = Response {type: "cors", url: "{mysite}.com/account/login?ReturnUrl=%2Fapi%2Fnotifications", redirected: true, status: 200, ok: true, …}

解决方案

It is solved with AJAX,

The Error was my fetch API from js file, couldn't reach my "Cookies" and return

options.AccessDeniedPath = "/account/accessdenied"; under

services.ConfigureApplicationCookie.

When I debugged my notification.js response object was

response = Response {type: "cors", url: "{mysite}.com/account/login?ReturnUrl=%2Fapi%2Fnotifications", redirected: true, status: 200, ok: true, …}

If you set your Cookies to HttpOnly=true then you are making them unreachable from client side scripts.

So, I've made an Ajax call directly under my .cshtml in a script tag and my Ajax call was:

function notifyUser() {
        var ul = document.getElementById("notification-list");
        ul.innerHTML = "";
        var notificationDropdownBtn = document.getElementById("notification-dropdown");
        var initialNotificationLimit = 2;

        notificationDropdownBtn.onclick = () => {
            notifyUser();
        }

        $.ajax({
            type: "GET",    

            //In here I directly use my controller and action.        
            url: "@Url.Action("Notifications", "Portal")",
            contentType: "application/json",
            dataType: "json",
            success: function (notifications) {

            var unreadNotifications = notifications.filter(notification => !notification.isRead);

            if (unreadNotifications.length > 0) {
                ...
            } else {
                ...
            },
            error: function (req, status, error) {
                console.error(error);
            }
        });
    }

这篇关于无法读取未定义的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆