Simon Fell > Its just code > Sforce and Indigo revisited

Friday, December 30, 2005

You may remember I tried the Nov CTP of Indigo without much luck, it would insist on sending the WS-Addressing headers with mustUnderstand='1' on them, which would cause the request to correctly fail. My plea on the indigo newsgroup was met with stark silence. I finally stumbled over how to do it, in the cofig file you change the mapAddressingHeadersToHttpHeaders attribute from false to true, which turns off WS-Addressing in favor of HTTP addressing. So, here's a step by step guide to get you started with Indigo and Sforce.

  1. Login to your salesforce account and download the enterprise WSDL.
  2. Run svcUtil /tm /uxs /config:client.exe.config enterprise.wsdl to have it generate the stubs from the WSDL, the /tm & /uxs switches tell it to use typed messages and the xmlSerializer, this used to be the only way Indigo would handle the WSDL, not sure if that's still the case.
  3. Ignore the reams of warnings like Warning: Fault named LoginFault in operation login cannot be imported. Type named LoginFault from namespace urn:fault.enterprise.soap.sforce.com cannot be imported by XmlFormatter. looks like they've still got a ways to go on the fault handling.
  4. Write your client code, to make the login call you'll need something like
    SoapProxy proxy = new SoapProxy();
    loginResponse lr = proxy.login(new loginRequest(new loginRequestBody(username, password)));
    LoginResult res = lr.Body.result;
    Console.WriteLine("Logged in, SessionId is {0}", res.sessionId);
    Console.WriteLine("serverUrl is {0}", res.serverUrl);
    
  5. Now you need to redirect the proxy to the new serverUrl, from reading the docs you ought to be able to do
    proxy.Endpoint.Address = new EndpointAddress(res.serverUrl)
    but it seems to ignore this and continue to send requests to the original url, so you need to create a new instance of the proxy with a different address, at the same time, go ahead and setup the SessionHeader instance
    proxy = new SoapProxy("", res.serverUrl);
    // setup the session header
    SessionHeader sid = new SessionHeader();
    sid.sessionId = res.sessionId;
  6. Now you can make a call, here's a call to describeSObject
    DescribeSObjectResult desc = proxy.describeSObject(new describeSObjectRequest(sid, new describeSObjectRequestBody("Account"))).Body.result;
    foreach (Field f in desc.fields)
    {
    	Console.WriteLine("{0}", f.name);
    }
    
  7. Compile it up and off you go, but it won't work, you'll get the can't understand headers fault back, so go into the client.exe.config file and change mapAddressingHeadersToHttpHeaders="false" to mapAddressingHeadersToHttpHeaders="true"

You can grab a zip of the demo client and a make file : sforceIndigoClient.zip. Some things I noticed are that the serialization contains multiple duplicate namespace declarations (for the xml schema & xml schema instance) and doesn't even use them, but hey bandwidth is cheap!. I also see that there's no User-Agent HTTP header, seems like a fairly lame omission, hopefully that'll get addressed. The Out of box experience is frankly pretty shitty, the default settings mean an Indigo client is going to fail by default with pretty much any service that wasn't written in Indigo.

As far as a .NET soap stack for use with Sforce, I see nothing in Indigo that would make me switch away from the existing .NET soap stack, the programming model is more verbose and cumbersome, and still seams heavily focused purely on Indigo -> Indigo scenarios. There are still missing features that are in the .NET 2.0 soap stack like support for response compression, I hope in the remaining 12 months before they ship they can address some of more egregious stuff, but realistically I can imagine they're already in lockdown mode, punting anything that's not a critical bug to a future release, we'll have to wait and see.