ASP.NET MVC JsonResult Date Format

Javascriptasp.net MvcJson

Javascript Problem Overview


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?

Javascript Solutions


Solution 1 - Javascript

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.


The second parameter of JSON.parse() accepts a reviver function where prescribes how the value originally produced by, before being returned.

Here is an example for date:

var parsed = JSON.parse(data, function(key, value) {
  if (typeof value === 'string') {
    var d = /\/Date\((\d*)\)\//.exec(value);
    return (d) ? new Date(+d[1]) : value;
  }
  return value;
});

See the docs of JSON.parse()

Solution 2 - Javascript

Here's my solution in Javascript - very much like JPot's, 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.

EDIT: I have intentionally left out the radix (the 2nd argument to parseInt); see my comment below. Also, please note that ISO-8601 dates are preferred over this old format -- so this format generally shouldn't be used for new development.

For ISO-8601 formatted JSON dates, just pass the string into the Date constructor:

var date = new Date(jsonDate); //no ugly parsing needed; full timezone support

Solution 3 - Javascript

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][1]. If you take a look at the documentation, you can use the RegisterConverters method to add custom [JavaScriptConverters][2]. 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][3]. 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][4] 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));
        }
    }
}

Usage Example:

[HttpGet]
public ActionResult Index() {
    return new CustomJsonResult { Data = new { users=db.Users.ToList(); } };
}

Additional credits: [James Newton-King][5]

[1]: http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx "JsonScriptSerializer" [2]: http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptconverter.aspx "JavaScriptConverters" [3]: http://blog.calyptus.eu/seb/2011/12/custom-datetime-json-serialization/ "Custom DateTime Serialization" [4]: http://json.codeplex.com/ "Json.NET" [5]: http://james.newtonking.com/archive/2009/02/20/good-date-times-with-json-net.aspx "James Newton-King"

Solution 4 - Javascript

Moment.js is an extensive datetime library that also supports this. http://momentjs.com/docs/#/parsing/asp-net-json-dates/

ex: moment("/Date(1198908717056-0700)/")

It might help. plunker output

Solution 5 - Javascript

I found that creating a new JsonResult and returning that is unsatisfactory - having to replace all calls to return Json(obj) with return new MyJsonResult { Data = obj } is a pain.


So I figured, why not just hijack the JsonResult using an ActionFilter:

public class JsonNetFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Result is JsonResult == false)
        {
            return;
        }

        filterContext.Result = new JsonNetResult(
            (JsonResult)filterContext.Result);
    }

    private class JsonNetResult : JsonResult
    {
        public JsonNetResult(JsonResult jsonResult)
        {
            this.ContentEncoding = jsonResult.ContentEncoding;
            this.ContentType = jsonResult.ContentType;
            this.Data = jsonResult.Data;
            this.JsonRequestBehavior = jsonResult.JsonRequestBehavior;
            this.MaxJsonLength = jsonResult.MaxJsonLength;
            this.RecursionLimit = jsonResult.RecursionLimit;
        }

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

            var isMethodGet = string.Equals(
                context.HttpContext.Request.HttpMethod, 
                "GET", 
                StringComparison.OrdinalIgnoreCase);

            if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet
                && isMethodGet)
            {
                throw new InvalidOperationException(
                    "GET not allowed! Change JsonRequestBehavior to AllowGet.");
            }

            var response = context.HttpContext.Response;

            response.ContentType = string.IsNullOrEmpty(this.ContentType) 
                ? "application/json" 
                : this.ContentType;

            if (this.ContentEncoding != null)
            {
                response.ContentEncoding = this.ContentEncoding;
            }

            if (this.Data != null)
            {
                response.Write(JsonConvert.SerializeObject(this.Data));
            }
        }
    }
}

This can be applied to any method returning a JsonResult to use JSON.Net instead:

[JsonNetFilter]
public ActionResult GetJson()
{
    return Json(new { hello = new Date(2015, 03, 09) }, JsonRequestBehavior.AllowGet)
}

which will respond with

{"hello":"2015-03-09T00:00:00+00:00"}

as desired!


You can, if you don't mind calling the is comparison at every request, add this to your FilterConfig:

// ...
filters.Add(new JsonNetFilterAttribute());

and all of your JSON will now be serialized with JSON.Net instead of the built-in JavaScriptSerializer.

Solution 6 - Javascript

Using jQuery to auto-convert dates with $.parseJSON

> Note: this answer provides a jQuery extension that adds automatic ISO and .net date format support.

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().

Solution 7 - Javascript

