Skip to main content

ASP.NET MVC JsonResult Date Format


I have a controller action that effectively simply returns a JsonResult of my model. So, in my method I have something like the following:




return new JsonResult(myModel);



This works well, except for one problem. There is a date property in the model and this appears to be returned in the Json result like so:




"\/Date(1239018869048)\/"



How should I be dealing with dates so they are returned in the format I require? Or how do I handle this format above in script?


Source: Tips4allCCNA FINAL EXAM

Comments

  1. Just to expand on CasperOne's answer.

    The JSON spec does not account for Date values. MS had to make a call, and the path they chose was to exploit a little trick in the javascript representation of strings: the string literal "/" is the same as "\/", and a string literal will never get serialized to "\/" (even "\/" must be mapped to "\\/").

    See http://msdn.microsoft.com/en-us/library/bb299886.aspx#intro_to_json_topic2 for a better explanation (scroll down to "From JavaScript Literals to JSON")


    One of the sore points of JSON is the
    lack of a date/time literal. Many
    people are surprised and disappointed
    to learn this when they first
    encounter JSON. The simple explanation
    (consoling or not) for the absence of
    a date/time literal is that JavaScript
    never had one either: The support for
    date and time values in JavaScript is
    entirely provided through the Date
    object. Most applications using JSON
    as a data format, therefore, generally
    tend to use either a string or a
    number to express date and time
    values. If a string is used, you can
    generally expect it to be in the ISO
    8601 format. If a number is used,
    instead, then the value is usually
    taken to mean the number of
    milliseconds in Universal Coordinated
    Time (UTC) since epoch, where epoch is
    defined as midnight January 1, 1970
    (UTC). Again, this is a mere
    convention and not part of the JSON
    standard. If you are exchanging data
    with another application, you will
    need to check its documentation to see
    how it encodes date and time values
    within a JSON literal. For example,
    Microsoft's ASP.NET AJAX uses neither
    of the described conventions. Rather,
    it encodes .NET DateTime values as a
    JSON string, where the content of the
    string is \/Date(ticks)\/ and where
    ticks represents milliseconds since
    epoch (UTC). So November 29, 1989,
    4:55:30 AM, in UTC is encoded as
    "\/Date(628318530718)\/".


    A solution would be to just parse it out:

    value = new Date(parseInt(value.replace("/Date(", "").replace(")/",""), 10));


    However I've heard that there is a setting somewhere to get the serializer to output DateTime objects with the new Date(xxx) syntax. I'll try to dig that out.

    ReplyDelete
  2. Here's my solution in Javascript - very much like JPots', but shorter (and possibly a tiny bit faster):

    value = new Date(parseInt(value.substr(6)));


    "value.substr(6)" takes out the "/Date(" part, and the parseInt function ignores the non-number characters that occur at the end.

    ReplyDelete
  3. Using jQuery to auto-convert dates with $.parseJSON

    Since you're using Asp.net MVC I suspect you're using jQuery on the client side. I suggest you read this blog post that has code how to use $.parseJSON to automatically convert dates for you.

    Code supports Asp.net formatted dates like the ones you mentioned as well as ISO formatted dates. All dates will be automatically formatted for you by using $.parseJSON().

    ReplyDelete
  4. There are quite a bit of answers to handle it client side, but you can change the output server side if you desired.

    There are a few ways to approach this, I'll start with the basics. You'll have to subclass the JsonResult class and override the ExecuteResult method. From there you can take a few different approaches to change the serialization.

    Approach 1:
    The default implementation uses the JsonScriptSerializer. If you take a look at the documentation, you can use the RegisterConverters method to add custom JavaScriptConverters. There are a few problems with this though: The JavaScriptConverter serializes to a dictionary, that is it takes an object and serializes to a Json dictionary. In order to make the object serialize to a string it requires a bit of hackery, see post. This particular hack will also escape the string.

    public class CustomJsonResult : JsonResult
    {
    private const string _dateFormat = "yyyy-MM-dd hh:mm:ss";

    public override void ExecuteResult(ControllerContext context)
    {
    if (context == null)
    {
    throw new ArgumentNullException("context");
    }

    HttpResponseBase response = context.HttpContext.Response;

    if (!String.IsNullOrEmpty(ContentType))
    {
    response.ContentType = ContentType;
    }
    else
    {
    response.ContentType = "application/json";
    }
    if (ContentEncoding != null)
    {
    response.ContentEncoding = ContentEncoding;
    }
    if (Data != null)
    {
    JavaScriptSerializer serializer = new JavaScriptSerializer();

    // Use your custom JavaScriptConverter subclass here.
    serializer.RegisterConverters(new JavascriptConverter[] { new CustomConverter });

    response.Write(serializer.Serialize(Data));
    }
    }
    }


    Approach 2 (recommended):
    The second approach is to start with the overridden JsonResult and go with another Json serializer, in my case the Json.NET serializer. This doesn't require the hackery of approach 1. Here is my implementation of the JsonResult subclass:

    public class CustomJsonResult : JsonResult
    {
    private const string _dateFormat = "yyyy-MM-dd hh:mm:ss";

    public override void ExecuteResult(ControllerContext context)
    {
    if (context == null)
    {
    throw new ArgumentNullException("context");
    }

    HttpResponseBase response = context.HttpContext.Response;

    if (!String.IsNullOrEmpty(ContentType))
    {
    response.ContentType = ContentType;
    }
    else
    {
    response.ContentType = "application/json";
    }
    if (ContentEncoding != null)
    {
    response.ContentEncoding = ContentEncoding;
    }
    if (Data != null)
    {
    // Using Json.NET serializer
    var isoConvert = new IsoDateTimeConverter();
    isoConvert.DateTimeFormat = _dateFormat;
    response.Write(JsonConvert.SerializeObject(Data, isoConvert));
    }
    }
    }


    Additional credits:
    James Newton-King

    ReplyDelete
  5. I have been working on a solution to this issue as none of the above answers really helped me. I am working with the jquery week calendar and needed my dates to have time zone information on the server and locally on the page. After quite a bit of digging around, I figured out a solution that may help others.

    I am using asp.net 3.5, vs 2008, asp.net MVC 2, and jquery week calendar,

    First, I am using a library written by Steven Levithan that helps with dealing with dates on the client side, Steven Levithan's date library. The isoUtcDateTime format is perfect for what I needed. In my jquery AJAX call I use the format function provided with the library with the isoUtcDateTime format and when the ajax call hits my action method, the datetime Kind is set to local and reflects the server time.

    When I send dates to my page via AJAX, I send them as text strings by formatting the dates using "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'zzzz". This format is easily converted client side using

    var myDate = new Date(myReceivedDate);


    Here is my complete solution minus Steve Levithan's source, which you can download:

    Controller:

    public class HomeController : Controller
    {
    public const string DATE_FORMAT = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'zzzz";

    public ActionResult Index()
    {
    ViewData["Message"] = "Welcome to ASP.NET MVC!";

    return View();
    }

    public ActionResult About()
    {
    return View();
    }


    public JsonResult GetData()
    {
    DateTime myDate = DateTime.Now.ToLocalTime();

    return new JsonResult { Data = new { myDate = myDate.ToString(DATE_FORMAT) } };
    }

    public JsonResult ReceiveData(DateTime myDate)
    {
    return new JsonResult { Data = new { myDate = myDate.ToString(DATE_FORMAT) } };
    }
    }


    Javascript:

    <script type="text/javascript">

    function getData() {
    $.ajax({
    url: "/Home/GetData",
    type: "POST",
    cache: "false",
    dataType: "json",
    success: function(data) {
    alert(data.myDate);
    var newDate = cleanDate(data.myDate);
    alert(newDate);
    sendData(newDate);
    }
    });
    }

    function cleanDate(d) {
    if (typeof d == 'string') {
    return new Date(d) || Date.parse(d) || new Date(parseInt(d));
    }
    if (typeof d == 'number') {
    return new Date(d);
    }
    return d;
    }

    function sendData(newDate) {
    $.ajax({
    url: "/Home/ReceiveData",
    type: "POST",
    cache: "false",
    dataType: "json",
    data:
    {
    myDate: newDate.format("isoUtcDateTime")
    },
    success: function(data) {
    alert(data.myDate);
    var newDate = cleanDate(data.myDate);
    alert(newDate);
    }
    });
    }

    // bind myButton click event to call getData
    $(document).ready(function() {
    $('input#myButton').bind('click', getData);
    });
    </script>


    I hope this quick example helps out others in the same situation I was in. At this time it seems to work very well with the Microsoft JSON Serialization and keeps my dates correct across timezones.

    ReplyDelete
  6. If you doing eval("(" + jsonResult + ")") on the result, it should work. You may be best to, as mentioned, do a cusom serialization of the date/time to a client specific GMT/UTC string. Dates aren't defined within the JSON specification, but using Date(TIME_T) will work unless you are doing client-side validation of JSON responses.

    Edit:example


    var o = eval("({ dtm: new Date('1990/01/05') })");
    alert(o.dtm);

    //milliseconds from 1970-01-01 to 1990-01-05 aka TIME_T * 1000
    o = eval("({ dtm: new Date(631522800000) })");
    alert(o.dtm);


    both work...

    ReplyDelete
  7. Not the most elegant way but this worked for me:

    var ms = date.substring(6, date.length - 2);
    var newDate = formatDate(ms);


    function formatDate(ms) {

    var date = new Date(parseInt(ms));
    var hour = date.getHours();
    var mins = date.getMinutes() + '';
    var time = "AM";

    // find time
    if (hour >= 12) {
    time = "PM";
    }
    // fix hours format
    if (hour > 12) {
    hour -= 12;
    }
    else if (hour == 0) {
    hour = 12;
    }
    // fix minutes format
    if (mins.length == 1) {
    mins = "0" + mins;
    }
    // return formatted date time string
    return date.getMonth() + 1 + "/" + date.getDate() + "/" + date.getFullYear() + " " + hour + ":" + mins + " " + time;
    }

    ReplyDelete
  8. I had the same problem and instead of returning the actual date value I just used ToString("dd MMM yyyy") on it. Then in my javascript I used new Date(datevalue), where datevalue may be "01 Jan 2009".

    ReplyDelete
  9. Format the date within the query.

    var _myModel = from _m in model.ModelSearch(word)
    select new { date = ((DateTime)_m.Date).ToShortDateString() };


    The only problem with this solution is that you won't get any results if ANY of the date values are null. To get around this you could either put conditional statements in your query BEFORE you select the date that ignores date nulls or you could set up a query to get all the results and then loop through all of that info using a foreach loop and assign a value to all dates that are null BEFORE you do your SELECT new.

    Example of both:

    var _test = from _t in adc.ItemSearchTest(word)
    where _t.Date != null
    select new { date = ((DateTime)_t.Date).ToShortDateString() };


    The second option requires another query entirely so you can assign values to all nulls. This and the foreach loop would have to be BEFORE your query that selects the values.

    var _testA = from _t in adc.ItemSearchTest(word)
    select _i;

    foreach (var detail in _testA)
    {
    if (detail.Date== null)
    {
    detail.Date= Convert.ToDateTime("1/1/0001");
    }
    }


    Just an idea which I found easier than all of the javascript examples.

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex