+ Start a Discussion
Mike LeachMike Leach 

VF Page Using AJAX Toolkit Not Working When Deployed to Sites

The following code is working well in a VF page, but fails when deployed to Sites with error message {faultcode: 'UNKNOWN_EXCEPTION', faultstring: 'UNKNOWN_EXCEPTION: Site under construction'}.  

 

I'm guessing {!$Api.Session_ID} is not supported under the Sites Guest User?

 

I'm not using a controller. All AJAX methods call into static WebServices on a global class. 

 

<apex:page sidebar="false" showHeader="false">

<apex:includeScript value="/soap/ajax/17.0/connection.js"/>

<apex:includeScript value="/soap/ajax/17.0/apex.js"/>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>

<script type="text/javascript">

$(function() {

sforce.connection.sessionId = '{!$Api.Session_ID}';

$("#testLink").click( function(){

sforce.apex.execute("MyWebService", "GetSomething", {},

{

onSuccess : function(result, source) { //databind JSON result to DIV output },

onFailure : function(error){//handle failure}

});

});

}

</script>

<a href="#" id="testLink">Test Link</a>

<div id="output"></div> 

</apex:page>

 

Before it's suggested, I'm aware <apex:actionFunction> provides an async AJAX interface and I've tried this, but most UI controls today databind to JSON on callback. The actionFunction oncomplete attribute appears to only notify the page that rerendering has occurred, and doesn't actually provide access to the response payload for use in custom data binding (please correct me if I'm wrong and can achieve the same results using actionFunction).

  

 

Best Answer chosen by Admin (Salesforce Developers) 
Ron HessRon Hess

Yes, the guest user has a session id, but it's not valid for anything.

here is how to use ActionFucntion and databinding

 

 

first, assume you have some JS framework that wants to have a JSON reply

 

the JS on your app, calls  Action Function 

my call looks like this 

 

<!-- for loading -->
<apex:actionFunction action="{!loadData}" name="loadData"
rerender="loadPanel, updateMessage">
<apex:param name="aParam" assignTo="{!startTime}" value="" />
<apex:param name="bParam" assignTo="{!endTime}" value="" />
</apex:actionFunction>

 

 standard stuff, now in my controller i run a query using the start and end times

 

the controller then populates a string variable (with the query result) which i've called 'jsondata' 

this code is from the controller 

 

 

// pass data on new event details back in jsondata
public string jsondata { get; set; } {jsondata = '{}';}

// run a query with the startTime and endTime in mind
public void loadData() {

[blah, blah deleted... ]

jsondata = calgroup.listToJSON( cgl );
}

 

 

 normal stuff, when it's done the data is sitting in the controller and viewstate of the page.

 

then the trick...

my VF page has this block 

 

 

<apex:outputPanel id="loadPanel" layout="block" rendered="true">
<script>
evts = eval( '({!jsondata})' );
if ( ical != null ) {
ical.render(evts);
}
</script>
</apex:outputPanel>

 

 

So, the partial page refresh will re-draw this script panel, with data in jsondata that is fresh from the controller.

simple, clean and works.

hope this helps in your case.

 

PS: be sure to use something like this to avoid JS errors if you have lots of data to pass back

 -->  jsondata = String.escapeSingleQuotes( jsondata);

 


 
Message Edited by Ron Hess on 11-02-2009 01:26 PM

All Answers

Ron HessRon Hess

Yes, the guest user has a session id, but it's not valid for anything.

here is how to use ActionFucntion and databinding

 

 

first, assume you have some JS framework that wants to have a JSON reply

 

the JS on your app, calls  Action Function 

my call looks like this 

 

<!-- for loading -->
<apex:actionFunction action="{!loadData}" name="loadData"
rerender="loadPanel, updateMessage">
<apex:param name="aParam" assignTo="{!startTime}" value="" />
<apex:param name="bParam" assignTo="{!endTime}" value="" />
</apex:actionFunction>

 

 standard stuff, now in my controller i run a query using the start and end times

 

the controller then populates a string variable (with the query result) which i've called 'jsondata' 

this code is from the controller 

 

 

// pass data on new event details back in jsondata
public string jsondata { get; set; } {jsondata = '{}';}

// run a query with the startTime and endTime in mind
public void loadData() {

[blah, blah deleted... ]

jsondata = calgroup.listToJSON( cgl );
}

 

 

 normal stuff, when it's done the data is sitting in the controller and viewstate of the page.

 

then the trick...

my VF page has this block 

 

 

<apex:outputPanel id="loadPanel" layout="block" rendered="true">
<script>
evts = eval( '({!jsondata})' );
if ( ical != null ) {
ical.render(evts);
}
</script>
</apex:outputPanel>

 

 

So, the partial page refresh will re-draw this script panel, with data in jsondata that is fresh from the controller.

simple, clean and works.

hope this helps in your case.

 

PS: be sure to use something like this to avoid JS errors if you have lots of data to pass back

 -->  jsondata = String.escapeSingleQuotes( jsondata);

 


 
Message Edited by Ron Hess on 11-02-2009 01:26 PM
This was selected as the best answer
Mike LeachMike Leach

Cool. That did the trick! Required some global variables for handling state between action and callback, but otherwise works great.

 

Thx!