The Force.com REST API lets you integration with Force.com applications using standard HTTP methods. This API provides a way to expose the data you have within your Force.com application to external applications – both mobile and non-mobile. A few useful bits of information related to these REST APIs:

  • Use standard HTTP verbs: GET, POST, PUT, PATCH, DELETE, and HEAD.
  • You can use either HTTP or HTTPS.
  • Use standard security to authenticate your REST calls via OAuth 2.0.
  • Serialize your data in either XML or JSON format.

Force.com provides this capability out-of-the-box (OOTB) for objects you create and supports standard CRUD (create, read, update, and delete) against your objects. While this is great, there are a few scenarios that are not supported OOTB in Force.com – complex data queries (i.e. joins) via the API, custom logic or rules, and anonymous access.

In this post I’ll show you how you can create REST APIs using Apex REST in order to anonymous access to your APIs.

Following is a detailed tutorial:

1. Start by creating a new Force.com developer account. Why create a new account? Well, why not? It provides a good sandbox for testing things out and you can have as many as you want. Note that the although the login you create looks like an email address it doesn’t have to be your email address – it’s simply a login. You can create a nonsensical login – i.e. anonymous@restcall.com – and just throw it away when you’re done.

2. Let’s create a custom object. Under App Setup click Schema Builder. Click the Elements tab and drag an Object into the schema canvas.

image

3. For the Label choose “Widget”, for the Plural Label choose “Widgets”, and for the Record Name choose “Name”. Click Save.

image

4. It’s time to create the Apex REST API. Close the Schema Builder and under App Setup expand Developer and click Apex Classes. Click New to create a new class.

5. Past the following code into Apex Class Editor:

@RestResource(urlMapping='/Widgets/*')
global class WidgetController {

    @HttpGet
    global static List<Widget__c> getWidgets() {
        List<Widget__c> widgets = [SELECT Name from Widget__c];
        return widgets;
    }

    @HttpPost 
    global static String createNewWidget(String Name) {
        Widget__c w = new Widget__c();
        w.Name = Name;
        insert w;

        return 'Done';
   }

    @HttpDelete
    global static String deleteWidgetById() {
        String Id = RestContext.request.params.get('Id');
        List<Widget__c> w = [ Select ID from Widget__c where Id= :Id];

        delete w;

        return 'Deleted Widget';
    }

    @HttpPut
    global static String updateWidget(String Id, String NewName) {
        Widget__c w = [ Select ID, Name from Widget__c where Id= :Id];

        w.Name = NewName;
        update w;

        return 'Widget Updated';
    }
}

6. To access these APIs we have to create a site and provide access to this Apex class. Force.com sites enable you to create public websites and applications. Under App Setup expand Develop and click Sites.

7. Choose a Force.com domain name. Ensure it is available, click the checkbox, then click Register My Force.com Domain.

image

8. Once your site is registered click the New button.

9. Give yourself a Site Label, Site Name, and choose an Active Site Home Page. Since no one will use this site as a website I’ve chosen FileNotFound. Click the Save button.

10. By default the site is not active. Click the Activate button or else you will not be able to access your APIs.

image

11. Next we have to grant anonymous access to our Apex REST API. Click the Public Access Settings button.

image

12. Scroll down the Custom Object Permissions and click the Edit button underneath the Widgets.

image

Scroll down again to Custom Object Permissions (yeah, I know …) and check all the boxes. Click Save.

image

13. Scroll down to Enabled Apex Class Access and click the Edit button. Select the WidgetController and click the Add button. Click Save.

image

14.Browse to http://www.hurl.it/. This is a great website for making HTTP requests and will let us test the GET, POST, PATCH, and DELETE.

15. Right now our object doesn’t have any data. Before we make a Get request let’s add some data. Enter https://wadeapitest-developer-edition.na15.force.com/services/apexrest/Widgets in the URL (note: the first part of this URL is from step 7 above). Change to POST (and if necessary click the set post body link. Add the following text into the body:

{"Name":"Widget1"}

Click + add header and enter “Content-Type” for the name and “application/json; charset=UTF-8” for the value. Click the Send button.

image

You should get a response like the following:

image

16. Change from POST to GET and click Send. You should get the following response:

image

Copy the Id value – we’ll use this in a moment.

17. Change from GET to PUT, enter the following information in the body, and click Send.

{"Id":"a00i0000001RdL4AAK","NewName":"Widget1a"}

You should get the following response:

image

If you quickly flip back to GET and click Send you’ll see that your record has been updated.

18. Finally, let’s delete the record. Change the URL to https://wadeapitest-developer-edition.na15.force.com/services/apexrest/Widgets?Id=a01i0000000Z4jzAAC (again, use your site name and the proper Id value), change from PUT (or GET) to DELETE, and click Send. Now the record is gone!

That’s it!

The beauty of this technique is that any platform or language that can communicate over this HTTP methods – i.e. GET, POST, PUT, and DELETE – can execute CRUD operations against your custom object without having to authenticate. Pretty cool!

Now, should you always allow for CRUD over an anonymous set of APIs? Probably not. Just because I’ve shown you how to do it doesn’t mean you should. However, I’m sure you can think of some scenarios when the aforementioned capabilities are useful.

I hope this helps!

Today I got the opportunity to attend a Salesforce.com “hack day” in San Francisco. Quite fun, and I learned a lot from Adam Seligman, Dave Carroll, Pat Patterson, and Akhilesh Gupta. This is a great team: extremely personable, clearly excited about their platform and the technology, and willing to pull up their sleeves and write some code. My kind of people.

During the hack day I acquired a few tips for getting started. Nothing earthshattering but useful nonetheless.

  1. Setup a developer account. It’s quick, easy, and free. You can get a lot of them.
  2. Don’t use your production account for development. This may sound trite but I can tell you from first-hand experience that you don’t want to start hacking in production. The Salesforce.com development lifecycle has process for deploying from one environment to another. Use it. Today I didn’t follow this advice and it cost me quite a bit of time. See tip #1 for getting a proper developer account.
  3. Simplify the password requirements for your developer account. First, under your name, choose Setup.image

    Then type “password” in the search box and click Password Policies.

    image

    Choose some less restrictive policies. It’s up to you – personally, I don’t want my developer account password expiring all the time. Note: I do not recommend you do this on your production account.

    image

  4. Change the default IP Restrictions. Again, for my developer account, I don’t want the platform continually challenging me if I log in from different places. After you browse to Setup search for Profile. Click on Profiles.image

    Scroll down until your see System Administrators and select it.

    image

    Scroll down to IP Address Ranges and click New. Enter default ranges 0.0.0.0 to 255.255.255.255 and click Save.

    image

That’s all for now. For those of you who are pro’s on the platform this is likely not new or exciting. I’m sure there are more tips I’ll learn over time and, when I do, I’ll try to update this list.

I hope this helps!

One of my goals this past year has been to get more hands-on with respects to real-world cloud applications. Working for Aditi has provided many opportunities to dig into some interesting cloud workloads. In addition to building all kinds of applications running in Windows Azure, I’ve learned a lot working with Ryan Dunn and Raghu Rajagopalan on building products (like Scheduler) that run in the cloud.

Coming from a Windows Azure focus at Microsoft my natural tendency has been to approach most problems with solutions in Windows Azure. It’s amazing how versatile Windows Azure is as a platform; with a little bit of elbow grease there are few problems you can’t solve. That said, what I’ve come to release is, regardless of any platforms merits, there are always cases when you need to leave your comfort zone. For me, this has manifested itself with customers that – for a great many reasons – look to either Amazon Web Services or SalesForce.com for solutions.

