Формат даты ASP.NET MVC JsonResult

У меня есть действие контроллера, которое эффективно просто возвращает JsonResult моей модели. Итак, в моем методе у меня есть что-то вроде следующего:

return new JsonResult(myModel);

Это хорошо работает, за исключением одной проблемы. В модели есть свойство date, и это, по-видимому, возвращается в результате Json так:

"\/Date(1239018869048)\/"

Как я должен иметь дело с датами, чтобы они были возвращены в требуемом формате? Или как мне обрабатывать этот формат выше в script?

Ответы

Ответ 1

Просто чтобы расширить ответ 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. Если используется число, вместо этого значение обычно принято считать числом миллисекунды в универсальном скоординированном Время (UTC) с эпохи, где эпоха определенная как полночь 1 января 1970 г. (УНИВЕРСАЛЬНОЕ ГЛОБАЛЬНОЕ ВРЕМЯ). Опять же, это просто конвенция, а не часть JSON стандарт. Если вы обмениваетесь данными с другим приложением вы будете необходимо проверить свою документацию, чтобы увидеть как он кодирует значения даты и времени в литературе JSON. Например, Microsoft ASP.NET AJAX не использует ни описанных конвенций. Скорее, он кодирует значения .NET DateTime как JSON, где содержимое строка/Дата (тики)/и где тики представляют миллисекунды с тех пор эпоха (UTC). Итак, 29 ноября 1989 года, 4:55:30, в UTC кодируется как "\/Дата (628318530718) \/".

Решение состоит в том, чтобы просто проанализировать его:

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

Однако я слышал, что есть параметр где-то, чтобы заставить сериализатор выводить объекты DateTime с синтаксисом new Date(xxx). Я попытаюсь выкопать это.


Второй параметр JSON.parse() принимает функцию reviver, где предписывает, как значение, изначально созданное, перед возвратом.

Вот пример даты:

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

Ответ 2

Здесь мое решение в Javascript - очень похоже на JPot, но короче (и, возможно, немного быстрее):

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

"value.substr(6)" вынимает функцию "/Date (" part ", а функция parseInt игнорирует символы без номера, которые встречаются в конце.

EDIT: Я намеренно упустил radix (второй аргумент parseInt); см. мой комментарий ниже. Кроме того, обратите внимание, что даты ISO-8601 предпочтительнее этого старого формата, поэтому этот формат обычно не должен использоваться для новой разработки. См. Превосходную библиотеку Json.NET для отличной альтернативы, которая сериализует даты с использованием формата ISO-8601.

Для ISO-8601 отформатированных дат JSON просто передайте строку в конструктор Date:

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

Ответ 3

Существует довольно много ответов для обработки клиентской части, но вы можете изменить выходную серверную сторону, если хотите.

Есть несколько способов приблизиться к этому, я начну с основ. Вам придется подклассифицировать класс JsonResult и переопределить метод ExecuteResult. Оттуда вы можете использовать несколько разных подходов для изменения сериализации.

Подход 1: Реализация по умолчанию использует JsonScriptSerializer. Если вы посмотрите на документацию, вы можете использовать метод RegisterConverters для добавления пользовательских JavaScriptConverters. Есть несколько проблем с этим: JavaScriptConverter сериализуется в словаре, то есть он берет объект и сериализуется в Json-словаре. Чтобы сделать сериализацию объекта строкой, он требует немного хакера, см. post. Этот конкретный хак также удалит строку.

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

Подход 2 (рекомендуется): Второй подход - начать с переопределенного JsonResult и пойти с другим сериализатором Json, в моем случае Json.NET сериализатору. Это не требует взлома подхода 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(); } };
}

Дополнительные кредиты: Джеймс Ньютон-Кинг

Ответ 5

Использование jQuery для автоматического преобразования дат с помощью $.parseJSON

Примечание: этот ответ предоставляет расширение jQuery, которое добавляет автоматическую поддержку формата даты в формате ISO и .net.

Поскольку вы используете Asp.net MVC, я подозреваю, что вы используете jQuery на стороне клиента. Я предлагаю вам прочитать этот пост в блоге, в котором есть код, как использовать $.parseJSON для автоматического преобразования дат для вас.

Код поддерживает даты форматирования Asp.net, такие как те, которые вы упомянули, а также даты в формате ISO. Все даты будут автоматически отформатированы для вас, используя $.parseJSON().

Ответ 6

Я обнаружил, что создание нового JsonResult и возвращение неудовлетворительное - замена всех вызовов на return Json(obj) на return new MyJsonResult { Data = 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.Net:

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

Ответ 7

Ajax-связь между клиентом и сервером часто включает данные в формате JSON. В то время как JSON хорошо работает для строк, чисел и логических значений, он может создавать определенные трудности для дат из-за того, как они преобразуются в ASP.NET. Поскольку у них нет специального представления для дат, они сериализуются как простые строки. В качестве решения механизм сериализации по умолчанию ASP.NET Web Forms и MVC сериализует даты в специальной форме -/Date (ticks)/- где тики - это количество миллисекунд с 1 января 1970 года.

Эта проблема может быть решена двумя способами:

клиентская сторона

Преобразовать полученную строку даты в число и создать объект даты с использованием конструктора класса даты с параметрами ticks как.

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

}

серверная сторона

