Simon Fell > Its just code > Salesforce.com

Saturday, May 03, 2008

Metadata API (more)

I discovered a new Salesforce related blog today, and noticed that they spread the seeming popular meme that the metadata API doesn't work on standard objects, so just clarify that that's wrong, here's a .NET example that adds a new custom field to the standard Account object.

using System;
using System.Collections.Generic;
using System.Text;

namespace metadata
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length != 2)
            {
                Console.WriteLine("useage: metadataDemo username password");
                return;
            }
            MetadataCreator mc = new MetadataCreator(args[0], args[1]);
            mc.Create();
        }
    }

    class MetadataCreator
    {
        private metaforce.MetadataService ms;
        private sforce.SforceService ss;

        public MetadataCreator(String username, String password)
        {
            ss = new sforce.SforceService();
            sforce.LoginResult lr = ss.login(username, password);
            
            ss.Url = lr.serverUrl;
            ss.SessionHeaderValue = new sforce.SessionHeader();
            ss.SessionHeaderValue.sessionId = lr.sessionId;

            ms = new metaforce.MetadataService();
            ms.Url = lr.metadataServerUrl;
            ms.SessionHeaderValue = new metaforce.SessionHeader();
            ms.SessionHeaderValue.sessionId = lr.sessionId;
        }

        public void Create()
        {
            metaforce.CustomField cf = new metaforce.CustomField();
            cf.description = "Favorite fruit";
            cf.fullName = "Account.favFruit__c";
            cf.label = "Fav Fruit";
            cf.type = metaforce.FieldType.Text;
            cf.length = 25;
            cf.lengthSpecified = true;

            metaforce.AsyncResult r = ms.create(new metaforce.Metadata[] { cf })[0];
            while(!r.done) {
                System.Threading.Thread.Sleep(r.secondsToWait * 1000);
                r = ms.checkStatus(new string[] { r.id })[0];
            }
            if (r.state == metaforce.AsyncRequestState.Error) 
                Console.WriteLine("Error : {0} {1}", r.statusCode, r.message);
            else {
                Console.WriteLine("Done, added new field to Account");
            }
        }
    }
}
< 4:25 PM PDT # > tags : .NET Salesforce.com [playing "Inca Steppa" by Juno Reactor (from Gods And Monsters)]

Thursday, March 06, 2008

SFFS

About a year ago I posted about sfdcFuse, a command line utility that exposes the Document repository in Salesforce.com as a mountable volume using MacFUSE. Unfortunately this version doesn't work on Leopard, so I've been working on a Leopard version, and at the same time, getting rid of the command line interface and putting a regular cocoa front end on it. The result is SFFS (the SalesForce File System). Much like the earlier version, this exposes a read-only copy of your document repository as a mounted volume on your Mac. You get my standard UI for login, complete with keychain support, and auto-updates via Sparkle. Its available under the open source BSD license, everything is over on the Google code project.

< 10:39 PM PST # > tags : OSX Salesforce.com [playing "On Being Blue" by The Art Of Noise (from The Seduction Of Claude Debussy)]

Monday, February 18, 2008

SF Cubed v0.53

