iMIS API returns “An error occurred while constructing the query”

While working with business objects, IQA, and the API for iMIS 20.2.65.9955, I recently encountered a strange error or undocumented limitation that had me scratching my head for a bit until I figured out what was happening.

To summarize, I created a business object in RiSE, then used that business object to build an IQA query. I was able to run the IQA query and view the results within RiSE with no problems. I was also able to run the generated SQL query displayed on the IQA Summary tab directly against the database without encountering any errors.

When I attempted to use the iMIS API to retrieve the query results, however, the API returned the message, An error occurred while constructing the query. This didn’t make much sense to me since the query ran just fine within RiSE. What was going on?

After some experimentation, I determined that the API returns that error if the IQA query being called uses a business object with a name greater than 32 characters long. In other words, a business object named “KB1_MyBusinessObjectNameIsTooLong” will cause problems, but a business object named “KB1_MyBusinessObjNameIsJustRight” will not. Without knowing what the API is doing behind the scenes, I can’t explain exactly why this happens.

The solution is, of course, not to use business object names more than 32 characters long if you intend to retrieve the results of an IQA query using the iMIS API.

How to retrieve and display data using IQA and the iMIS API

In April, I started a new job. Among my duties at this point is working on converting the organization’s C#-based web parts to IQA queries and JavaScript widgets that make use of the API provided by ASI’s iMIS.

ASI’s API documentation is very thorough in some places, and frustratingly fragmentary in others. My goal here is to explain how to create a basic IQA query, which is easy enough, and to provide working HTML and JavaScript that will allow you to run that query that returns records with a specific last name and display the results to an iMIS-based website user.

As a reference point, I am using iMIS 20.2.65.9955 as the basis for this tutorial.

Building your IQA query

To begin, access your iMIS staff site, perhaps at https://www.example.org/Staff, and go to RiSE > Intelligent Query Architect. You’ll see a number of existing folders. I recommend creating a folder and if necessary subfolders of your own so that you can easily keep track of the queries that you create. For purposes of the JavaScript code I’ll share later on, I’ll name my folder MyTests.

Click New > Query, then enter a name for your query. For purposes of this tutorial, I’m going to name my query LastName-Test.

  • On the Sources tab, click Add Source. Double-click the CsContact business object listed in the window that appears, or select it and click OK.
  • On the Filters tab, select Full Name from the Property select box in the first row, then click + to ensure the filter is added to the query. In the second row, select Name (Last, First) from the Property select box, enter "@url:LastName" (with the double quotes) in the corresponding Value box, and then click + in that row.
  • On the Display tab, you can choose which pieces of information you want available in the query. The only one with which we’re concerned for this tutorial is Full Name, which is checked by default.
  • On the Sorting tab, choose Name (Last, First) from the Property select box, then click + to ensure the sorting is added to the IQA.
  • Finally, if you want everyone to be able to see the results even if they’re not logged in to the website, select Share (Everyone) on the Security tab.

Click Save. Your IQA query is complete!

Displaying IQA results on a webpage

iMIS offers some iParts such as Query Menu that do a fine job of displaying results so long as you don’t need to apply special formatting or manipulate it in some way. For this tutorial, I’m not going to use those iParts, but will instead demonstrate how to use HTML and JavaScript including jQuery which is part of the iMIS website in order to display results.

On the iMIS staff site, navigate to RiSE > Page Builder > Manage content, navigate to a folder, and choose New > Website Content. Enter a Title and Publish file name, then click Add content and choose the Content HTML iPart. Select the HTML tab and then enter the following HTML:

<div id="imis-json-results" class="json-results">
    <p id="imis-json-results-loading" class="loading-results">Loading results…</p>
</div>

This is the container into which we’ll load the results retrieved from our API call.

Next, enter the following JavaScript:

<script type="text/javascript">
    // we’ll display these messages only if results can’t be displayed
    var msgNoResults = "No results found.";
    var msgAjaxError = "The results failed to load. Please try again later."
    
    // create unordered list for insertion into DIV#imis-json-results
    var resultList = document.createElement("ul");
    resultList.id = "imis-results";
    
    // set URL for API call to retrieve names
    // note the QueryName parameter includes folder name and IQA query name
    // the LastName parameter is used due to the "@url:LastName" that we entered while building our IQA query
    // the Limit parameter defines the maximum number of results to be returned
    var apiURL = "/api/IQA?QueryName=$/MyTests/LastName-Test&LastName=Smith&Limit=500";
    
    // make ajax call to API to retrieve names
    jQuery.ajax(apiURL, {
        type: "GET",
        contentType: "application/json",
        headers: {
        
            // this line retrieves the __RequestVerificationToken value that iMIS automatically populates onto the webpage, eliminating the need for separate authentication
            RequestVerificationToken: document.getElementById("__RequestVerificationToken").value
        },
        success: function(data) {
        
            // if you want to see raw data returned by API, uncomment following line and view results in web browser’s developer console
            // console.log(data);
            
            // display results if any were found
            if (data["TotalCount"] > 0) {
            
                // loop through values in JSON string
                for (var i = 0; i < data["Items"]["$values"].length; i++) {
                    var fullName = "";
                    
                    // get properties for specific record, then loop through them
                    var record = data["Items"]["$values"][i]["Properties"]["$values"];
                    for (var j = 0; j < record.length; j++) {
                        if (record[j].Name == "FullName") {
                            fullName = record[j].Value;
                        }
                    }
                    
                   // create list item, list item to unordered list created earlier
                   var resultItem = document.createElement("li");
                   resultItem.innerHTML = fullName;
                   resultList.appendChild(resultItem);
               }
           }
           
           // eliminate loading message
           var loadingElem = document.getElementById("imis-json-results-loading");
           loadingElem.parentElement.removeChild(loadingElem);
           
           // append results or message indicating no results were found to DIV#imis-json-results
           if (data["TotalCount"] > 0) {
                document.getElementById("imis-json-results").appendChild(resultList);
            }
            else {
                var noResultsP = document.createElement("p");
                noResultsP.innerHTML = msgNoResults;
                document.getElementById("imis-json-results").appendChild(noResultsP);
            }
        },
        error: function() {
            // eliminate loading message
            var loadingElem = document.getElementById("imis-json-results-loading");
            loadingElem.parentElement.removeChild(loadingElem);
            
            // append ajax error message to DIV#imis-json-results
            var ajaxErrorP = document.createElement("p");
            ajaxErrorP.innerHTML = msgAjaxError;
            document.getElementById("imis-json-results").appendChild(ajaxErrorP);
        }
    });
</script>

Again, the Query Menu iPart may be sufficient for displaying very basic lists, but for more involved projects, this should at least give you a starting point for getting data out of your iMIS database using the API.

Diagnosing a bad laptop hard drive

Last week, my father-in-law asked me to take a look at his Dell Inspiron laptop running Windows 10. He said he had left it powered on but not actively used it for a while, and when he picked it up to try to do something, it didn’t boot up normally, but instead entered Windows Recovery.

In hopes of an easy fix, I began my troubleshooting by simply choosing the Continue option to exit and continue to Windows 10, but the laptop after a long delay ended up back in Windows Recovery again. That time around, I selected the Troubleshoot option. Selecting System Restore revealed no restoration points, so I next tried selecting System Repair, but was shortly informed that the system could not be repaired without any particular reason being given.

At that point, my hopes of a speedy resolution were evaporating pretty quickly, but I still wanted to try to determine what was wrong. I selected the Command Prompt option so I could try taking a look at the file system; then, in the command prompt window that opened, I entered c:. After another long pause, the following message was displayed:

The volume does not contain a recognized file system.
Please make sure that all required file system drivers are loaded and that the volume is not corrupted.

Well, that didn’t sound good! No recognized file system detected? My gut feeling was that the hard drive was dying, but since my father-in-law said he didn’t have any files of notes on the computer, attempting to reinstall Windows seemed worthwhile.

I entered exit to get out of the command prompt, then inserted a Windows 10 installation disc into the laptop’s optical drive, selected the Use a device option, and chose EFI DVD/CDROM from the list of devices. After the laptop rebooted, when I was prompted to press any key to boot from CD or DVD, I pressed Enter, and after a period of time, Windows Setup loaded.

With the appropriate language, time and currency format, and keyboard or input method selected, I clicked the Next button, then clicked Install now. I accepted the license terms and clicked Next, selected Custom: Install Windows only (advanced) option, and then selected the 452 GB partition that was listed as Primary partition type (rather than System, Recovery, etc.).

When I selected that partition, Windows Setup displayed a message indicating Windows couldn’t be installed on the partition, so I clicked for details, at which point Windows Setup reported the following:

Windows cannot be installed to this disk. The disk may fail soon. If other hard disks are available, install Windows to another location.

That certainly eliminated any lingering doubts that I may have had about the hard drive being the problem: Windows Setup wouldn’t even attempt to install Windows 10 to the existing hard drive!

The laptop’s existing hard drive is not especially old, but it is a super-slow 500 GB Toshiba 5400 RPM drive. I’ve ordered a 240 GB Seagate BarraCuda SSD to replace it; although it’s only half the size of the original drive, it should run rings around the original, and for what my father-in-law uses the computer for—web browsing and email—it will be more than adequate.