Предыдущее решение использует клиентскую сторону script для преобразования даты в объект JavaScript Date. Вы также можете использовать код на стороне сервера, который сериализует экземпляры .NET DateTime в выбранном вами формате. Для выполнения этой задачи вам необходимо создать свой собственный ActionResult и затем сериализовать данные так, как вы хотите.

ссылка: http://www.developer.com/net/dealing-with-json-dates-in-asp.net-mvc.html

Ответ 8

У меня была такая же проблема, и вместо того, чтобы возвращать фактическое значение даты, я просто использовал ToString ( "dd MMM yyyy" ). Затем в моем javascript я использовал новую Date (datevalue), где datevalue может быть "01 января 2009".

Ответ 9

Смотрите эту тему:

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

По сути, хотя формат Date() является допустимым javascript, он НЕ является действительным JSON (есть разница). Если вы хотите использовать старый формат, вам, вероятно, придется создать фасад и трансформировать значение самостоятельно или найти способ получить сериализатор для вашего типа в JsonResult и использовать его в настраиваемом формате для дат.

Ответ 10

Не самый элегантный способ, но это сработало для меня:

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

Ответ 11

Я работаю над решением этой проблемы, так как ни один из вышеперечисленных ответов мне не помог. Я работаю с календарем недели jquery и нуждаюсь в моих датах, чтобы иметь информацию о часовом поясе на сервере и локально на странице. После довольно много рывка вокруг, я выяснил решение, которое может помочь другим.

Я использую asp.net 3.5, vs 2008, asp.net MVC 2 и календарь недели jquery,

Во-первых, я использую библиотеку, написанную Стивеном Левитаном, которая помогает справляться с датами на стороне клиента, Датой регистрации Стивена Левитана. Формат isoUtcDateTime идеально подходит для того, что мне нужно. В моем вызове jQuery AJAX я использую функцию формата, предоставляемую библиотекой с форматом isoUtcDateTime, и когда вызов ajax вызывает мой метод действия, datetime Kind установлен в локальный и отражает время сервера.

Когда я отправляю даты на свою страницу через AJAX, я отправляю их в виде текстовых строк, форматируя даты, используя "ddd, dd MMM yyyy HH": 'mm': 'ss' GMT'zzzz. Этот формат легко конвертируется с помощью

var myDate = new Date(myReceivedDate);

Вот мое полное решение минус источник Стива Левитана, который вы можете скачать:

Контроллер:

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>

Надеюсь, этот быстрый пример поможет другим в той же ситуации, в которой я был. В настоящее время он отлично работает с Microsoft JSON Serialization и сохраняет мои даты правильными во времени.

Ответ 12

Лучший способ обработки дат в knockoutjs - использовать библиотеку времени и обрабатывать даты, такие как босс. Вы можете легко иметь дело с датами типа /Date (-62135578800000)/. Не нужно беспокоиться о том, как ваша дата сериализации в контроллере.

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

используйте его как

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

momentjs поддерживает множество дат и форматов функций в датах.

Ответ 13

Отформатируйте дату в запросе.

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

Единственная проблема с этим решением заключается в том, что вы не получите никаких результатов, если ANY из значений даты равно null. Чтобы обойти это, вы можете либо поставить условные операторы в свой запрос, прежде чем вы выбираете дату, которая игнорирует дату null, или вы можете настроить запрос для получения всех результатов, а затем пропустить всю эту информацию с помощью цикла foreach и присвоить значение ко всем датам, которые являются нулевыми до того, как вы сделаете свой новый SELECT.

Пример обоих:

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.

Ответ 14

Вы можете использовать этот метод:

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

Ответ 15

добавить jquery ui плагин на вашей странице.

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

Ответ 16

Он возвращает формат даты сервера. Вам нужно определить свою собственную функцию.

function jsonDateFormat(jsonDate) {

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

};

Ответ 17

Вот код JavaScript, который я написал, который устанавливает значение <input type="date"> из даты, переданной из 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);
    }
};

Вы вызываете эту функцию следующим образом:

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

Где CommissionStartDate - дата JSON, переданная MVC.

Ответ 18

Не зря, но есть другой способ. Сначала создайте запрос LINQ. Затем создайте запрос результата Enumerated и примените любой тип форматирования для вас.

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

Я должен сказать, что дополнительный шаг раздражает, но он работает хорошо.

Ответ 19

Что сработало для меня, так это создать модель представления, содержащую свойство date в виде строки. Присвоение свойства DateTime из модели домена и вызов .ToString() в свойстве date при присвоении значения модели viewmodel.

Результат JSON из метода действия MVC вернет дату в формате, совместимом с представлением.

Просмотреть модель

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

Ответ 20

Переопределите контроллеры Json/JsonResult для возврата JSON.Net:

Это работает.

Ответ 21

Раздражает, не так ли?

Мое решение состояло в том, чтобы изменить мою службу WCF, чтобы вернуть DateTimes в более читаемый (не Microsoft) формат. Обратите внимание: "UpdateDateOriginal", который представляет собой формат дат даты по умолчанию для WCF, и мой "UpdateDate", который отформатирован на что-то более читаемое.

введите описание изображения здесь

Вот как это сделать:

Изменение формата даты WCF

Надеюсь, что это поможет.

Ответ 22

eval (JSON.stringify(object).replace(//Date ((\ d+))//gi, function (a, b, c) {return new Date (parseInt (b))}))

Ответ 23

Самый простой:

var milisegundos = parseInt (data.replace("/Date (", "").replace(")/", ""));
Var newDate = новая дата (milisegundos). toLocaleDateString ("en-UE");