ASP.NET MVC Json.Encode() DateTime encoding issue string not date type
Asked Answered
V

6

11

I am having an issue with the JavaScript that is produced by ASP.NET MVC's System.Web.Helpers.Json.Encode() if the model includes a DateTime property.

My Model:

public class MyViewModel
{
    public string MyString { get; set; }
    public DateTime MyDateTime { get; set; }
    public int MyInt { get; set; }
    public string[] MyStringArray { get; set; }
}

My Controller:

public ActionResult Index()
{
    var myViewModel = new MyViewModel();
    myViewModel.MyString = "My test string";
    myViewModel.MyInt = 100;
    myViewModel.MyDateTime = DateTime.Now;
    myViewModel.MyStringArray = new string[] { "string 1", "string 2" };

    return View(myViewModel);
}

My View:

<script type="text/javascript">

    var myViewModel = @Html.Raw(Json.Encode(Model)) ;

</script>

The Output:

<script type="text/javascript">

    var myViewModel = {"MyString":"My test string","MyDateTime":"\/Date(1372280916431)\/","MyInt":100,"MyStringArray":["string 1","string 2"]} ;

</script>

The issue is with the way the date is being encoded. It is a string and not a Date type.

I have also tried using Newtonsoft.Json.JsonConvert.SerializeObject() and I still get a string and not a Date type.

Vita answered 26/6, 2013 at 22:7 Comment(0)
H
2

This behavior is by design.

JSON (unlike Javascript) doesn't have a date type.

Heavyhanded answered 26/6, 2013 at 22:10 Comment(2)
You can add types by including a $type member and can preserve references and cyclic references via the $id and $ref members. By using a custom replacer callback to handle stringification: JSON.stringify(value[, replacer[, space]])), you can embed these members properly. JSON.NET can then interpret and revive objects with strong types, as long as those types exist on the server-side. You can implement your own type-mapping scheme (I've done intermediate types, template types, namespace mirroring, etc.), built into JSON.NET. It's easier in AS3 due to strong types, unlike JavaScript.Damnable
To embed references, you add objects to a hash as they're encountered. You always check the hash to see if the object has already been serialized, and if it has, then you grab the ID from the hash and just embed a {$ref:id} in the string. Again, this is easier in Flash/AS3 because it actually supports object references as keys in its Dictionary class, while JavaScript doesn't. JavaScript converts all keys to strings, which is useless for objects. The only workaround until the standard catches up with AS3, is to override object.prototype to give every object a unique string ID very early.Damnable
P
8

Date type has no literals in JavaScript. You will have to call its constructor.

var myDate = new Date(@Html.Raw(Json.Encode(Model.MyDateTime)));
Permissive answered 26/6, 2013 at 22:11 Comment(0)
H
2

This behavior is by design.

JSON (unlike Javascript) doesn't have a date type.

Heavyhanded answered 26/6, 2013 at 22:10 Comment(2)
You can add types by including a $type member and can preserve references and cyclic references via the $id and $ref members. By using a custom replacer callback to handle stringification: JSON.stringify(value[, replacer[, space]])), you can embed these members properly. JSON.NET can then interpret and revive objects with strong types, as long as those types exist on the server-side. You can implement your own type-mapping scheme (I've done intermediate types, template types, namespace mirroring, etc.), built into JSON.NET. It's easier in AS3 due to strong types, unlike JavaScript.Damnable
To embed references, you add objects to a hash as they're encountered. You always check the hash to see if the object has already been serialized, and if it has, then you grab the ID from the hash and just embed a {$ref:id} in the string. Again, this is easier in Flash/AS3 because it actually supports object references as keys in its Dictionary class, while JavaScript doesn't. JavaScript converts all keys to strings, which is useless for objects. The only workaround until the standard catches up with AS3, is to override object.prototype to give every object a unique string ID very early.Damnable
D
2

Drawing inspiration from these answers, I needed to pass my nullable date to an MVC controller and have it model bound correctly. This is where i landed:

  var dob = @Html.Raw(Json.Encode(Model.BirthDate.HasValue ? Model.BirthDate.Value.ToShortDateString() : null));
Dudeen answered 11/9, 2014 at 17:42 Comment(0)
R
2

Using Newtonsoft to encode the object results in an ISO formatted date.

@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model))

Date Format:

0001-01-01T00:00:00
Radiobroadcast answered 24/2, 2020 at 17:5 Comment(0)
G
1

You can use

var myDate = new Date(parseInt('@Html.Raw(Json.Encode(Model.MyDateTime))'.substr(6)));

or

var myDate = new Date(parseInt('@Html.Raw(Json.Encode(Model.MyDateTime))'.replace('/Date(', '')));

Both ignores the '/Date(' part and with "parseInt" you are ignoring the last ')/' part. Then getting the date object from miliseconds.

But don't forget that when you create Date() object it is created according to Browser's GMT time.

When using this Date() object in my javascript code I always use UTC Date methods like: myDate.getUTCHours();

Grounds answered 23/9, 2013 at 13:52 Comment(0)
A
0

Using the Forloop.HtmlHelpers nuget package you can get the AddScriptBlock HtmlHelper extension and do something like this with the Newtonsoft call to set a variable in script:

@{
using (var context = Html.BeginScriptContext())
{
    Html.AddScriptBlock(@"
$(function () {
        var data = " + JsonConvert.SerializeObject( Model.Data ) + @";
        ///continue processing ...
});");
}

}

Agglutinin answered 8/2, 2014 at 11:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.