Don’t get me wrong. I’m still a huge fan of Windows Azure and incredibly excited by what the platform offers. (And not just because I spent five years of my life working on it!) Just look at the evolution Windows Azure has taken over the last year:

  • Introduced IaaS capabilities last year
  • Introduced Windows Azure Websites
  • Introduced Windows Azure Mobile Services
  • Introduced Media Services

… and so much more. There’s never been a better time to build on Windows Azure.

That said, it’s interesting to talk to CIOs and technology leaders at various companies. I’ve found a great many different mental models people have for the cloud. Generally speaking, it appears that when talking to a technical person the cloud is synonymous with AWS; when talking to a businessperson the cloud is synonymous with SalesForce.com. We all ignore these platforms at our own peril. The same can be said for folks focused entirely on AWS or SalesForce.com – you ignore Windows Azure at your own peril.

At the end of the day, no one platform ever has all the answers. If we’re honest with ourselves we have to admit that it’s both worthwhile and important to understand other platforms as well. The desire to learn and to branch out into new areas is natural; furthermore, and most importantly, the needs of customers comes first.

All of this is a way of saying that you’ll start to see me blog more about other cloud platforms – certainly AWS and SalesForce.com, but it’s possible I’ll go even beyond these two. There’s a lot to learn from platforms like Heroku, Google Cloud, and others.

None of this is surprising or revolutionary. Consequently, you may ask yourself, why a long blog post? Well, primarily it’s because I don’t want to give the impression that I’ve given up on Windows Azure. In fact, I’m more excited about the future of Windows Azure than ever before. There’s a lot of opportunity just around the corner.

So … to the cloud(s)!

Lately I’ve been attempting to try out a number of different techniques for publishing web applications – both websites and web APIs – to the cloud. I’m being purposely vague when saying “the cloud” – it could be Windows Azure, AWS, or even a traditional hosting provider. It’s likely you saw a great post by Michael Washam that provides a solution for using Windows Azure virtual machines along with Web Deploy and a few PowerShell scripts. What’s below is a technique adapted from Michael’s post and detailed for each of the steps. What I like about this approach is that, aside from the machine preparation, the deployment technique is consistent across different platforms.

There are certainly a few things missing below: scripts for scaling up/down, scripts for running Windows update, and so forth. I’ll tackle these in future posts. My point here is to highlight a different way to look at tackling a common problem.

What are some of the advantages to this approach?

  • Near instant deployment.
  • Fully automated.
  • Consistent development model with other platforms.
  • Consistent deployment model with other platforms.

I’m sure there are more. There are some limitations as well – in particular, you’re bound by the number of roles you can have in your Cloud Service, which today is (I think) 25. This means that, at most, you can only scale out to 25 virtual machines. I imagine this limitation will be removed at some point (or perhaps you could get around it by using virtual networks).

Regardless, give it a try.

Note: You can find the PowerShell scripts used below in this gist here: https://gist.github.com/wadewegner/5080142.

Image Preparation

In this first step you’ll create and customize a virtual machine that you’ll then sysprep and turn into a disk that we’ll use later on.

Create the Base Virtual Machine

This first part takes the longest. This is because you’re preparing the disk you’ll use moving forward. Note that you only do it once – this is not something you have to do over and over again.

1. Create a Virtual Machine.
 WAIIASImage1

2. Enter the VM information. Use the default “Windows Server 2012 Datacenter” image. Size doesn’t matter. This VM will sysprepped and used as a disk image for creating future virtual machines.
WAIIASImage2

  • Be sure to note the location you use.
  • Be sure and remember the password. You’ll need it.

3. Start the VM.

  • Note: Notice that VMs create a Cloud Service. Each VM is actually a role within

4. RDP into the VM once it has provisioned and started.
WAIIASImage3

5. Click to Add roles and features.
image

6. Leave defaults and click Next until you get to Server Roles.

7. Choose Application Server and Web Server (IIS). Click Next.
image

8. Under Features be sure to select ASP.NET 4.5.
image

