UPDATE (May 2018): See my latest article for more information on how to manage calls programmatically on 3CX v15. The article below was written for 3CX 11 and some information may not be applicable for the latest version of 3CX.
In one of the projects at work I attempted to use the 3CX Call Control API (see this) from my .NET application and encountered unique challenges because the Call Control API is only available from a .NET application running on the same server as the 3CX machine. This means, even if the sample .NET application to demonstrate the API provided by 3CX is working well, it is of little usefulness if you want to expose the API to your custom application which undoubtedly must be running from the client machine and not on the same server.
Issues with 3cxpscomcpp2.dll when called from ASP.NET SOAP web service
My design is to write an API wrapper that runs on the 3CX server, receives client requests via HTTP, interacts with the 3CX Call Control API to perform the necessary actions and returns the API response back to the client also via HTTP.
With this design, the first attempt is to use an ASP.NET SOAP web service, which unfortunately does not work. First, the web service fails to start due to a BadImageFormatException once the API DLL 3cxpscomcpp2.dll, is added as a reference to the project
System.BadImageFormatException: Could not load file or assembly ‘3cxpscomcpp2.dll’ or one of its dependencies. An attempt was made to load a program with an incorrect format
Knowing that this is because of the format of the DLL (32-bit vs. 64-bit) and the architecture of the project (x86 or x64), I tried to changed the project platform but neither x86 or x64 works. I also changed the application pool settings inside IIS following this article, which also does not help.
Next I noticed that the API DLL is a 64-bit DLL and attempted to install 3CX on a 32-bit machine to retrieve the 32-bit version of the DLL. This time, the error message when loading the web service changed:
The error message is not very useful and several Google searches did not return any working solutions. This has to do with the fact that the 3cxpscomcpp2.dll uses a native C++ dll named sl.dll. For the API to initialize properly, both DLLs are required. Despite substantial research, I could not find any reasons why sl.dll fails to be loaded and thus giving up integrating the DLL with ASP.NET web service.
The solutionMy next attempt is to use a Windows Communication Foundation (or WCF) aplication instead, and not ASP.NET web service. The application will hook up to a HTTP port on the machine, listening to HTTP request via POST/GET and returning the response in JSON. This time, the application has no difficulties connecting to the API and things work as expected. Take note that you will need to host your WCF service in a console app, or as a Windows service. Hosting it under IIS and you will still encounter the same BadImageFormatException issue.
- The browser must allow cross domain calls. For Chrome, you can launch chrome with the parameters –disable-web-security and cross domain calls will be allowed.
- The server response must contain the following header to allow calls from any origin:
- The server sends the response in JSONP
Because (1) is out of the question since the calling web site must be able to support different browsers while (3) is not possible yet from WCF, I have chosen (2). Luckily I found the following MSDN blog which proposes a solution that does not require any code changes:
- Import the WebHttpCors DLL provided by the author
- Modified app.config to add the tag to allow cross-domain calls.
It works well and the API can be called from jQuery with no issues. However, during the project, I also noticed several limitations with the 3CX Call Control API:
- There is no API to put a call on hold. The closest you can get is to transfer the call to a parked extension. To unhold the call, make a call to the parked number and you will be able to continue with the parked call.
- There is no API to retrieve the call history and the application needs to manually parse the 3CX Call History log files located at C:ProgramData3CXDataLogsCallHistory or read from the 3CX internal PostgreSQL database. Refer to this article for more details. In this aspect, the approach of using a WCF application instead of ASP.NET poses a major advantage because as a Windows application, WCF has no difficulties accessing files located on different paths on the server. This is also needed to read the call recording files located at C:ProgramData3CXDataRecordings