Please Don’t Screen Scrape Visualforce!

I watch for questions at StackOverflow with the ‘salesforce’ tag – this morning, I noticed one asking about how to retrieve a Visualforce page from server side code for the purpose of screen scraping it to extract data. There were a couple of good answers on how to achieve this, but the better answer is “Just don’t do it!” – there’s really no need. Here’s the answer I gave at StackOverflow:

Rendering the data into a Visualforce page, then screenscraping it seems a bit brittle, not to mention inefficient – there is a better way…

Define an Apex REST web service, then you can easily invoke that web service from your server side code, and still render it in Visualforce if you need to – you can call an Apex REST method like any other Apex method.

Here’s a sample REST web service. I’m just returning a Map<String,String> here, but you can return any primitive type, any sObject or a List or Map of primitives or sObjects (as long as the Map has String keys) – see the Apex REST Web Services docs

@RestResource(urlMapping='/MyResource/*')
global with sharing class MyRestResource { 
    @HttpGet
    global static Map<String,String> getResource() {
        Map<String,String> result = new Map<String,String>();

        result.put('key1', 'value1');
        result.put('key2', 'value2');

        return result;
    }
}

Here’s some PHP that calls it (I’ll assume you have an access token (aka session ID) and instance URL):

$url = "$instance_url/services/apexrest/MyResource";
$curl = curl_init($url);

curl_setopt($curl, CURLOPT_HEADER, false); 
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER,
  array("Authorization: OAuth $access_token",
    "Content-type: application/json"));

$json_response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);

if ( $status != 200 ) {
    die("Error: call to URL $url failed with status $status, ". 
      "response $json_response\n"); 
} 

$response = json_decode($json_response, true); 

echo "The service says ".$response['key1'].' '.$response['key2']."\n"; curl_close($curl);

And here’s a Visualforce page, if you want to show the same data

<apex:page controller="TestRestController"> 
  <p>Controller says {!result}</p> 
</apex:page>

The page controller:

public class TestRestController { 
    public String getResult() { 
        Map<String, String> result = MyRestResource.getResource(); 

        return result.get('key1') + ' ' + result.get('key2'); 
    } 
}

If you’re a StackOverflow user (and if you’re not, you should be!), please go vote my answer up so that best practice wins out!

Published
October 28, 2011
Topics:

Leave your comments...

Please Don’t Screen Scrape Visualforce!