I just released this, it fixes a problem with all day events not picking up date changes from Salesforce.com, and addresses some weirdness relating to filtering on 10.5.2 (which would manifest itself as SF3 saying it picked up local changes, but that it didn't appear to change anything in Salesforce.com). I'm working entirely out of the Google code project now, so you can see source code changes for specific issues, issues come and go in the issue tracker, and the sparkle auto-updater is now pulling builds from the google code site. Everything seems to be working just fine.

< 9:08 PM PST # > tags : OSX Salesforce.com [playing "Eye of a Needle (Lemon D Remix)" by The Art Of Noise (from The Drum And Bass Collection)]

Sunday, February 17, 2008

Maildrop goes open source

Hot on the heals of SF3, Maildrop is now open source as well, checkout the source, log bugs, enhancement requests etc all over at the project home page @ Google code. My thanks to Ron and the ADN crew for helping organize this.

< 10:49 PM PST # > tags : OSX Salesforce.com [playing "E.F.L." by The Art Of Noise (from In No Sense? Nonsense!)]

Sunday, February 10, 2008

SFCubed now open source

With the 0.52 release of SF3 I made it open source under the BSD license. Rather than host everything myself, which is how I've handled previous open source projects of mine, (sourceforge looked to be on its last legs for quite a well, but is still going) I've decided to try out the Google code project hosting. Everything is over there, source code in SVN, an issue tracker that i loaded up with all the bugs and feature requests i know about, and there's a wiki that contains most of the content from my own SF3 page. Share & Enjoy.

< 11:33 AM PST # > tags : OSX Salesforce.com [playing "Chime [Live]" by Orbital (from Live At Glastonbury 1994-2004 [Disc 2])]

Friday, February 08, 2008

SF Cubed

For those folks that have ran into iCal sync problems on Leopard, try this build, let me know how you get on. (this also includes a lot of fixes for contact sync where your AB contact have more data than salesforce supports, e.g. multiple work phone numbers). I've also decided to open source SF3, as i just don't have the time to move it forward fast enough, the complexities of the sync and data mapping process/problems means you really can't work on it in little chunks of time like i can for the other apps. This should give the folks that are in need of more features and/or specific changes for their setup a chance to get what they need done.

< 9:31 AM PST # > tags : OSX Salesforce.com [playing "Let's Do It Together" by Blue Six (from Beautiful Tomorrow)]

Sunday, February 03, 2008

SoqlX superbowl edition

There's a new version of SoqlXplorer available, this version requires Leopard, it has an updated UI, support for displaying child queries (double click on the magnifying glass icon), a recent query list, and a few other bits'n'peices.

< 1:48 PM PST # > tags : OSX Salesforce.com [playing "I Love You... I'll Kill You" by Enigma (from LSD: Love, Sensuality and Devotion)]

Thursday, January 31, 2008

Metadata API from .NET

A few people have been asking for a complete example of using the metadata API from .NET, If you've using the regular enterprise/partner API, then the patterns should look familiar. One wrinkle for .NET is the whole fooSpecified mess, this is more apparent in the metadata API because most of the fields aren't strings.

I created a new project in VS.NET 2005, imported the enterprise WSDL (as sforce) and imported the metadata WSDL (as metaforce), the code makes a login call with the enterprise API, creates a stub for the metadata API, configuring the sessionHeader and Url from the login result (just like for the regular enterprise stub). then goes on to setup a CustomObject structure and passes it to create. One difference to the enterprise API is that the process is async, so you get back an AsyncResult structure that indicates its current state, a guess at how long to wait before checking its state again and so on, so we sit in a loop (with the specified waits) until its done. If the object was created, then we call describeSObject on the enterprise API to check that it really did do something, here's the code.

using System;
using System.Collections.Generic;
using System.Text;

namespace metadataDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length != 2)
            {
                Console.WriteLine("useage: metadataDemo username password");
                return;
            }
            MetadataCreator mc = new MetadataCreator(args[0], args[1]);
            mc.Create();
        }
    }

    class MetadataCreator
    {
        private metaforce.MetadataService ms;
        private sforce.SforceService ss;

        public MetadataCreator(String username, String password)
        {
            ss = new sforce.SforceService();
            sforce.LoginResult lr = ss.login(username, password);
            
            ss.Url = lr.serverUrl;
            ss.SessionHeaderValue = new sforce.SessionHeader();
            ss.SessionHeaderValue.sessionId = lr.sessionId;

            ms = new metaforce.MetadataService();
            ms.Url = lr.metadataServerUrl;
            ms.SessionHeaderValue = new metaforce.SessionHeader();
            ms.SessionHeaderValue.sessionId = lr.sessionId;
        }

        public void Create()
        {
            metaforce.CustomObject co = new metaforce.CustomObject();
            co.deploymentStatus = metaforce.DeploymentStatus.Deployed;
            co.deploymentStatusSpecified = true;
            co.description = "My Custom Object created from .NET";
            co.fullName = "DotNetCustomObject__c";
            co.label = "DotNet Custom Object";
            co.pluralLabel = "DotNet Custom Objects";
            co.sharingModel = metaforce.SharingModel.ReadWrite;
            co.sharingModelSpecified = true;
            co.nameField = new metaforce.CustomField();
            co.nameField.type = metaforce.FieldType.Text;
            co.nameField.label = "The Name";
            co.nameField.length = 100;
            co.nameField.lengthSpecified = true;

            metaforce.AsyncResult r = ms.create(new metaforce.Metadata[] { co })[0];
            while(!r.done) {
                System.Threading.Thread.Sleep(r.secondsToWait * 1000);
                r = ms.checkStatus(new string[] { r.id })[0];
            }
            if (r.state == metaforce.AsyncRequestState.Error) 
                Console.WriteLine("Error : {0} {1}", r.statusCode, r.message);
            else {
                Console.WriteLine("Created customObject {0}, calling describeSObject now", co.fullName);
                sforce.DescribeSObjectResult d = ss.describeSObject(co.fullName);
                Console.WriteLine("DescribeSobject for {0} ({1})", d.name, d.label);
                foreach(sforce.Field f in d.fields)
                    Console.WriteLine("{0}\t{1}", f.name, f.type);
            }
        }
    }
}
And here's the output from a running it
Created customObject DotNetCustomObject__c, calling describeSObject now
DescribeSobject for DotNetCustomObject__c (DotNet Custom Object)
Id      id
OwnerId reference
IsDeleted       boolean
Name    string
CreatedDate     datetime
CreatedById     reference
LastModifiedDate        datetime
LastModifiedById        reference
SystemModstamp  datetime

