Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Uncaught TypeError: i.Started.toUTCString is not a functionΒ #370

@tomglover24

Description

@tomglover24

I was looking to integrate MiniProfiler to an ASP.net Core 2.2 MVC app and have come across a rendering issue. This issue only affects rendering of the MiniProfiler widget and seems to be related to the format that Started is being provided in JSON back to the widget.

Setup

  • .Net Core 2.2
  • ASP.Net Core 2.2.0 MVC
  • MiniProfiler.AspNetCore.Mvc 4.0.165
  • MiniProfiler.Providers.MySql 4.0.165
  • Default config from the getting started page, with the exception of:
options.Storage = new MySqlStorage(Configuration["ConnectionStrings:DefaultConnection"]);

The Full Error

Uncaught TypeError: i.Started.toUTCString is not a function
    at n.renderProfiler (includes.min.js?v=4.0.165+g04f8ac4653:formatted:4790)
    at n.buttonShow (includes.min.js?v=4.0.165+g04f8ac4653:formatted:4800)
    at Object.success (includes.min.js?v=4.0.165+g04f8ac4653:formatted:4552)
    at l (includes.min.js?v=4.0.165+g04f8ac4653:formatted:1825)
    at Object.fireWith [as resolveWith] (includes.min.js?v=4.0.165+g04f8ac4653:formatted:1876)
    at b (includes.min.js?v=4.0.165+g04f8ac4653:formatted:3539)
    at XMLHttpRequest.<anonymous> (includes.min.js?v=4.0.165+g04f8ac4653:formatted:3757)

Example JS Response

{"Id":"d0d344d0-fed2-4215-9bcd-71039db08141","Name":"Home/Index","Started":"2019-03-16T15:54:50Z","DurationMilliseconds":3.0,"MachineName":"LDCL139658","Root":{"Id":"4649f8ab-5119-483c-9025-aedcf7c58ac4","Name":"https://localhost:44326/","DurationMilliseconds":3.000,"StartMilliseconds":0.000,"Children":[{"Id":"60d2bc5d-6ca1-4f55-b551-9a90b707eef4","Name":"MiniProfiler Prep","DurationMilliseconds":1.400,"StartMilliseconds":0.000},{"Id":"7c551655-915b-4995-82a8-b620f9b41937","Name":"Controller: Home.Index","DurationMilliseconds":0.000,"StartMilliseconds":1.600},{"Id":"6dba533e-96df-425d-a81f-6583fdc89146","Name":"Find: Index","DurationMilliseconds":0.000,"StartMilliseconds":1.600},{"Id":"0fb7b931-b50d-43a4-bf01-9184033e9fc7","Name":"Render: /Views/Home/Index.cshtml","DurationMilliseconds":0.700,"StartMilliseconds":1.700,"Children":[{"Id":"7b4023c6-4c7b-40c2-855b-b87b7f1c3939","Name":"Find: _CookieConsentPartial","DurationMilliseconds":0.000,"StartMilliseconds":2.200},{"Id":"ecbdccb1-b652-42d5-b8c1-0550a8290190","Name":"Render: /Views/Shared/_CookieConsentPartial.cshtml","DurationMilliseconds":0.000,"StartMilliseconds":2.300}]}]},"ClientTimings":{"RedirectCount":0,"Timings":[{"Name":"fetchStart","Start":0.0,"Duration":0.0},{"Name":"domainLookupStart","Start":0.0,"Duration":0.0},{"Name":"connectStart","Start":0.0,"Duration":0.0},{"Name":"requestStart","Start":3.0,"Duration":11.0},{"Name":"responseStart","Start":14.0,"Duration":13.0},{"Name":"domLoading","Start":27.0,"Duration":36.0},{"Name":"firstPaintTime","Start":220.0,"Duration":0.0},{"Name":"domInteractive","Start":282.0,"Duration":0.0},{"Name":"domContentLoadedEventStart","Start":282.0,"Duration":1.0},{"Name":"domComplete","Start":316.0,"Duration":0.0},{"Name":"loadEventStart","Start":316.0,"Duration":0.0}]},"User":"4","HasUserViewed":true}

The key value being "Started":"2019-03-16T15:54:50Z"

Looking through the source I think I may have traced this to how the js handles the full page rendering and button rendering specifically JSON Ajax response is parsed using this regex:

const isoDate = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*))(?:Z|(\+|-)([\d|:]*))?$/;
const parseDates = (key: string, value: any) =>
key === 'Started' && typeof value === 'string' && isoDate.exec(value) ? new Date(value) : value;
mp.fetchStatus[id] = 'Starting fetch';
this.jq.ajax({
url: this.options.path + 'results',
data: JSON.stringify(request),
dataType: 'json',
contentType: 'application/json',
type: 'POST',
converters: {
'text json': (result) => JSON.parse(result, parseDates),
},

Vs the full html page which takes a JS object, assumes the string is correct and just parses it:

// profiler will be defined in the full page's head
window.profiler.Started = new Date('' + window.profiler.Started); // Ugh, JavaScript

The Underlying Fault
The underlying fault seems to be the lack of precision returned from MySQL causing the iso date format to be simplified when converted to a string, ignoring the micro seconds.

A small change to the regex string used to Parse the dates to allow for optional micro seconds resolves the parsing issue:

isoDate = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)(?:Z|(\+|-)([\d|:]*))?$/;

Sorry if this was not enough detail or incorrectly formatted, this is my first OSS issue.

I will try and create a pull request for this too, I haven't built the full repo to test the fix, as I don't know how and have never used typescript, I'm still learning C# with simple repos.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions