FullCalendar (v4) 不适用于有效 JSON

FullCalendar (v4) not working with valid JSON

我希望有人可以帮助 FullCalendar (v4) 在使用 Json 选项时不加载事件。当相同的数据被硬编码为事件时,它工作正常。

生成的 Json 有效 - 即它通过 https://jsoncompare.com

验证

我花了很多时间自己想办法解决这个问题,但我碰壁了 - 所以是时候寻求帮助了。

我试过使用内置的 Net Json 序列化程序 - 但这会产生错误的日​​期格式,所以我也尝试过 newtonsoft Json.net,它确实会为FullCallendar 但仍然不会加载事件。

使用 JSON 时没有 JS 控制台错误,它只是没有加载到日历中。 JSON 来自同一个域(即不受跨域问题的影响)。

欢迎任何help/advice,谢谢。

当事件被硬编码时,这非常有效:

var calendar = new FullCalendar.Calendar(calendarEl,
                {
                    plugins: ['interaction', 'dayGrid', 'timeGrid'],
                    defaultDate: new Date(),
                    defaultView: 'timeGridWeek',
                    minTime: '07:00:00',
                    maxTime: '22:00:00',
                    timeZone: 'local',
                    header: {
                        left: 'prev,next today',
                        center: 'title',
                        right: 'timeGridDay,timeGridWeek,dayGridMonth'
                    },
                    events: [ //hardcoded events load just fine
                            {
                                id: '12',
                                title: 'Event Name',
                                start: '2019-08-28T08:00:00',
                                end: '2019-08-28T08:30:00'
                            }
                        ]

                });

            calendar.render();

        }

当使用 JSON 选项时,它不起作用:

//JSON provided events do not load
events: {
          url:'/CourseTimetable/GetAllEventsAsJson' 
         }

提供 FEED 的替代方式(没有括号和 "url:" 前缀):

events:'/CourseTimetable/GetAllEventsAsJson' 

URL 工作正常 - 验证为 JSON - 并且不会产生任何错误 - 它产生:

"[{\"id\":12,\"title\":\"Event 1\",\"start\":\"2019-08-29T08:00:00\",\"end\":\"2019-08-29T08:30:00\"}]"

HEADER 和 cors 信息:

Content-Type: application/json; charset=utf-8
Referer: http://localhost:54928/CourseTimetable
Request Method: GET
Status Code: 200 OK

Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

提前感谢任何 help/advice :)

这是两个可供选择的控制器版本(使用标准 .net,然后使用 json.net)

标准.net

 public JsonResult GetAllEventsAsJson(DateTime? start = null, DateTime? end = null)
        {

            var events = db.CourseTimetables.Where(p => p.StartTime >= start && p.EndTime <= end)
                .Select(s => new
                {
                    id = s.Id,
                    title = s.Title,
                    start = s.StartTime,
                    end = s.EndTime
                }).ToList();

            //using built in .NET serialiser
            return new JsonResult { Data = events, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
        }

以上操作的输出(主要区别在于输出日期和转义):

[{"id":12,"title":"Event 1","start":"\/Date(1567062000000)\/","end":"\/Date(1567063800000)\/"},{"id":13,"title":"Event 2","start":"\/Date(1567148400000)\/","end":"\/Date(1567150200000)\/"}]

Json.Net版本

 public ActionResult GetAllEventsAsJson(DateTime? start = null, DateTime? end = null)
        {

            var events = db.CourseTimetables.Where(p => p.StartTime >= start && p.EndTime <= end)
                .Select(s => new
                {
                    id = s.Id,
                    title = s.Title,
                    start = s.StartTime,
                    end = s.EndTime
                }).ToList();

            //USING JSON.NET
            string jsonData = JsonConvert.SerializeObject(events);
            return Json(jsonData, JsonRequestBehavior.AllowGet);
        }

以上操作的输出(日期采用正确的 iso 格式):

"[{\"id\":12,\"title\":\"Event 1\",\"start\":\"2019-08-29T08:00:00\",\"end\":\"2019-08-29T08:30:00\"},{\"id\":13,\"title\":\"Event 2\",\"start\":\"2019-08-30T08:00:00\",\"end\":\"2019-08-30T08:30:00\"}]"

这种格式:"[{\"id\":12,\"title\":\"Event 1\",\"start\":\ ...等就是问题所在。您正在对数据进行双重序列化。看到那些外引号 (") 和斜杠 \ 了吗?外引号表示您正在 return 将一个简单的字符串作为响应( 有效的 JSON,但将被解析器视为纯文本),而斜杠是必须转义字符串中的引号的结果。因此,内部数据虽然看起来像 JSON,但不会被客户端解析器视为 JSON。相反,整个事情只是被视为一个大字符串,其中没有对象、属性等。

在 ASP.NET MVC 中,return Json... 希望您为其提供一个对象。然后它会自动为您将其序列化为 JSON。在传入之前不需要序列化它。只需删除该代码并将 events 直接发送到 Json() 方法:

public ActionResult GetAllEventsAsJson(DateTime? start = null, DateTime? end = null)
{
        var events = db.CourseTimetables.Where(p => p.StartTime >= start && p.EndTime <= end)
            .Select(s => new
            {
                id = s.Id,
                title = s.Title,
                start = s.StartTime,
                end = s.EndTime
            }).ToList();

        return Json(events, JsonRequestBehavior.AllowGet);
    }

P.S。您使用的是什么版本的 MVC?无论如何,最新的受支持版本使用 JSON.NET 作为默认序列化程序,因此没有理由必须手动执行。如果你有一个旧版本的 MVC(看起来你可能有,因为它会产生那些奇怪的日期格式,例如 Date(1567062000000)\)并且由于某种原因无法升级,默认情况下有 ways to make it use JSON.NET。或者,您可以使用 JSON.NET 自己进行序列化,然后仅 return 来自操作方法的纯字符串。

P.P.S。上述的另一种替代方法是使用 momentJS plugin in fullCalendar which then allows you to use momentJS to parse your dates - and momentJS includes the ability to parse ASP.NET's old date format.