无法读取属性未定义

时间:2019-12-12 19:01:52

标签: javascript asp.net-mvc api asp.net-core asp.net-web-api

我已经在.NET Core MVC项目中创建了一个终结点。

我的Api是:

[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);
}

我将SignalR用于数据库更改通知

[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");

 }

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

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>`
}

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

**错误/问题**

当我发布带有FTP的站点时,出现控制台错误。

但是主要的问题是,直到我的朋友告诉我通知存在错误和控制台错误,我才真正知道这是错误。因为在我的计算机上一切正常, 我尝试在另一台朋友计算机上也可以正常工作,但是其他人告诉我,在他们的计算机上,他们遇到了此错误。

错误是

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

我试图告诉他们删除浏览器的缓存历史记录,对于某些浏览器来说,它起作用了,而对于某些浏览器来说,则没有。.

我真的被困在这里,我不知道怎么用谷歌搜索...

注意:为您提供信息,我的端点具有数据,并且我的操作或ef方法都可以正常工作...

代码如何在其他计算机上以不同的方式工作,并且我也不知道如何 Google 这个问题,并且您可以理解我不是专家...

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

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

编辑:如上所述,我尝试以同一用户身份在不同计算机上登录, 当我在计算机和其他计算机上键入“ http:// {my-site} / api / notifications”时,我得到了JSON对象(到目前为止有3条通知。),但在其他计算机上,此 endpoint < / strong>返回空数组=> []

第二个编辑:当我在浏览器上调试js文件时,这是我的回应,它无法访问设置为 HttpOnly cookies >,我试图用credentials:same-origin来获取,但实际上没有用。

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

2 个答案:

答案 0 :(得分:0)

如果只需要显示未读的通知,只需通过getNotifications()方法将其返回即可。

async function getNotifications() {
    try {
        ...
        var unreadNotifications = notifications.filter(notification => !notification.isRead);
        return unreadNotifications;
    } catch (e) {
        console.error(e);
    }
}

然后在notifyUser()中将其用作

getNotifications().then(unreadNotifications => {
    if (unreadNotifications.length > 0) {
        ...
    }

答案 1 :(得分:0)

使用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", redirected: true, status: 200, ok: true, …}

如果将您的 Cookie 设置为 HttpOnly = true ,那么您将使它们无法从 client 辅助脚本访问。

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

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);
            }
        });
    }