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:
Could not load file or assembly
'3cxpscomcpp2' or one of its dependencies. Modules which are not in the manifest
were streamed in. (Exception from HRESULT: 0x80131043)
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 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 solution
My 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 next challenge is encountered when one of the developers using my APIs reported a strange error when calling my API from jQuery:
Origin http://localhost:8888 is not allowed by Access-Control-Allow-Origin.
To fix the error, one of the following must be done:
- 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:
Access-Control-Allow-Origin: * - The server sends the response in JSONP
- Import the WebHttpCors DLL provided by the author
- Modified app.config to add the
tag to allow cross-domain calls.
- 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:\ProgramData\3CX\Data\Logs\CallHistory 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:\ProgramData\3CX\Data\Recordings
I hope 3CX will be able to introduce more APIs in the future to solve the above mentioned limitations. For more information on how to use 3CX API with your .NET application, read my other article.
How do I contact you... This code is very interesting as part of a project i'm working on.
ReplyDeleteHi Biztactix, you can just submit your query here. I will try to answer where I can.
DeleteHow did you run WCF service? When I add 3cxpscomcpp2.dll and start debuging in visual studio I see message System.BadImageFormatException: Could not load file or assembly '3cxpscomcpp2.dll'... regardless x32, x86, 32-bit application pool?
ReplyDeleteHi,
DeleteYou will need to host your WCF service in a console app, or as a Windows service. Hosting it under IIS and you'll have the BadImageFormatException issue - same as when running as ASP.NET Web Service.
Secondly, once you've hosted as a console app or Windows service, check your build target to make sure your app is targeting x86/x64 accordingly, and not Any CPU. The 3cxpscomcpp2.dll file would need to be taken from a 3CX version that is installed for the specified architecture (x86 or x64 version), otherwise you will also have the exception.
Thirdly, remember to keep sl.dll in the same directly as the application executable, as it will try to load this DLL at runtime.
Hope this helps
Excellent, it works. :) Thank you.
DeleteI have same problem.
DeletePlease help me to solve this issue.
I need 3cxpscomcpp2.dll file for 64 bit version.
Could you say me how can I get this dll?
Hi, you will need to install 3CX server on a 64-bit version of Windows, then take the 3cxpscomcpp2.dll from the 3CX installation directory - it will be the 64-bit version. The installer copies either the 32-bit or 64-bit version of this DLL depending on your Windows version.
Deletethanks!
DeleteHi ,
ReplyDeleteI have a problem related to dropcall sample , so
Could you say me that where I can get parameters(callerId and participiant) for calling dropcall sample ?
Please help me .
Hi,
DeleteFor DropCall method, callID is the ID of the call that you want to terminate. You can retrieve this ID from the list of active calls returned by the GetActiveConnections() method. participant is the number of the party which you want to be removed from the call - just pass the extension number that is currently involved in the call. The call will be disconnected after the DropCall method if there are fewer than two active parties.
Let me know if you have any other questions.
Thanks for quick response!
DeleteWe can proceed to a call with MakeCall, but we are not able to find out the CallID from the database while the call is active.
After few minutes when the call is finished we can find this information it db table : callhistory3 and call details.
Maybe there is another table where can get this while the call is active. Thanks in advance!
Hi there,
DeleteActive calls will not be in the database- you need to get its ID from the Call Control API by using GetActiveConnections() as mentioned. The following code will help you to retrieve the callID for all active calls:
foreach (Tenant t in PhoneSystem.Root.GetTenants())
{
DN[] dnArr = t.GetDN();
foreach (DN dn in dnArr)
{
foreach (ActiveConnection con in dn.GetActiveConnections())
{
Debug.WriteLine(con.CallID);
}
}
}
With the above ID, pass it to DropCall and it will work.
Additionally the ID of the call that you saw in the DB tables is the history ID of the call - a long alphanumeric string that looks like 00000BD538E62E50_2539. The callID to be passed into DropCall should be a small integer that gets incremented each time a new call is placed on the PBX.
Thanks man , you saved my time
ReplyDeleteHI MD,
ReplyDeletePLEASE UPDATE SAMPLE SOURCE CODE FOR 3CX API & WCF.