Call a svc Web Service from Table Script

Hi!

Is it possible to call a REST .svc Web Service from the CRM table scripts after a Company is created or updated with the companyid in the call?

Also, is there an existing table script execution log I can consult to debug?

Thanks!

Pascal.

  • 0

    Pascal

    I assume you want to call something like

    http://[servername]:[port]/CustomService.svc/methodName?paramName=value

    Will you be calling using GET or POST? - just something to think about.

    In an ASP page you can do this

    var objSrvHTTP;

    objSrvHTTP = Server.CreateObject ("Msxml2.ServerXMLHTTP.6.0");

    objSrvHTTP.open ("GET","http://[servername]:[port]/CustomService.svc/methodName?paramName=value", false);

    objSrvHTTP.send ();

    Response.ContentType = "text/xml";

    Response.Write (objSrvHTTP.responseXML.xml);

    See: msdn.microsoft.com/.../ms766431(v=vs.85).aspx

    Within the Table Level Script you will need to handle what ever the web service returns appropriately.

  • 0

    Hi Jeff,

    The objective is to detect any update / creation of Company in SAGE and call the web service from the table script with the companyId in its address. The web service retrieves all the data for that company, formats it to our liking for our systems to digest, then sends a message over NServiceBus (MSMQ) for any subscribers to pick up.

    I would like to call something like you've mentioned using the GET method. The companyId will be a param in the URL.

    The only operation I would like the table scripts to do is call the web service. My web service is in .NET 4 so ideally I'd like to avoid using an ASP page.

    Pascal.

  • 0

    Here's a very basic worked example.

    The very first thing you want to do if you haven't already is to familiarise yourself with the contents of this blog entry:
    https://community.sagecrm.com/partner_community/b/hints_tips_and_tricks/archive/2009/10/31/function-library-for-tablescripts.aspx

    Having all your stuff in one place makes life immeasurably easier.

    Once you've established your common scripts file, then put these common functions in:

    //*
    //COMMON FUNCTIONS

    //** Quick switch to enable/disable file logging **
    function loggingOn() {
    return true;
    }

    //***** SET THIS SPECIFIC TO THE CRM INSTANCE *****
    function logFileName() {
    return "C:\\CRM\\CRM\\Logs\\tablescriptlog.txt";
    }
    //***** SET THIS SPECIFIC TO THE CRM INSTANCE *****


    function writeToFile(message) {

    if (loggingOn()) {
    try {
    var fso = new ActiveXObject("Scripting.FileSystemObject");
    var s = fso.OpenTextFile(logFileName(), 8, true);
    var fName = arguments.callee.caller.toString().match(/function ([^\(]+)/)[1]
    s.writeline(new Date().toTimeString() + " - " + fName + ":");
    s.writeline("---- " + message);
    s.writeline("");
    s.Close();
    fso = null;
    } catch (error) {
    ErrorStr += message;
    }
    }
    }

    /*

    That actually answers the second part of your query as to logging. There's your logging right there.

    Now let's create a script function in the .js file that will get called from Company Update:

    function Company_Test_UpdateRecord() {
    try {
    writeToFile("***** Update Record");
    } catch (error) {
    writeToFile("ERROR: " + error.message);
    }
    }

    In CRM, create a new Tablescript for Company, and in the Update function, call Company_Test_UpdateRecord(), like so:

    function InsertRecord() {
    }

    function PostInsertRecord(){
    }

    function UpdateRecord() {
    Company_Test_UpdateRecord();
    }

    function DeleteRecord(){
    }


    Assuming all goes well then once you've edited a company you should see the tablescript log. Great.

    Now to business. For the purposes of example I'm going to use our old Microsoft friend, 'Northwind'. There's an OData REST endpoint at services.odata.org/.../Northwind.svc, so we'll use that. I'll just send a GET request in this example:

    function Company_Test_UpdateRecord() {
    try {

    writeToFile("***** Update Record");
    try {

    var req = new ActiveXObject("Microsoft.XMLHTTP");
    req.open("GET", "services.odata.org/.../Orders eq 10248", false);
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.send(null);

    writeToFile(req.responseText);

    } catch (e) {
    writeToFile(e.message);
    }

    } catch (error) {
    writeToFile("ERROR: " + error.message);
    }
    }

    Before we get all excited and run our code, there's a few salient points to make.

    1) We're using 'new ActiveXObject' to instantiate our XMLHttpRequest object. This script doesn't execute in the browser, so we can't just new up an XMLHttpRequest object directly. But we can't use Server.CreateObject either as we're not running in the context of an ASP page.

    2) Our AJAX call is synchronous. I agree that that's no way to run a railroad, but again, it's down to the context in which the TableScript code is executed. As far as I can tell, CRM parses and executes the code as part of an eWare.dll internal process. As a result, it pays no heed to the idea of async; once the code executes, the context in which it's running is disposed of - so it'll never wait for an async request to return. If you're expecting the request to be laggy or slow then you might want to think about setting the TableScript up as detached, so as to not degrade the user experience too much.

    3) I'm not parsing the responseText, as we don't have a JSON object. Again, as we're not in the browser there's no such thing as JSON. It's easy enough to get JSON in ASP pages by slightly doctoring Doug Crockford's json2 library (see discussion here : https://community.sagecrm.com/partner_community/f/49/t/13389.aspx), but you'd basically have to construct the JSON object in the table scripts .js file to enjoy the same functionality here. And ain't nobody got time for that!

    So try that and have a look in your log file - you should see the result of the request. Happy days.

  • 0

    Everything that Chris says except (and I can't believe that I am adding to him)

    var req = new ActiveXObject("Microsoft.XMLHTTP");

    is very much a client 'thing'. See: support.microsoft.com/.../frequently-asked-questions-about-serverxmlhttp

    I think you'll need to use

    var req = new ActiveXObject("Msxml2.ServerXMLHTTP.6.0");

  • 0

    Chris

    Will you be able to come to the partner Meet Up in Newcastle? It's on the 18th July. It would be excellent to capture your thoughts about the product.

    Details below. (we can then fight in the car park).

  • 0

    Oooff! I think a fight in the car park might be in the offing.

    Hang on then, let me give it a go......

    OK, either works on my machine*. So probably better that we stick with the Jeff version, with its inherent server-ness!

    * I'm a developer, so of course it "works on my machine".

  • 0

    Well, if I'm (a) allowed out of my cupboard at Increase, and (b) allowed back into North Park after what happened last time*, then I'd love to attend. I'll ask the bossman tomorrow.

    *only joking.

  • 0

    Thanks Chris, your suggestion worked nicely using Jeff's suggestion of newing the ActiveXObject objetc with Msxml2.ServerXMLHTTP.6.0.