Ajax communication between the client and the server often involves data in JSON format. While JSON works well for strings, numbers and Booleans it can pose some difficulties for dates due to the way ASP.NET serializes them. As it doesn't have any special representation for dates, they are serialized as plain strings. As a solution the default serialization mechanism of ASP.NET Web Forms and MVC serializes dates in a special form - /Date(ticks)/- where ticks is the number of milliseconds since 1 January 1970.

This problem can be solved in 2 ways:

client side

Convert the received date string into a number and create a date object using the constructor of the date class with the ticks as parameter.

function ToJavaScriptDate(value) {
  var pattern = /Date\(([^)]+)\)/;
  var results = pattern.exec(value);
  var dt = new Date(parseFloat(results[1]));
  return (dt.getMonth() + 1) + "/" + dt.getDate() + "/" + dt.getFullYear();
}

server side

The previous solution uses a client side script to convert the date to a JavaScript Date object. You can also use server side code that serializes .NET DateTime instances in the format of your choice. To accomplish this task you need to create your own ActionResult and then serialize the data the way you want.

reference : http://www.developer.com/net/dealing-with-json-dates-in-asp.net-mvc.html

Solution 8 - Javascript

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".

Solution 9 - Javascript

See this thread:

http://forums.asp.net/p/1038457/1441866.aspx#1441866

Basically, while the Date() format is valid javascript, it is NOT valid JSON (there is a difference). If you want the old format, you will probably have to create a facade and transform the value yourself, or find a way to get at the serializer for your type in the JsonResult and have it use a custom format for dates.

Solution 10 - Javascript

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;
}

Solution 11 - Javascript

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.

Solution 12 - Javascript

The better way to handle dates in knockoutjs is to use moment library and handle dates like boss. You can easily deal with dates like /Date(-62135578800000)/. No need to bother of how your serialize date in controller.

function jsonToDate(date,format) {
   return moment(date).format(format);
}

use it like

var formattedDate = jsonToDate(date,'MM/DD/YYYY')

momentjs supports lots of date time formats and utility functions on dates.

Solution 13 - Javascript

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.

Solution 14 - Javascript

Here's some JavaScript code I wrote which sets an <input type="date"> value from a date passed from ASP.NET MVC.

var setDate = function(id, d) {
  if (d !== undefined && d !== null) {
    var date = new Date(parseInt(d.replace("/Date(", "").replace(")/", ""), 10));
    var day = ('0' + date.getDate()).slice(-2);
    var month = ('0' + (date.getMonth() + 1)).slice(-2);
    var parsedDate = date.getFullYear() + "-" + (month) + "-" + (day);
    $(id).val(parsedDate);
  }
};

You call this function like so:

setDate('#productCommissionStartDate', data.commissionStartDate);

Where commissionStartDate is the JSON date passed by MVC.

Solution 15 - Javascript

You can use this method:

String.prototype.jsonToDate = function(){
    try{
        var date;
        eval(("date = new " + this).replace(/\//g,''));
        return date;
    } 
    catch(e){
        return new Date(0);
    }
};

Solution 16 - Javascript

add jquery ui plugin in your page.

function JsonDateFormate(dateFormate, jsonDateTime) {
    return $.datepicker.formatDate(dateFormate, eval('new ' + jsonDateTime.slice(1, -1)));
};

Solution 17 - Javascript

It returns Server Date Format. You need to define your own function.

function jsonDateFormat(jsonDate) {
  // Changed data format;
  return (new Date(parseInt(jsonDate.substr(6)))).format("mm-dd-yyyy / h:MM tt");
};

Solution 18 - Javascript

Not for nothing, but there is another way. First, construct your LINQ query. Then, construct a query of the Enumerated result and apply whatever type of formatting works for you.

var query = from t in db.Table select new { t.DateField };
var result = from c in query.AsEnumerable() select new { c.DateField.toString("dd MMM yyy") };

I have to say, the extra step is annoying, but it works nicely.

Solution 19 - Javascript

What worked for me was to create a viewmodel that contained the date property as a string. Assigning the DateTime property from the domain model and calling the .ToString() on the date property while assigning the value to the viewmodel.

A JSON result from an MVC action method will return the date in a format compatible with the view.

View Model

public class TransactionsViewModel
{
    public string DateInitiated { get; set; }
    public string DateCompleted { get; set; }
}

Domain Model

public class Transaction{
   public DateTime? DateInitiated {get; set;}
   public DateTime? DateCompleted {get; set;}
}

Controller Action Method

public JsonResult GetTransactions(){

var transactions = _transactionsRepository.All;
        var model = new List<TransactionsViewModel>();

        foreach (var transaction in transactions)
        {
            var item = new TransactionsViewModel
            {
                ...............
                DateInitiated = transaction.DateInitiated.ToString(),
                DateCompleted = transaction.DateCompleted.ToString(),
            };

            model.Add(item);
        }
        return Json(model, JsonRequestBehavior.AllowGet);
}

Solution 20 - Javascript

Override the controllers Json/JsonResult to return JSON.Net:

This works a treat

Solution 21 - Javascript

Annoying, isn't it ?

My solution was to change my WCF service to get it to return DateTimes in a more readable (non-Microsoft) format. Notice below, the "UpdateDateOriginal", which is WCF's default format of dates, and my "UpdateDate", which is formatted to something more readable.

enter image description here

Here's how to do it:

Changing WCF date format

Hope this helps.

Solution 22 - Javascript

I found this to be the easiest way to change it server side.

using System.Collections.Generic;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;

namespace Website
{
    /// <summary>
    /// This is like MVC5's JsonResult but it uses CamelCase and date formatting.
    /// </summary>
    public class MyJsonResult : ContentResult
    {
        private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            Converters = new List<JsonConverter> { new StringEnumConverter() }
        };

        public FindersJsonResult(object obj)
        {
            this.Content = JsonConvert.SerializeObject(obj, Settings);
            this.ContentType = "application/json";
        }
    }
}

Solution 23 - Javascript

I had a number of issues come up with JSON dates and decided to just get rid of the problem by addressing the date issue in the SQL. Change the date format to a string format

select flddate from tblName
    
select flddate, convert(varchar(12), flddate, 113) as fldDateStr from tblName

By using the fldDateStr the problem dissappeared and I could still use the date field for sorting or other purposes.

Solution 24 - Javascript

0

In your cshtml,

<tr ng-repeat="value in Results">                
 <td>{{value.FileReceivedOn | mydate | date : 'dd-MM-yyyy'}} </td>
</tr>

In Your JS File, maybe app.js,

Outside of app.controller, add the below filter.

Here the "mydate" is the function which you are calling for parsing the date. Here the "app" is the variable which contains the angular.module

app.filter("mydate", function () {
    var re = /\/Date\(([0-9]*)\)\//;
    return function (x) {
        var m = x.match(re);
        if (m) return new Date(parseInt(m[1]));
        else return null;
    };
});

Solution 25 - Javascript

The easiest one:

var milisegundos = parseInt(data.replace("/Date(", "").replace(")/", ""));
Var newDate = new Date(milisegundos).toLocaleDateString("en-UE");

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJon ArchwayView Question on Stackoverflow
Solution 1 - JavascriptJPotView Answer on Stackoverflow
Solution 2 - JavascriptRoy TinkerView Answer on Stackoverflow
Solution 3 - JavascriptPerishable DaveView Answer on Stackoverflow
Solution 4 - JavascriptEricView Answer on Stackoverflow
Solution 5 - Javascriptdav_iView Answer on Stackoverflow
Solution 6 - JavascriptRobert KoritnikView Answer on Stackoverflow
Solution 7 - JavascriptMischaView Answer on Stackoverflow
Solution 8 - JavascriptJoeView Answer on Stackoverflow
Solution 9 - JavascriptcasperOneView Answer on Stackoverflow
Solution 10 - JavascriptGabeView Answer on Stackoverflow
Solution 11 - JavascriptJesseView Answer on Stackoverflow
Solution 12 - JavascriptAjay KelkarView Answer on Stackoverflow
Solution 13 - JavascriptChadView Answer on Stackoverflow
Solution 14 - JavascriptTribal CoderView Answer on Stackoverflow
Solution 15 - JavascripteladmatView Answer on Stackoverflow
Solution 16 - JavascriptThulasiramView Answer on Stackoverflow
Solution 17 - JavascriptManish KunduView Answer on Stackoverflow
Solution 18 - JavascriptskrileView Answer on Stackoverflow
Solution 19 - JavascriptOladipo OlasemoView Answer on Stackoverflow
Solution 20 - JavascriptIanView Answer on Stackoverflow
Solution 21 - JavascriptMike GledhillView Answer on Stackoverflow
Solution 22 - JavascriptMohamed FakhreddineView Answer on Stackoverflow
Solution 23 - JavascriptHarry BinnendykView Answer on Stackoverflow
Solution 24 - JavascriptMohamedasiqView Answer on Stackoverflow
Solution 25 - JavascriptKenlly AcostaView Answer on Stackoverflow