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 JsonRes
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.
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 "ffffd, 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 = "ffffd, 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.
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.
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
.
add jquery ui plugin in your page.
function JsonDateFormate(dateFormate, jsonDateTime) {
return $.datepicker.formatDate(dateFormate, eval('new ' + jsonDateTime.slice(1, -1)));
};
Override the controllers Json/JsonResult to return JSON.Net:
This works a treat