3
votes

I have a knockout/mvc3 application. I am passing the date back to a controller.

controller

public ActionResult PackageUpdate(Package updatePackage){
\\do some stuff but dates are set to zero?
}

view model and save method

var Package = function (data) {
    self = this;
    self = ko.mapping.fromJS(data);
    self.save = function(){
        $.ajax({
            url: '/MediaSchedule/PackageUpdate', 
            data:ko.toJSON({ updatePackage: self })
        }).success(function (results) {
            console.log(results);
        }).error(function (er) { 
            console.error('Ah damn you broke it.')
            console.log(er);
        });
    }
    return self;
}

Json Being passed.

{"updatePackage":{"Id":"82e3bc7e-27b8-49c2-b1fa-1ee2ebffbe66","Name":"28a38","SecondaryName":"è€å­æˆ‘è¦é’±","IsLocked":true},"DateCreated":"/Date(1357650000000+1100)/","DateStart":"/Date(1365080400000+1100)/","DateEnd":"/Date(1365516000000+1000)/"}

ID, name and other properties are coming through but the date is being reset to {1/1/0001 12:00:00 AM}. My assumption is because it is not being deserialised it is setting a min date. Question: How do I correctly deserialise my date.

3
This answer by Darin should help. stackoverflow.com/a/3940464/243694Pieter Germishuys
is there a way to do this without posting each property of the object. I have removed some properties but there are about 15. There are also 2 arrays each containing objects with start/end/created dates.Kieran
that suggestion also would mean unpacking the knockout object manually. something i would like to avoid.Kieran

3 Answers

2
votes

I think the problem lies in how you obtaining those dates to begin with. You show an example using MS date format such as /Date(1357650000000+1100)/ which is not standardized and is slowly being deprecated in favor of ISO8601, which looks like 2013-01-08T13:00:00.000+11:00.

Indeed, when you JSON.stringify a javascript Date object, it uses the ISO8601 format. This also happens with ko.mapping.toJSON.

There are several solutions to this problem, both client side and server side. This post describes the problem in detail and has some great answers that may help you.

IMHO, the best solution is have your MVC controller emit and consume ISO8601 rather than the old Microsoft date format. The easiest way to do that is by using the Json.Net library which now has ISO8601 as the default so you don't even need to customize it. On the client side, you might also want to look at Moment.js - which makes it easy to parse and format ISO dates.

1
votes

I think it just the data type you push to you updatePackage object. Following is my code and run well, I use read the Date from jQuery Datepicker and use the format as 'dd MM, yy' (01 January 2013)

 var iEndInsuredDate = $('#dpkEndInsuredDate').val();
            var iEndPolicyDate = $('#dpkEndPolicyDate').val();

            $.ajax({
                url: '@Url.Action("DeleteClientMember", "ClientMember")',
                type: "POST",
                dataType: "json",
                data: { clientMemberID: id, endInsuredDate: iEndInsuredDate, endPolicyDate: iEndPolicyDate },
                success: function (result) {
                    ShowWaiting("Reloading...");
                    Search(1);
                }
            });

and my ActionResult

public ActionResult DeleteClientMember(int clientMemberID, DateTime? endInsuredDate, DateTime? endPolicyDate)
    {
        ClientMember model = clientMemberService.GetById(clientMemberID);

        //model.EndPolicyDate = endPolicyDate;
        model.EndInsuredDate = endInsuredDate;
        foreach (ClientMemberProduct item in model.ProductList)
        {
            item.EndDate = endInsuredDate;
        }
        model.IsActive = false;
        model.ActionStatus = ClientMemberActionStatus.PendingDelete.ToString();
        clientMemberService.CalculateInsFee(model);
        clientMemberService.Update(model);
        return null;
    }

Hope this help Regard

1
votes

Thanks to Matt Johnson I was able to change the way the dates were being sent to the browser. It was a relativly easy fix taken from Perishable Dave answer to a similar problem with ASP.NET MVC JsonResult Date Format

My JsonNetResult class now look like

public class JsonNetResult : ActionResult
{
    private const string _dateFormat = "yyyy-MM-dd hh:mm:ss";

    public Encoding ContentEncoding { get; set; }
    public string ContentType { get; set; }
    public object Data { get; set; }

    public JsonSerializerSettings SerializerSettings { get; set; }
    public Formatting Formatting { get; set; }

    public JsonNetResult()
    {
        SerializerSettings = new JsonSerializerSettings();
        Formatting = Formatting.Indented;
        SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        HttpResponseBase response = context.HttpContext.Response;

        response.ContentType = !string.IsNullOrEmpty(ContentType)
          ? ContentType
          : "application/json";

        if (ContentEncoding != null)
            response.ContentEncoding = ContentEncoding;

        if (Data != null)
        {
            var isoConvert = new IsoDateTimeConverter();
            isoConvert.DateTimeFormat = _dateFormat;

            JsonTextWriter writer = new JsonTextWriter(response.Output) { Formatting = Formatting };

            JsonSerializer serializer = JsonSerializer.Create(SerializerSettings);
            serializer.Converters.Add(isoConvert);

            serializer.Serialize(writer, Data);

            writer.Flush();
        }
    }
}

I have added the iso date converter to the serizer

in the controller you invoke it by:

public JsonNetResult YourAction(){
    //your logic here
    return JsonNetResult(/*your object here*/);
}

When I wrote this I did not know about Web API. It is worth a look as it will do a lot of the heavy lifting when it comes to serialization of your objects. Checkout Getting Started with ASP.NET Web API 2