16

This question appears to have been answered several times on here, but none of the solutions are working for me. I have an Apex function defined like so:

@RemoteAction
global static ActivityWrapper createActivity(Activity__c activity)

And when I call this Javascript function:

Controller.createActivity(
    {ForWeek__c: "2014-04-21T08:00:00.000Z",
     Notes__c: "sdfsdf",
     Type__c: "Referral",
     Id: null,
     sObjectType: "Activity__c"}, callback);

I always get back this error message:

Visualforce Remoting Exception: Unexpected type for Controller.createActivity(Activity__c)

As far as I know this is all that is required, but I can't get past this.

10
  • Is it possible that activity is a reserved keyword? – greenstork Apr 21 '14 at 20:37
  • Can you confirm that you have no namespace defined in the org? – Keith C Apr 21 '14 at 21:03
  • @greenstork even if Activity were a reserved keyword, Activity__c would not be, correct? – Matt Baker Apr 21 '14 at 23:05
  • @KeithC I just confirmed that there is no namespace defined in my org. I'm just using a simple Developer instance at this point anyway. – Matt Baker Apr 21 '14 at 23:09
  • 2
    I tried: {!$RemoteAction.remote.createAccount}({ Id: null, Name: "Nobody", Industry: "Technology" }, function(d,e) { console.log(d.Id); }); in my dev org. It works. The sObjectType param is only required if you're using generics (SObject). Try not including the type. Also check the case sensitivity of those field names. – sfdcfox Apr 22 '14 at 2:05
7

EDIT 2:

I've also just noticed that you're passing a formatted date string, with Visualforce Remoting you need to pass your Date values as Unix timestamp values (in milliseconds, rather than seconds).

So for your example you need to pass 1398067200000.


EDIT:

In fact, I've just noticed that your JSON is poorly formed, you are missing a few commas (after the ForWeek__c, Notes__c and Type__c values). Try this:

Controller.createActivity
(
    {
        ForWeek__c: "1398067200000",
        Notes__c: "sdfsdf",
        Type__c: "Referral",
        Id: null
    }, 
    callback
);

I've tried replicating your issue and I've not managed to end up with exactly the same error message, however I have stripped it down to the simplest example.

The only solution I can offer you is to try and pull your controller and page back to it's simplest possible version (i.e. something that looks like the below) and build from there, because other than setting the sObjectType field I can't see anything wrong with what you're doing.

RemotingSObject__c

  • Field__c (String)

RemotingSObjectController

public class RemotingSObjectController
{
    @RemoteAction
    public static RemotingSObject__c getRemoteObject() 
    {
        RemotingSObject__c anObject = new RemotingSObject__c(Field__c = 'Value');
        return anObject;
    }

    @RemoteAction
    public static String setRemoteObject(RemotingSObject__c anObject) 
    {
        return anObject.Field__c;
    }
}

RemoteObjectPage

<apex:page controller="RemotingSObjectController">
    <script type="text/javascript">
        var sobject;

        function getRemoteObject() 
        {
            RemotingSObjectController.getRemoteObject
            ( 
                function(result, event)
                {
                    if (event.status) 
                    {
                        console.log(result);
                    } 
                    else if (event.type === 'exception') 
                    {
                        console.log(event.message);
                    } 
                    else 
                    {
                        console.log(event.message);
                    }
                }
            );
        }

        function setRemoteObject() 
        {
            RemotingSObjectController.setRemoteObject
            (
                {Field__c: 'Success!'},
                function(result, event)
                {
                    if (event.status) 
                    {
                        console.log(result);
                    } 
                    else if (event.type === 'exception') 
                    {
                        console.log(event.message);
                    } 
                    else 
                    {
                        console.log(event.message);
                    }
                }
            );
        }
    </script>

    <input type="button" onclick="getRemoteObject();" value="get"/>
    <input type="button" onclick="setRemoteObject();" value="set"/>

</apex:page>

Result

Clicking the get button results in a JSON representation of my RemotingSObject__c in my Javascript log with 'Value' in Field__c, clicking the set button results in 'Success!' being printed to my Javascript log.

2
  • The example JSON I provided was missing commas, but that was a result of me copying out of the console. The actual code does the right thing in that respect. I wonder if my date format doesn't deserialize on the controller side... – Matt Baker Apr 22 '14 at 10:59
  • @MattBaker Not sure how I missed that first time through, I've updated my answer. – Alex Tennant Apr 22 '14 at 11:24
2

While Alex's response hits the root cause of my original question, I'm glad this confusion arose. Do not do what I did accessing the window scoped Controller helper unless you want to reinvent the wheel. If you need to use Javascript Remoting for non-CRUD purposes use the "official" method raised by @sfdcfox

{!$RemoteAction.remote.createAccount}({ Id: null, Name: "Nobody", Industry: "Technology" }, function(d,e) { console.log(d.Id); });

If Remoting is only a means to get at CRUD (like my case) I recommend using the RemoteTK component + controller available here:

https://github.com/developerforce/Force.com-JavaScript-REST-Toolkit/blob/master/RemoteTK.component

As a huge plus, this also allows you infinite CRUD without worrying about API limits. It should really not be hidden alongside the forcetk library though. I completely overlooked it when I originally pulled in ForceTK.

3
  • I'm curious as to why you suggest not using the scoped controller helper, as it and Visualforce.remoting.Manager.invokeAction are the documented way of invoking remoting calls rather than the method proposed by sfdcfox. I'd also recommend the AJAX Toolkit as an alternative if you're planning on doing purely CRUD operations as it doesn't require you to use a specific controller. – Alex Tennant Apr 22 '14 at 14:16
  • 1
    @AlexTennant good to know. I just recommended against it since using the global helper forces you to manually handle things like date values on the way out of your application. If you can avoid it, do so. As far as the AJAX toolkit, I'm not doing much by way of true Visualforce pages, but instead am using Ember.js and Ember Data. I wrote an Ember Data adapter around forcetk.js and remotetk.js, which is what lead to this question. Hopefully I can get the adapter stable enough to release soon, since Ember lacks an official Mobile Toolkit for SalesForce. – Matt Baker Apr 22 '14 at 14:22
  • That all makes sense. Good to know. – Alex Tennant Apr 22 '14 at 14:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.