Calling a custom Salesforce Apex web service from C#
Update: The code below has been updated to copy the server address from the login result into the binding for our custom web service. Unfortunately it doesn’t work if you just copy the URL directly, so I parsed it to take the server URL and append the path to my web service. This works, but if anybody has a better suggestion I’d love to hear about it.
————————————————-
Having just figured out how to do this, I thought I’d post some sample C# code just to save somebody else the grief that I just went through. It’s simple, but not completely intuitive. The trick is that you have to authenticate via the Enterprise wsdl then pass the resulting Session ID over to your custom web service.
I got pretty tired of reading “answers” in the forums that consisted of, “Download the WSDL, cover your eyes, and when the smoke clears, everything will work perfectly.” So I thought I’d break with tradition here and show some actual working C# code. The Apex side is pretty well documented (search for WebService in the Force.com Apex Code Developer’s Guide). But then they just refer you to how to call this from JavaScript and Ajax without any mention of authentication. Yeah, that’s useful, thanks. Anyway, here are the steps to get this to work.
- Create your web service in Apex, following the Force.com documentation. In my example the class is called AccountMaintenance and the web service method is called myApexMethod.
- Download your web service wsdl file (Setup -> Develop -> API Classes, and click on WSDL next to your class).
- Download your Enterprise wsdl file (Setup -> Develop -> API -> Generate Enterprise WSDL).
- Add references to both of these wsdl’s in your Visual Studio project (I’m using the .NET 2.0-style Web Reference here). My Enterprise service is named “Enterprise” and the reference to my Apex web service is “MyApexClass”.
- Add “using” statements as shown below.
- Create binding objects pointing to each of these services.
- Log in using your Enterprise wsdl as you normally would (I hard-coded the credentials in this sample, but of course you’d want to prompt for those). Don’t forget to append your security token to the password.
- Instantiate the SessionHeaderValue object in your custom web service’s binding object, and set the sessionId to the value returned by the login process.
- Now you can call methods on your Apex class
I hope somebody out there finds this useful. If so, or if I’ve left anything out, I welcome your comments.
====================
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using ApexWebService.Enterprise; using ApexWebService.MyApexClass;
namespace ApexWebService
{
public partial class frmMain : Form
{
private SforceService enterpriseBinding = new SforceService();
private AccountMaintenanceService myBinding = new AccountMaintenanceService();
// This is the name of the Apex Class + "Service", defined in the MyApexClass WSDL
private void btnGo_Click(object sender, EventArgs e)
{
LoginResult lr = enterpriseBinding.login("me@mydomain.com", "myPasswordMyToken");
myBinding.SessionHeaderValue = new MyApexClass.SessionHeader();
myBinding.SessionHeaderValue.sessionId = lr.sessionId;
// Update: Copy the URL returned by login to the endpoint for our web service
int idx1 = lr.serverUrl.IndexOf(@"/services/");
int idx2 = myBinding.Url.IndexOf(@"/services/");
if (idx1 == 0 || idx2 == 0)
{
MessageBox.Show("Invalid URL strings in bindings");
return;
}
myBinding.Url = lr.serverUrl.Substring(0, idx1) + myBinding.Url.Substring(idx2);
// End update
string result = myBinding.myApexMethod();
MessageBox.Show("The web service returned " + result);
}
public frmMain()
{
InitializeComponent();
}
}
}


You need to call the custom web service with the endpint that you get from the login. The generated WSDL has an endpoint that points to the sf instance that it was generated from, which cannot be trusted for production use. Both because your WSDL may very well have been generated from a sand box and because sf may move your Org to another production server in case you generated the WSDL from your production sf.
Thanks, Michael – I was wondering about that, too, and I appreciate the info. As soon as I can get around to adding that to the code and testing it I’ll post an update.
Hi Michael,
I have a requirement where I need to insert or update records in custom designed Apex Salesforce WebService which gets records from SQL job on nightly basis.
Let me know how to trigger WebService from SQL job we aren’t using SSIS.Also suggest on how the integration will happen from SQL job to WebService.
Thanks,
Sidhartha
Sorry, I’m not an expert on SQL Server jobs, so I’m not sure how you would trigger the process from a job. But you might look at CLR Integration to see if that will help. That might allow you to trigger some code written in C# to query SQL and call your Apex web service with the new data.
Hi Mike,
Many thanks for your post. It assisted me with a short deadline that I had committed too
Regards,
Warren