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

Why is this Javascript much *slower* than its jQuery equivalent?

I have a HTML list of about 500 items and a "filter" box above it. I started by using jQuery to filter the list when I typed a letter (timing code added later): $('#filter').keyup( function() { var jqStart = (new Date).getTime(); var search = $(this).val().toLowerCase(); var $list = $('ul.ablist > li'); $list.each( function() { if ( $(this).text().toLowerCase().indexOf(search) === -1 ) $(this).hide(); else $(this).show(); } ); console.log('Time: ' + ((new Date).getTime() - jqStart)); } ); However, there was a couple of seconds delay after typing each letter (particularly the first letter). So I thought it may be slightly quicker if I used plain Javascript (I read recently that jQuery's each function is particularly slow). Here's my JS equivalent: document.getElementById('filter').addEventListener( 'keyup', function () { var jsStart = (new Date).getTime()...

Is it possible to have IF statement in an Echo statement in PHP

Thanks in advance. I did look at the other questions/answers that were similar and didn't find exactly what I was looking for. I'm trying to do this, am I on the right path? echo " <div id='tabs-".$match."'> <textarea id='".$match."' name='".$match."'>". if ($COLUMN_NAME === $match) { echo $FIELD_WITH_COLUMN_NAME; } else { } ."</textarea> <script type='text/javascript'> CKEDITOR.replace( '".$match."' ); </script> </div>"; I am getting the following error message in the browser: Parse error: syntax error, unexpected T_IF Please let me know if this is the right way to go about nesting an IF statement inside an echo. Thank you.