Skip to main content
2 of 4
Added detail about it working with an sObject.
Mark Pond
  • 23.1k
  • 2
  • 60
  • 104

What is the correct way to send DateTime member types in the payload to RemoteActions?

I have seen quite a few questions and answers regarding the conversion and display of a JSON serialized DateTime field in JavaScript and the effects of UTC on that data related to the user's locale but I have yet to be able to find a solution to the issue I'm facing here.

I am using @RemoteAction methods to expose a custom Apex Type to the page. When performing the retrieve operation, the DateTime members on the class are serialized into the unix epoch format.

{
    name: "Item Name",
    theDate: 1440797362525
}

However, when performing a commit back to the controller with this exact same data, the unix epoch format is not able to be deserialized back into the concrete type and it throws an exception.

Visualforce Remoting Exception: Unable to convert date '1440797362525' to Apex type Datetime.

What is the correct way to implement this very simple pattern? Am I just doing it wrong? This seems like "JS Remoting: 101" and it shocks me that it does not work.

Update: apparently this is only an issue with a concrete type on my own class. Tried the same code with the Contact sObject, no exception thrown.

Controller

public with sharing class DateTimeSerializationController {
    
    public class MyItem {
        public String name      { get; set; }
        public DateTime theDate { get; set; }
    }
    
    @RemoteAction
    public static MyItem fetchTheItem() {
        MyItem item = new MyItem();
        item.name = 'Item Name';
        item.theDate = DateTime.now();
        return item;
    }
    
    @RemoteAction
    public static MyItem storeTheItem(MyItem item) {
        // DML or something similar could happen here
        system.debug(item);
        
        return item;
    }
    
    @RemoteAction
    public static Contact fetchTheContact() {
        Contact item = new Contact();
        item.FirstName = 'Joe';
        item.LastName = 'Bob';
        item.My_Date__c = DateTime.now();
        return item;
    }
    
    @RemoteAction
    public static Contact storeTheContact(Contact item) {
        // DML or something similar could happen here
        system.debug(item);
        
        return item;
    }
}

VF Page

<apex:page controller="DateTimeSerializationController">
    <script>
        window.myApp = window.myApp || {};
        
        window.myApp.fetchItem = function() {
        
            Visualforce.remoting.Manager.invokeAction(
                'DateTimeSerializationController.fetchTheItem',
                function(result, event){
                    if (event.status) {
                        console.log(result);
                        myApp.myItem = result;    
                    } else {
                        console.log(event.message);
                    }
                }, 
                {escape: true}
            );
        
        }
        
        window.myApp.storeItem = function() {
            Visualforce.remoting.Manager.invokeAction(
                'DateTimeSerializationController.storeTheItem',
                myApp.myItem,
                function(result, event){
                    if (event.status) {
                        console.log(result);
                    } else {
                        console.log(event.message);
                    }
                }, 
                {escape: true}
            );
        }
        
        window.myApp.fetchContact = function() {
        
            Visualforce.remoting.Manager.invokeAction(
                'DateTimeSerializationController.fetchTheContact',
                function(result, event){
                    if (event.status) {
                        console.log(result);
                        myApp.myContact = result;    
                    } else {
                        console.log(event.message);
                    }
                }, 
                {escape: true}
            );
        
        }
        
        window.myApp.storeContact = function() {
            Visualforce.remoting.Manager.invokeAction(
                'DateTimeSerializationController.storeTheContact',
                myApp.myContact,
                function(result, event){
                    if (event.status) {
                        console.log(result);
                    } else {
                        console.log(event.message);
                    }
                }, 
                {escape: true}
            );
        }
    </script>

    <p>Open the browser console and then click the buttons.</p>

    <button onclick="myApp.fetchItem();">Fetch Item</button>
    <button onclick="myApp.storeItem();">Store Item</button>

    <button onclick="myApp.fetchContact();">Fetch Contact</button>
    <button onclick="myApp.storeContact();">Store Contact</button>
</apex:page>
Mark Pond
  • 23.1k
  • 2
  • 60
  • 104