ASP。. NET MVC JsonResult Date格式

我有一个控制器动作,它有效地简单地返回模型的JsonResult。所以,在我的方法中,我有如下内容:

return new JsonResult(myModel);

这很有效,除了一个问题。在模型中有一个日期属性,这似乎在Json结果中返回,如下所示:

"\/Date(1239018869048)\/"

我应该如何处理日期,以便它们以我所需的格式返回?或者我如何处理脚本上面的这种格式?

199297 次浏览

请看这个帖子:

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

基本上,虽然Date()格式是有效的javascript,但它不是有效的JSON(有区别)。如果你想要旧的格式,你可能必须自己创建一个facade并转换值,或者找到一种方法来获得JsonResult中你的类型的序列化器,并让它使用自定义的日期格式。

只是展开casperOne的回答

JSON规范不考虑Date值。MS不得不进行调用,他们选择的路径是利用javascript字符串表示中的一个小技巧:字符串字面量“/”与“\/”相同,字符串字面量从来没有将被序列化为“\/”(即使“\/”也必须映射为“\\/”)。

请参阅http://msdn.microsoft.com/en-us/library/bb299886.aspx#intro_to_json_topic2以获得更好的解释(向下滚动到“从JavaScript文字到JSON”)

JSON的一个痛点是 缺少日期/时间文字。许多 人们既惊讶又失望 当他们第一次学会这个 遇到JSON。简单的解释 (安慰与否)的缺席 日期/时间文字就是JavaScript 也从来没有过:支持 日期和时间值在JavaScript是 完全由日期提供 对象。使用JSON的大多数应用程序 因此,作为一种数据格式 倾向于使用字符串或 表示日期和时间的数字 值。如果使用字符串,则可以 一般期望它在ISO中 8601格式。如果使用数字, 相反,值通常是 指…的数量 毫秒的通用协调 自epoch以来的时间(UTC),其中epoch为 定义为1970年1月1日午夜 (UTC)。同样,这是一个单纯的 而不是JSON的一部分 标准。如果您正在交换数据 在另一个应用程序中,您就可以做到 需要查一下它的文档才能看到 它如何编码日期和时间值 在JSON文本中。例如, 微软的ASP。NET AJAX两者都不使用 所描述的约定。相反, 它将.NET DateTime值编码为 的内容 字符串是/Date(ticks)/和where Ticks表示毫秒,因为 时代(UTC)。1989年11月29日, 4:55:30 AM,在UTC编码为 “\ /日期(628318530718)\ /”。< / p >

一个解决办法就是把它解析出来:

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

然而,我听说在某个地方有一个设置,可以让序列化器用new Date(xxx)语法输出DateTime对象。我试着把它挖出来。


JSON.parse()的第二个形参接受一个reviver函数,该函数规定了返回值之前的初始生成方式。

下面是一个关于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;
});

参见JSON.parse ()的文档

下面是我的Javascript解决方案——非常像JPot,但更短(可能更快一点):

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

“value.substr(6)“;拿出&;/日期(&;部分,parseInt函数忽略出现在末尾的非数字字符。

编辑:我故意省略了基数(parseInt的第二个参数);看到我的评论如下。另外,请注意ISO-8601日期比这种旧格式更受欢迎——因此这种格式通常不应该用于新的开发。

对于ISO-8601格式的JSON日期,只需将字符串传递给Date构造函数:

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

这不是最优雅的方式,但对我来说很管用:

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

我有同样的问题,而不是返回实际的日期值,我只是使用ToString(“dd MMM yyyy”)。然后在我的javascript中,我使用了新的日期(datevalue),其中datevalue可能是“01 Jan 2009”。

我一直在研究这个问题的解决方案,因为上面的答案都没有真正帮助到我。我正在使用jquery周日历,需要我的日期在服务器和本地页面上有时区信息。经过一番深入研究,我想出了一个可能会帮助到其他人的解决方案。

我使用asp.net 3.5, vs 2008, asp.net MVC 2,和jquery周日历,

首先,我使用Steven Levithan编写的库,它有助于处理客户端上的日期,史蒂文·利维坦的数据库。isoUtcDateTime格式非常适合我所需要的。在我的jquery AJAX调用中,我使用isoUtcDateTime格式库提供的格式函数,当AJAX调用命中我的动作方法时,datetime Kind被设置为本地并反映服务器时间。

当我通过AJAX发送日期到我的页面时,我通过使用“ddd, dd MMM yyyy HH':'mm':'ss 'GMT'zzzz”格式化日期将它们作为文本字符串发送。这种格式在客户端使用时很容易转换

var myDate = new Date(myReceivedDate);

以下是我的完整解决方案,减去Steve Levithan的源代码,你可以下载:

控制器:

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>

我希望这个简单的例子能帮助那些和我处境相同的人。在这个时候,它似乎工作得很好与微软JSON序列化和保持我的日期跨时区正确。

使用jQuery自动转换日期$.parseJSON

< em >注意:这个答案提供了一个jQuery扩展,添加了自动ISO和.net日期格式支持

因为你使用Asp.net MVC,我怀疑你在客户端使用jQuery。我建议你阅读这篇博文,它有代码如何使用$.parseJSON为你自动转换日期。

代码支持Asp.net格式的日期,就像你提到的,以及ISO格式的日期。所有日期都将通过使用$.parseJSON()自动格式化。

在查询中格式化日期。

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

此解决方案的唯一问题是,如果任何日期值为空,则不会得到任何结果。为了解决这个问题,你可以在你选择忽略日期null的日期之前在你的查询中放入条件语句,或者你可以设置一个查询来获得所有结果,然后使用foreach循环遍历所有这些信息,并在你执行select new之前为所有日期赋值。

两者的例子:

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

第二个选项需要完全另一个查询,因此可以将值赋给所有空值。这个循环和foreach循环必须在选择值的查询之前。

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

只是一个想法,我发现比所有的javascript例子更容易。

客户端有很多解决方案,但是如果您愿意,可以更改输出服务器端。

有一些方法可以解决这个问题,我将从基本的开始。您必须创建JsonResult类的子类,并重写ExecuteResult方法。在此基础上,您可以采用几种不同的方法来更改序列化。

< >强方法1: 默认实现使用JsonScriptSerializer。如果你看一下文档,你可以使用RegisterConverters方法来添加自定义JavaScriptConverters。但是有一些问题:JavaScriptConverter序列化到一个字典,也就是它接受一个对象并序列化到一个Json字典。为了使对象序列化为字符串,它需要一些技巧,参见帖子。这个特殊的hack也将转义字符串。

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

方法二(推荐): 第二种方法是从重写的JsonResult开始,然后使用另一个Json序列化器,在我的例子中是Json。网序列化器。这并不需要方法1的技巧。下面是我的JsonResult子类的实现:

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

使用的例子:

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

< >强额外的学分: 詹姆斯Newton-King < / p >

在页面中添加jquery UI插件。

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

js是一个扩展的datetime库,它也支持这个功能。http://momentjs.com/docs/#/parsing/asp-net-json-dates/

例:时刻”(/日期(1198908717056 - 0700)/”)

这可能会有帮助。恰好输出

它返回服务器日期格式。你需要定义自己的函数。

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

下面是我编写的一些JavaScript代码,用于从ASP传递的日期设置<input type="date">值。净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);
}
};