Creating customFields is just as easy, just remember to specify the fully qualified fieldname as its fullName, e.g. if you wanted a new field on your custom object co__c, you set the name to be co__c.newField__c, or if you wanted a new custom field on Account, it'd be Account.newField__c. Share and Enjoy.

< 9:28 AM PST # > tags : .NET Salesforce.com [playing "Metaforce" by The Art of Noise (from The Seduction of Claude Debussy)]

Monday, January 21, 2008

ApexDataLoader

At Thursdays Tour de Force conference, I ran into a few folks who asked for a more upto date build of the DataLoader for OSX. I put together a new build based on the 10.0 Apex Data Loader. I've tested this on Leopard, it should also work on Tiger if you have the Java 1.5 update installed (but I haven't tried it, if you have trouble the older version was built & tested on Tiger, details here). If you're still on Tiger, let me know how you get on with it.. And a reminder, you can find the complete list of my OSX/Salesforce.com tools at http://www.pocketsoap.com/osx/.

< 2:55 PM PST # > tags : OSX Salesforce.com [playing "Blue Train" by Page & Plant (from Walking Into Clarksdale)]

Sunday, January 06, 2008

Updated Apex plugin for TextMate

I updated the TextMate plug-in I wrote for Apex, the new version handles the keychain much better, and now supports servers other than www.salesforce.com (e.g. Sandbox or pre-release). Download the updated plugin bundle and drop it in your ~/Library/Application Support/TextMate/Bundles folder.

< 3:53 PM PST # > tags : OSX Salesforce.com [playing "Property Is Theft" by Klute (from The Secret Art Of Science 2)]

Thursday, January 03, 2008

Tour De Force

Tour de Force - San Francisco is rapidly approaching, your chance to talk to other Salesforce.com customers & developers, and to hear from and talk to the product managers and developers behind the Force.com platform, I'll be there, bring your Web Services questions.

< 8:20 PM PST # > tags : Salesforce.com [playing "Eggshell" by Animals On Wheels (from Designs and Mistakes)]

Friday, October 26, 2007

Leopard day

Got Leopard installed without a hitch, spotlight is still chugging away re-indexing everything. Going back to my earlier Time Machine question, it won't let you pick a CIFS or SMB mounted volume as the destination, so I'd think the chances of Windows Home Server being usable as a TM destination are about 0. (There also seems to be an ongoing question about using TM with an AirPort Extreme hosted disk, which is disappointing)

A quick check of my apps, they all appear fine so far with the exception of SF3 which appears to have some weirdness around timezones in the calendar syncing. I need to dig into that some more. The new conflict and changes dialogs from Sync Services are nice, now you can actually see what's going to get changed when it warns you that 50 calendar entries are going to change.

< 2:00 PM PDT # > tags : OSX Salesforce.com [playing "The Thing That Should Not Be" by Metallica (from S&M Disc 1)]

Thursday, September 27, 2007

Maildrop v1.5

There's a new build of Maildrop available, this adds the email subject to the add email window so that you can edit before adding the activity to Salesforce. Restart Maildrop or pick Check for Updates from the help menu to pickup the new version.

Thanks to everyone who dropped by to talk OSX, WebServices and other stuff at Dreamforce, it was a packed three days, big props to Adam and the whole ADN crew for the kick ass developers lounge.

< 9:25 PM PDT # > tags : OSX Salesforce.com [playing "In Dust We Trust" by The Chemical Brothers (from Exit Planet Dust)]

Sunday, September 16, 2007

Wait there's more

There's a new build of Trapdoor available, this adds keyboard shortcuts for the first 9 logins in the login menu. And there's another new build of Maildrop, this has some improvements to the add email dialog window. As usual restart the app, or pick check for updates from the help menu to get updated to the latest versions.
< 7:36 PM PDT # > tags : OSX Salesforce.com [playing "Kein Trink Wasser [Live]" by Orbital (from Live At Glastonbury 1994-2004 [Disc 1])]

Thursday, September 13, 2007

Maildrop drop

There's a new build of Maildrop available, this changes the Add Email window to use a split pain to show both the Who and What searches at the same time, rather than the previous tabbed dialog, which people seemed to think you could only select a who or a what. Hopefully this'll make it clearer that you can use both, and quicker to boot. Restart Maildrop or pick Check for Updates from the help menu to pickup the new version.

And Dreamforce is fast approaching, I'll be there, probably spend most of my time in the ADN lounge / lab area, feel free to drop by to chat about Mac and/or Web Services stuff.

< 10:23 PM PDT # > tags : OSX Salesforce.com [playing "Are We Here? (Oral Mix)" by Orbital (from Are We Here -ffrr 697-120047-2)]