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

return new JsonResult(myModel);

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

"\/Date(1239018869048)\/"

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


当前回答

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

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

方法1: 默认实现使用JsonScriptSerializer。如果查看文档,可以使用RegisterConverters方法添加自定义JavaScriptConverters。但是有一些问题:JavaScriptConverter序列化到一个字典,也就是它接受一个对象并序列化到一个Json字典。为了使对象序列化为字符串,它需要一点技巧,请参阅post。这个特殊的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

其他回答

请看这个帖子:

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

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

在查询中格式化日期。

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并返回它是不令人满意的-必须用返回新的MyJsonResult {Data = obj}替换所有返回Json(obj)的调用是一种痛苦。


所以我想,为什么不只是劫持JsonResult使用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));
            }
        }
    }
}

这可以应用于任何返回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。

对我来说有用的是创建一个包含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);
}

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

这很有用