你可以这样调用这个函数:

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

其中commissionStartDate是MVC传递的JSON日期。

你可以使用这个方法:

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

不是没有原因,而是还有别的办法。首先,构造LINQ查询。然后,构造枚举结果的查询,并应用适合您的格式类型。

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

我不得不说,额外的步骤很烦人,但效果很好。

在knockoutjs中处理日期的更好方法是使用moment库并像boss一样处理日期。您可以轻松地处理/Date(-62135578800000)/这样的日期。不需要担心如何在控制器中序列化日期。

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

像这样使用它

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

momentjs支持大量日期时间格式和日期实用函数。

客户端和服务器之间的Ajax通信通常涉及JSON格式的数据。虽然JSON可以很好地处理字符串、数字和布尔值,但由于ASP。NET序列化它们。因为它对日期没有任何特殊的表示,所以它们被序列化为普通字符串。 作为一种解决方案,ASP的缺省序列化机制。NET Web Forms和MVC以一种特殊的形式序列化日期- /Date(ticks)/-其中ticks是自1970年1月1日以来的毫秒数

这个问题有两种解决方法:

客户端

将接收到的日期字符串转换为数字,并使用日期类的构造函数以tick为参数创建日期对象。

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

服务器端

前面的解决方案使用客户端脚本将日期转换为JavaScript date对象。您还可以使用服务器端代码以您选择的格式序列化. net DateTime实例。 要完成这个任务,你需要创建自己的ActionResult,然后以你想要的方式序列化数据 < p >参考: http://www.developer.com/net/dealing-with-json-dates-in-asp.net-mvc.html < / p >

对我来说有用的是创建一个包含date属性为字符串的视图模型。从域模型分配DateTime属性,并在为视图模型分配值时调用date属性上的. tostring()。

来自MVC操作方法的JSON结果将以与视图兼容的格式返回日期。

视图模型

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

域模型

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

控制器动作方法

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

我发现创建一个新的JsonResult并返回它是不令人满意的-必须用return new MyJsonResult { Data = obj }替换所有对return Json(obj)的调用是一种痛苦。


所以我想,为什么不直接使用ActionFilter劫持JsonResult:

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

这可以应用于任何返回JsonResult以使用JSON的方法。网:

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

它会回应

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

根据需要!


如果你不介意在每个请求时调用is比较,你可以将这个添加到你的FilterConfig:

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

所有的JSON都将被JSON序列化。Net而不是内置的JavaScriptSerializer. Net。

重写控制器Json/JsonResult以返回Json。Net:

这是一个有效的治疗

很烦人,不是吗?

我的解决方案是改变我的WCF服务,让它以更可读(非微软)的格式返回DateTimes。请注意下面的“UpdateDateOriginal”,这是WCF的默认日期格式,以及我的“UpdateDate”,它被格式化为更易于阅读的格式。

enter image description here

以下是如何做到这一点:

更改WCF日期格式 .

希望这能有所帮助。

最简单的一个:

var milisegundos = parseInt(数据。replace("/Date(", "").replace(")/", ""));
Var newDate = newDate (milisegundos).toLocaleDateString("en-UE");

我发现这是更改服务器端的最简单的方法。

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

我遇到了一些JSON日期的问题,并决定通过在SQL中解决日期问题来摆脱这个问题。将日期格式更改为字符串格式

select flddate from tblName


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

通过使用fldDateStr,问题消失了,我仍然可以使用日期字段进行排序或其他目的。

0

在你的cshtml中,

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

在你的JS文件中,也许是app。JS,

在app.controller之外,添加下面的过滤器。

这里的“mydate”是用来解析日期的函数。这里的"app"是包含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;
};
});