9. Click Next until you get to Role Services under Web Server Role (IIS).

10. Add ASP.NET 4.5 under Application Development. This will add the other default values.
image

11. Click Next until you get to the last step. Click Install. Wait until the operation completes.

Install and Use Windows Azure PowerShell Cmdlets

12. From the machine, download the Windows Azure PowerShell Cmdlets. These can be found at: http://www.windowsazure.com/en-us/downloads/.

13. Install the cmdlets. This can take 5-15 minutes.
image

14. Create the folder c:\\Scripts.

15. Run the following script in Windows PowerShell ISE to download your publish settings file:

Get-AzurePublishSettingsFile

16. Save or move this file into the c:\\Scripts folder and rename to credentials.publishsettings.

17. Run the following script in Windows PowerShell ISE to change the execution policy:
Set-ExecutionPolicy Unrestricted

Setup Web Deploy

18. Download Web Deploy 3.0 from the following link: http://download.microsoft.com/download/1/B/3/1B3F8377-CFE1-4B40-8402-AE1FC6A0A8C3/WebDeploy_amd64_en-US.msi. Do not install. To simplify, download to C:\\.

19. Open a Command Prompt.

20. Run the following command:

C:\\>msiexec /I webdeploy_amd64_en-us.msi /passive ADDLOCAL=ALL LISTENURL=http://+:8080/
image

Configure Firewall Settings

21. Run Windows Firewall with Advanced Security.

22. Select Inbound Rules and click New Rule.

23. Select Port and click Next.

24. Level TCP selected and enter 8080 for the Specific local ports.
image

25. Keep the defaults and click Next until prompted to give a name. Choose a name (e.g. Web Deploy Port) and click Finish.

System Preparation

26. Open a Command Prompt as an administrator.

27. Change the directory to: %windir%\\system32\\sysprep

28. Run sysprep.exe.
image

29. Ensure the following options are selected:

  • Enter System Out-of-Box Experience (OOBE)
  • Generalize
  • Shutdown
    image

Capture the Virtual Machine

30. Return to your Virtual Machine Instances tab in the portal: https://manage.windowsazure.com/#Workspace/VirtualMachineExtension/vms.

31. Wait until you see that the status of your virtual machine is Stopped.
image

32. Capture the image by clicking the CAPTURE button below.
clip_image024

33. Select an image name (e.g. WS2012-WebFarmImage) and check that you have sysprepped the machine. Click the button.
image

34. When the capture operation completes you’ll see the disk image available under Images in the portal: https://manage.windowsazure.com/#Workspaces/VirtualMachineExtension/images

image

Virtual Machine Deployment

You’ll run these steps from your own PC.

1. Open the Windows PowerShell ISE to run the following scripts. It’s always a good idea to save them somewhere to use later.

2. You might need to import your publish settings. If so, download your publish settings file, save it, then import it.

Get-AzurePublishSettingsFile

Import-AzurePublishSettingsFile C:\\credentials.publishsettings

3. Get the subscription name to which you’ll deploy. Run the following script:

Get-AzureSubscription -Current
image

4. You need to get the storage account that contains your disk image. You’ll need to use the same storage account for the disks attached to the web servers in your web farm. Select the Images tab under Virtual Machines on the portal. Find your image and look at the location. The first part of the URL is the storage account name.
image

5. It’s now time to deploy your web farm using the disk image you created in the previous section. Review the following script and update appropriately.

$imgname = 'WS2012-WebFarmImage'
$cloudsvc = 'DemoWebFarm'
$pass = 'Password'
$subscriptionName = 'Windows Azure MSDN - Visual Studio Ultimate'
$storageAccount = 'portalvhds9dvbvvff5hdg3'
$location = 'East US'

Set-AzureSubscription -SubscriptionName $subscriptionName -CurrentStorageAccount $storageAccount

