1

I have a Windows 8 Metro app pulling data from SalesForce through the REST API, which works for most queries. However, the routes to download attachments from records do not seem to work. As an alternative, I decided to try out the SOAP API, which seems to have better documentation.

Unfortunately, I have not been able to get the SOAP API to work on a Metro app because the SforceService object is not available when the WSDL file is added as a service reference. The most common solution(e.g. here, here, and here) is to add the WSDL as a web reference, however this is not possible for a Metro app. So, has anyone successfully used the SOAP API from a Metro app, and if so how did you get around the SforceService problem? Is there another way to add the WSDL that keeps SforceService?

For reference, I am using C# in Visual Studio Enterprise 2015, targeting .NET 4.6 with project type Windows 8.1 (Metro app). I am well aware of the process for adding a web service, and that works fine for a console application, but adding a web service is not an option for Metro apps.

Edit: Steps taken so far - Have added SalesForce WSDL file (both Enterprise and Partner) as a service reference, found that SforceService was not available. Tested with a console app and found that adding as a web service works correctly. Common answers to this issue are to add as a web service (not possible for Metro app), or to target .NET 3.5 (not practical for this project). I have not provided detail about the file issues in the REST API as my question here is about the SOAP API, I've only mentioned those problems as background for why I am trying to use the SOAP API.

0

When using a Service Reference to access the Salesforce SOAP APIs there are different methods for handling the SOAP headers.

With a web reference it is reasonable easy and there are plenty of examples out there that demo it.

Service references SOAP headers are done per request, are are MUCH more difficult in the Metro world.

enter image description here

Compare the generated Reference.cs file for the Service Reference between Metro and a standard Console Application

Console App

Among other methods and slightly shortened for clarity. Example calls can be found in Consuming Force.com SOAP and REST Web Services from .NET Applications and Accessing Force.com SOAP Endpoints with .NET

public Task<SforceService.loginResponse> loginAsync(SforceService.LoginScopeHeader LoginScopeHeader,
  SforceService.CallOptions CallOptions,
  string username, string password) {
    // ...
}

Metro App

public Task<SforceService.LoginResult> loginAsync(string username, string password) {
    // ...
}

Note the complete lack of SOAP headers that you will need to pass the sessionId etc...

The question then becomes how do you add those missing headers back in.

Nuget package WCFExtrasPlus 2.4.0 looks promising based on SOAP Headers - Client Side.

However, I ran into a more immediate problem. I tried dropping a button down and connecting via a service reference:

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        string userName = "foo@example.com";
        string password = "<password>";

        SforceService.SoapClient sforceServiceClient = new SforceService.SoapClient();
        SforceService.LoginResult loginResult = await sforceServiceClient.loginAsync(userName, password);

        System.ServiceModel.EndpointAddress apiAddress = new System.ServiceModel.EndpointAddress(loginResult.serverUrl);
        sforceServiceClient = new SforceService.SoapClient(App1.SforceService.SoapClient.EndpointConfiguration.Soap, apiAddress);

        //sforceServiceClient.SessionHeader = new SforceService.SessionHeader();

        SforceService.QueryResult soqlResult = await sforceServiceClient.queryAsync("Select Id, Name from Account limit 200");

        foreach (var account in soqlResult.records)
        {
            System.Diagnostics.Debug.WriteLine("Account Id: {0}", account.Id);
        }
    }

The call to loginAsync throws a System.ServiceModel.CommunicationException

'Unable to generate a temporary class (result=1).

error CS0012: The type 'System.Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

error CS0012: The type 'System.ComponentModel.INotifyPropertyChanged' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.ObjectModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

error CS0012: The type 'System.Enum' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

'. Please see InnerException for more details.

I'm not sure if that is my local machine setup or something specific to Metro.

Sample App project structure:

enter image description here

  • Daniel, your code still uses SforceService, may I ask what type of project this is? My project is a "Store App Windows 8.1", go here to determine the project type from the GUID in the csproj file. For a Metro/Store app, SforceService is not available after importing the WSDL file, among other problems it uses System.Web, which is not allowed in Metro/Store apps. – James Worcester Oct 15 '15 at 13:24
  • @JamesWorcester My project types are translating to "Store App Windows 8.1", "C#" from Visual Studio 2013. It definitely added the Partner v34.0 WSDL as a service reference, but appears to have problems around the .NET version. There might be a different version of svcutil.exe being used. My Reference.cs has "This code was generated by a tool. Runtime Version:4.0.30319.34014" – Daniel Ballinger Oct 15 '15 at 18:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.