简体   繁体   English

使用Asp.Net MVC和KnockoutJS处理日期

[英]Handling dates with Asp.Net MVC and KnockoutJS

I recently started working with KnockoutJs and quickly realized using the default Json(myModelWithADate) resulted in the default json encoding of \\/Date(-62135578800000)\\/ With a bit of research I located four potential ways to handle the display of my dates in dom elements. 我最近开始使用KnockoutJs并很快意识到使用默认的Json(myModelWithADate)导致默认的json编码为\\/Date(-62135578800000)\\/通过一些研究我找到了四种可能的方法来处理我的日期显示dom元素。

1) Create a binding that handles the conversion from the Json date to the format you desire 1)创建一个绑定,处理从Json日期到您想要的格式的转换

ko.bindingHandlers.date = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var jsonDate = valueAccessor();
        var value = new Date(parseInt(jsonDate.substr(6)));
        var ret = value.getMonth() + 1 + "/" + value.getDate() + "/" + value.getFullYear();
        element.innerHTML = ret;
    },
    update: function(element, valueAccessor, allBindingsAccessor, viewModel) {

    }
};

Usage 用法

<td data-bind="date: DueDate">
</td>

2) Return “strings” from your Controller 2)从控制器返回“字符串”

return Json(new {MyDate = DateTime.Now.ToShortDateString()});

3) Use the JSON.NET to specify a Date Time format seen over at james.newtonking.com 3)使用JSON.NET指定在james.newtonking.com上看到的日期时间格式

Example

string isoJson = JsonConvert.SerializeObject(entry, new IsoDateTimeConverter());
// {"Details":"Application started.","LogDate":"2009-02-15T00:00:00Z"}

4) use JSON.parse to handle your dates as seen in this stackoverflow answer. 4)使用JSON.parse来处理您的日期,如此stackoverflow答案中所示。

JSON.parse(jsonText, function(key, value) {
    // Check for the /Date(x)/ pattern
    var match = /\/Date\((\d+)\)\//.exec(value);
    if (match) {
        var date = new Date(+match[1]); // Convert the ticks to a Date object
        return humanReadable(date); // Format the date how you want it
    }

    // Not a date, so return the original value
    return value;
});

They all appear to work, but I am still struggling with which one feels “right”. 他们似乎都工作,但我仍然在努力与哪一个感觉“正确”。 Right now my gut is going with a mix with the binding and returning strings. 现在,我的内心正在与绑定和返回的字符串混合。 As I could see myself extending the binding to handle input with jQuery UI datepicker controls. 正如我可以看到自己扩展绑定以使用jQuery UI datepicker控件处理输入。

Is there an accepted practice when handling displaying dates or other types such as currency? 处理显示日期或其他类型(如货币)时是否有可接受的做法? Is there another option I am missing that solves this problem? 我还缺少另一个可以解决这个问题的选择吗?

Personally I think the JSON.NET solution is the best simply because it imposes less on the client. 我个人认为JSON.NET解决方案是最好的,因为它对客户端的影响较小。 All the other solutions require additional client parsing or additional client code. 所有其他解决方案都需要额外的客户端解析或其他客户端代码。

I have switched over to using JSON.NET for all of my ASP .NET code that uses JSON because its a much more customizable library. 我已经切换到使用JSON.NET来使用所有使用JSON的ASP .NET代码,因为它是一个更可定制的库。

For example I have had to implement JSON data in MVC that conformed to Google's Chart API (used in combination with Knockout for paging, etc.) and the default JavascriptSerializer simply cannot do it. 例如,我必须在MVC中实现符合Google的Chart API (与Knockout结合用于分页等)的JSON数据,而默认的JavascriptSerializer根本无法做到。

In addition with JSON.NET you can customize it to actually spit out full Knockout view models so you don't even need to employ the mapping plugin. 除了JSON.NET,你可以自定义它以实际吐出完整的Knockout视图模型,这样你甚至不需要使用映射插件。

I wrote a sample library called FluentJson.NET which lets you do things in Razor like: 我写了一个名为FluentJson.NET的示例库,它允许您在Razor中执行以下操作:

var viewModel = @JsonObject.Create()
    .AddProperty("name", "value")
    .AddObservable("knockoutProperty", 123)

And get: 得到:

var viewModel = {"name":"value","knockoutProperty":ko.observable(123)}

So you can get a Knockout view model without any client side hoops to jump through. 因此,您可以获得一个Knockout视图模型,而无需任何客户端箍跳过。

You could easily extend something like that to handle date values however you would prefer. 你可以轻松地扩展这样的东西来处理日期值,但你更喜欢。

I would suggest a middle man approach through ko.mapping.fromJS( data, mapping ) this would allow you to customize even with a user defined object. 我建议通过ko.mapping.fromJS( data, mapping )的中间人方法ko.mapping.fromJS( data, mapping )这将允许您甚至使用用户定义的对象进行自定义。

var $data = { _ID : '1', _Created : someDate };  
var $mapping = {
    '_Created' : {
       update: function (options) {
           return convertdata( options.data );
       }
    }
}
var viewDataModel = ko.mapping( data, mapping );  
ko.applyBindings( viewDataModel );

mapping parameter allows you handle changes easily and can easily be leveraged with arrays also. mapping参数允许您轻松处理更改,也可以轻松地使用数组。

The better way to handle dates in knockoutjs is to use moment library and handle dates like boss. 在knockoutjs中处理日期的更好方法是使用时刻库​​并处理像boss这样的日期。 You can easily deal with dates like /Date(-62135578800000)/. 您可以轻松处理/ Date(-62135578800000)/等日期。 No need to bother of how your serialize date in controller. 无需担心控制器中序列化日期的方式。