$iisvm1 = New-AzureVMConfig -Name 'iis1' -InstanceSize Small -ImageName $imgname |
    Add-AzureEndpoint -Name web -LocalPort 80 -PublicPort 80 -Protocol tcp -LBSetName web -ProbePath '/' -ProbeProtocol http -ProbePort 80 |
    Add-AzureEndpoint -Name webdeploy -LocalPort 8080 -PublicPort 8080 -Protocol tcp | 
    Add-AzureProvisioningConfig -Windows -Password $pass
    
$iisvm2 = New-AzureVMConfig -Name 'iis2' -InstanceSize Small -ImageName $imgname |
    Add-AzureEndpoint -Name web -LocalPort 80 -PublicPort 80 -Protocol tcp -LBSetName web -ProbePath '/' -ProbeProtocol http -ProbePort 80 |
    Add-AzureProvisioningConfig -Windows -Password $pass
    
$iisvm3 = New-AzureVMConfig -Name 'iis3' -InstanceSize Small -ImageName $imgname |
    Add-AzureEndpoint -Name web -LocalPort 80 -PublicPort 80 -Protocol tcp -LBSetName web -ProbePath '/' -ProbeProtocol http -ProbePort 80 |
    Add-AzureProvisioningConfig -Windows -Password $pass    
    
New-AzureVM -ServiceName $cloudsvc -VMs $iisvm1, $iisvm2, $iisvm3 -Location $location

Notes on script:

  • $imgname: This is the name of the disk image you created.
  • $cloudsvc: When you deploy it will create a cloud service. This is the name for the cloud service.
  • $pass: This is the password for the virtual machine you created.
  • $subscriptionName: This is your subscription name.
  • $location: The datacenter you want to deploy into. Note: this has to be the same data center as your storage account.

It is important to note that the setup for $iisvm1 is different than $iisvm2 and $iisvm3. That’s because we’re adding an additional endpoint named webdeploy on 8080. We’ll use this public port for deploying via web deploy. It is not opened on the other machines.

6. It’s time to run the script. Note: the script does not rollback. If you have values that are incorrect you’ll have to clean them up manually. If all goes well, you’ll see progress indicators like the following:
image
image

7. You can now look in the portal and you’ll see the following machines Running/Provisioning.
image

8. You can browse the URL, for example: http://demowebfarm.cloudapp.net. You’ll get the standard IIS page:
image

Setup Synchronization across Virtual Machines

1. Remote into iis1. From the portal, select iis1 under Virtual Machine Instances and click the CONNECT button. This will download an RDP file. Save this and use it for connecting to the machine later.
clip_image039

2. Open Windows PowerShell ISE.

3. Click New to create a new script.

4. Copy the following script and save it as C:\\Scripts\\Sync.ps1. DO NOT RUN IT.

$subscriptionName = 'Windows Azure MSDN - Visual Studio Ultimate'
$storageAccount = 'portalvhds9dvbvvff5hdg3'
$cloudsvc = ' DemoWebFarm' 
$publishSettings = 'C:\\Scripts\\credentials.publishsettings'

Import-Module 'C:\\Program Files (x86)\\Microsoft SDKs\\Windows Azure\\PowerShell\\Azure\\Azure.psd1'

Import-AzurePublishSettingsFile $publishSettings
Set-AzureSubscription -SubscriptionName $subscriptionName -CurrentStorageAccount $storageAccount

$publishingServer = (gc env:computername).toLower()

Get-AzureVM -ServiceName $cloudsvc | foreach { 
    if ($_.Name.toLower() -ne $publishingServer) {
       $target = $_.Name + ":8080"
       $source = $publishingServer + ":8080"

       $exe = "C:\\Program Files\\IIS\\Microsoft Web Deploy V3\\msdeploy.exe"
       [Array]$params = "-verb:sync", "-source:contentPath=C:\\Inetpub\\wwwroot,computerName=$source", "-dest:contentPath=C:\\Inetpub\\wwwroot,computerName=$target";

        & $exe $params;
    }   
}

Create a Scheduled Task

5. Open Task Scheduler.

6. Click Create Task …
image

7. On the General tab set the Name and Run wehather user is logged on or not.
image

8. On the Triggers tab click New. Create a Daily trigger and Repeat task every 2 minutes. Click OK.
image

9. On the Actions tab click New. Set the following values:

Program/script: C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe
Add arguments: -File C:\\Scripts\\Sync.ps1
image

10. You should now see this as a scheduled task.
image

11. You can wait for this to run or run it manually. It should run successfully.
image

Deploy a Website through Web Deploy

1. Create a new ASP.NET MVC 4 Web Applications. (In actually it can be anything.) Choose an Internet Application.
image

2. Update the HomeController.cs code:

public ActionResult Index()
{
    string machineName = Environment.MachineName;
    ViewBag.Message = "Computer Name: " + machineName;

    return View();
}

3. Right-click on your application and click Publish.
image

4. In the dropdown select New.
image

5. Give your publish profile a name. Click OK.
image

6. Update all the fields:
image

  • Server: This is the DNS name of the cloud service with port 8080.
  • Site name: This needs to be “Default Web Site”.
  • User name: This is the administrator account.
  • Password: The password you set.
  • Destination URL: The same as server without the ports.

7. Click Publish.

8. In Visual Studio you should see that it deployed successfully.
image

WARNING: Don’t be alarmed if the browser opens and you don’t see your site. Remember that we set synchronization at two minutes and you have a 66% chance of hitting iis2 or iis3.

9. If you go back to your RDP session with iis1 and browse to C:\\inetpub\\wwwroot you’ll see all your content has been deployed.

10. Either way two minutes or manually invoke your synchronization task. Hit the website again and start refreshing:
image
image

That’s it!

Yeah, that might seem like a lot but realize that most of the work detailed here – such as the image preparation – you’ll only have to do one time. The rest of the time you’re using tools like PowerShell and Visual Studio.

Enjoy!

Yesterday Windows Azure experienced a worldwide disruption in many services due to an expired PKI certificate for Windows Azure storage. Mary Jo Foley’s article Windows Azure storage issue: Expired HTTPS certificate possibly at fault provides the best coverage of the event as it unfolded. You can also take a look at a few threads on the Windows Azure forum and Stack Overflow that provide a lot of commentary on the event. The effects of this disruption rippled through most of the other Windows Azure services. Even if you modified your application to use HTTP instead of HTTPS it’s likely you still had issues given that the rest of the platform was crippled by the expired certificate.

It’s disappointing this happened but highlights a pretty common situation. This has nothing to do with the merits of the Windows Azure storage service or any other parts of the platform – this is an operations management issue, plain and simple. The irony is that, as a number of folks including Lars Wilhelmsen have pointed out, there are tools like Microsoft SCOM that provide a Certificate Management Pack that can notify operations of expiring certificates. I can’t imagine the operations team at Windows Azure doesn’t use some kind of tool to manage expiring certificates.

As a developer, I found myself curious to see just how hard it is to determine the expiration of a certificate by checking the URI. Turns out, it’s pretty simple by using System.Net.ServicePoint which provides connection management for HTTP/S connections.

private string GetSSLExpiryDate()
{
    string url = "https://www.aditicloud.com/";
    var request = WebRequest.Create(url) as HttpWebRequest;
    var response = request.GetResponse();

    if (request.ServicePoint.Certificate != null)
    {
        return request.ServicePoint.Certificate.GetExpirationDateString();
    }
    else
    {
        return string.Empty;
    }
}

Pretty simple. What’s hard is the practice of managing and tracking these sorts of things.

I would expect that Microsoft will ensure that this kind of problem never happens again. It’s embarrassing yet solvable. Yet it exposes an issue that most of us will also have to account for – expiring certificates. If it can happen to Microsoft, it can happen to us too.