Approach 1 : Directly in view: 方法1:直接在视图中:

Lets say your knockout model gets such date in a observable called sentDate and now it has value /Date(-62135578800000)/. 让我们说你的淘汰模型在一个名为sentDate的可观察对象中得到这样的日期,现在它有值/日期(-62135578800000)/。 To bind it in view you can do : 要在视图中绑定它,您可以:

<p><label>Date</label>: <span data-bind="moment(sentDate).format('MM/DD/YYYY')"></span></p>

Approach 2 : In custom binding 方法2:在自定义绑定中

ko.bindingHandlers.date = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var jsonDate = valueAccessor();     
        var ret = moment(jsonDate).format('MM/DD/YYYY');
        element.innerHTML = ret;
    },
    update: function(element, valueAccessor, allBindingsAccessor, viewModel) {

    }
};

Usage same as you had said : 用法和你说的一样:

<td data-bind="date: sentDate">
</td>

momentjs supports lots of date time formats and utility functions on dates. momentjs支持日期上的大量日期时间格式和实用程序功能。

I'm using the following code to generate short date strings. 我正在使用以下代码生成短日期字符串。 I use it for my date strings and jQueryUi Date Picker. 我将它用于我的日期字符串和jQueryUi日期选择器。

class T
    {
        public DateTime d { get; set; }
    }

static void Main(string[] args)
    {
        var k = new T { d = DateTime.Now };

        var formatter = new IsoDateTimeConverter();
        formatter.DateTimeFormat = "d";
        var s = JsonConvert.SerializeObject(k, formatter);
    }

This generates the following JSON 这会生成以下JSON

"{"d":"4/21/2012"}"

This results clean JavaScript code for me. 这样可以为我提供干净的JavaScript代码。

Just came up on this question because we also started using knockout.js on our MVC3 app. 刚刚提出这个问题,因为我们也开始在我们的MVC3应用程序上使用knockout.js。 Since we already have jQuery datepicker and we need to format dates differently by locale (portal has different languages and different formats are presented per language), so maybe this mashup of technological requirements arise somewhere else and will be useful: 由于我们已经有了jQuery datepicker,我们需要通过locale以不同的方式格式化日期(门户网站有不同的语言,每种语言都有不同的格式),所以也许这个技术要求的混搭会出现在其他地方,并且会很有用:

var jsDateFormat = "@CultureHelper.JsDateFormat"; // can be something like yy-mm-dd

//...

 ko.bindingHandlers.date = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var value = valueAccessor();
        if (value != null) {
            var jsonDate = new Date(parseInt(valueAccessor().substr(6)));
            element.innerHTML = jQuery.datepicker.formatDate(jsDateFormat, jsonDate);
        }
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
    }
};

And in the view then for example: 然后在视图中,例如:

<p><label>Date</label>: <span data-bind="date: SentDate"></span></p>

A cleaner alternative to @photo_tom's answer is to decorate the property with the IsoDateTimeConverter via the JsonConverter attribute, like so: @ photo_tom答案的一个更清晰的替代方法是通过JsonConverter属性使用IsoDateTimeConverter来装饰属性,如下所示:

public class MyClass
{
    [JsonConverter(typeof(IsoDateTimeConverter))]
    public DateTime Timestamp { get; set; }
}

I loved Andres Toro's answer except that in my case, input fields are expecting formatted strings. 我喜欢Andres Toro的答案,但在我的情况下,输入字段需要格式化的字符串。 So I am using JQuery to format my dates according to my favorite format provided by my helper @Html.ConvertDateFormat() Hope this helps someone day. 因此,我使用JQuery根据我的帮助器@Html.ConvertDateFormat()提供的格式来格式化我的日期。希望这有助于某一天。

var mapping = {
    'ActualDateTime': {
        update: function (options) {
            var d = /\/Date\((\d*)\)\//.exec(options.data);
            return (d) ? $.datepicker.formatDate('@Html.ConvertDateFormat()', new Date(+d[1])) : value;
            //return "5/10/2017";
        }
    }
};
var paymentModel = ko.mapping.fromJS(modelJSON, mapping);

I always use a data converter instead of sending data directly to server to fix any client encoding or parsing issues, without the need to use additional tools. 我总是使用数据转换器而不是直接向服务器发送数据来修复任何客户端编码或解析问题,而无需使用其他工具。

In the Knockout JS view model file, I add the following code before the view model setup, which intercept selected proeprries of the view model and use moment.js to take care of date convertions: 在Knockout JS视图模型文件中,我在视图模型设置之前添加以下代码,它拦截视图模型的选定proeprries并使用moment.js来处理日期转换:

// converting data before sending to controller
var dataConverter = function (key, value) {  
    if (key === 'InvoiceDate') {
        return moment(value).format("YYYY MMMM DD");
    }

    return value;
};

Then I use the dataConverter instead of data in the ajax save method within the view model: 然后我使用dataConverter而不是视图模型中的ajax save方法中的data

// Example view model for sales invoice
SalesInvoiceViewModel = function (data) {
    var self = this;
    ko.mapping.fromJS(data, {}, self);
    self.SaveInvoice = function () {
        $.ajax({
            url: '/SalesInvoices/SaveInvoice/',
            type: 'POST',
            data: ko.toJSON(self, **dataConverter**),
            contentType: 'application/json',
            success: function (data) {
                if (data.invoiceViewModel !== null) {
                    ko.mapping.fromJS(data.invoiceViewModel, {}, self);
                }
                if (data.redirectToLocation !== null) {
                    window.location = data.redirectToLocation;
                }
            },
            error: function (xhr, ajaxOptions, thrownError) {
                // report error to user
            }
        });
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM