Crafting HTTP Requests for the AppFxWebService.asmx

Infinity's Web API is fairly well documented, especially if you're going to be referencing the web service as a web reference in a .NET (Visual Studio), PowerShell, or Java project. This content attempts to explain how HTTP requests to AppFxWebService.asmx can be manually crafted for use and/or testing with tools like Fiddler.

Choosing an endpoint

To begin using the API, you must first choose what functionality you want to use. This endpoint will determine what data you will send, and what you can expect to receive in response. This document does not describe each endpoint in detail, but rather how to find the endpoints and explore them.

The Endpoint Reference Page

The Endpoint Reference page is a very useful tool for Infinity systems (such as Blackbaud CRM or ResearchPoint) that will allow you to see functionality exposed to you via the Web API. There are a couple ways to access the Endpoint Reference page, but not all of them may be applicable depending on how you access your Infinity product. If, when accessing your Infinity product you come to the splash or "Candy Store" page with many choices of how to continue, including: Web Shell, Web dashboard, Mobilize, Utilities,Endpoints, and Browser, then finding your endpoints is simple. All you have to do is click on the Endpoints link and it will take you to the Endpoint Reference page.

If you do not have the above landing page available to you, you can still access it. From inside your Infinity application, copy the entire URL up to `/webui/...`

For example, if your starting page URL after logging in is http://localhost/bbappfx/webui/webshellpage.aspx?databasename=BBInfinity you should copy http://localhost/bbappfx.

Once you have this base URL, add /endpointhelp.aspx?databasename=BBInfinity to the end of it. The resulting URL, http://localhost/bbappfx/endpointhelp.aspx?databasename=BBInfinity, will take you to the Endpoint Reference page.

Once on the page, there are many things to explore, but if you're reading this document the one you probably care about is Blackbaud AppFx Web Service.

The AppFxWebService documentation lists the available operations. Your integration software can use these operations to get things done in Blackbaud CRM or ResearchPoint..

AppFxWebService.asmx Endpoint Description

Blackbaud’s Infinity Web Services APIs can be used by custom third party software to interact with individual features via HTTP. Every application feature is accessible via standard web services accessible from any programming tool that utilizes XML, HTTP, and SOAP.This page describes the multitudes of operations that are supported by the Web API. It's up to you to scan the list to find an operation that might suite your needs, but for the rest of the document we will look at SimpleDataListLoad.

The table below provides an abbreviated guide to some of the most essential operations for performing CRUD type activities (Create, Read, Update, and Delete), along with other operations like record searches and listing records and look-up code table values. These operations typically require the ID of the feature. For more information on locating and securing Infinity features, see Add Features to Infinity System Role.

Operation Type Operation Description
Create DataFormSave Saves (insert or update) the data for a record defined by the supplied (Data) Form ID. Call DataFormSave to save an update provided by an Edit Data Form or to save an insert by an Add Data Form.
Create CodeTableEntryAdd Creates a new CodeTable entry item.
Read DataFormLoad Gets the data (for edit or view) for a record defined by the supplied Form ID.Call DataFormLoad to retrieve the data pulled by the load implementation of an Edit Data Form or View Data Form.
Read CodeTableEntryGetData Gets the data for an individual code table entry item
Update DataFormSave Saves (insert or update) the data for a record defined by the supplied Form ID. Call DataFormSave to save an update provided by an Edit Data Form or to save an insert by an Add Data Form.
Update CodeTableEntryUpdate Updates a CodeTable entry description and active status
Update RecordOperationPerform Performs the operation on a record as defined by the supplied Record Operation name or ID
Delete RecordOperationPerform Performs the operation on a record as defined by the supplied Record Operation name or ID
Delete CodeTableEntryDelete Deletes a CodeTable entry item
List DataListLoad Loads the data for a datalist given the ID or Name and any parameters. Use DataListLoadMore to load a rows from a previous call to DataListLoad which had more TotalAvailableRows than the TotalRequestRows in the reply. Used to support paging of data in large result sets.
List SimpleDataListLoad Gets the data for a simpledatalist given the ID or Name and any parameters
List CodeTableEntryGetList Returns the list of table entries for the given code table.
Search SearchListLoad Gets the data for a search list given the search list ID or Name and any filters

Figure: Essential AppFxWebService.asmx CRUD Operations

When you click on an operation description, you will be taken to a page with lots of XML. This is a helpful description of the SOAP requests and responses that the API consumes and produces. Specifications for SOAP 1.1 and SOAP 1.2 are shown for each endpoint. The first XML document shown is the SOAP request, which you will need to craft. The second XML document shown is the SOAP response, which you will have to handle.

Although we all wish that this operation description page was the end of the story, there is a bit more to be done before a request can be successfully sent.

Headers

Most of the headers that you'll need are described in the Endpoint description page above the SOAP request example. For example:

POST /bbappfx.dev.firebird/AppFxWebService.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "Blackbaud.AppFx.WebService.API.1/SimpleDataListLoad"

are all but one of the headers you will need to make a successful SOAP 1.1 POST request. The one that is missing is the `Authorization` header.

Authentication

Since you must be logged in to use the application, the API is only available to authenticated users, and that includes your application. Infinity supports a few types of authentication, including Basic and NTLM. For more information on authorization, see Authentication and Authorization.

Basic Authentication

Basic authentication is simple.

  1. Create a string username:password from your Infinity login credentials or create a username PAT for a proxy user.
  2. Base64 encode that string.

Take that string and add the following header

Authorization: Basic YOURBASE64ENCODEDAUTHENTICATIONSTRING

And that's it! Your request will be authenticated now.

NTLM Authenticaion

Describing how to manually compute an NTLM signature and use it in this context is currently beyond the scope of this document. It is an option, though, if you cannot use Basic authentication.

Most of the SOAP request body is perfectly described by the endpoint description page. You can copy-paste and modify the sample request and be 90% of the way to a perfectly functioning request. However, there are two bits of information that you will need to add to the request to make it work correctly.

ClientAppInfo

One thing that the sample request does not describe is an element that must be included called `ClientAppInfo`. Its format is as follows:

<ClientAppInfo 
        REDatabaseToUse="YOUR DATABASE IDENTIFIER/KEY" 
        ClientAppName="THE NAME OF YOUR REQUESTING APPLICATION" 
        TimeOutSeconds="THE NUMBER OF SECONDS BEFORE A REQUEST TIMES OUT"
        />

REDatabaseToUse

Your database identifier/key will vary. For this example, I am using 'BBInfinity'. Your database key will most likely vary. Read below.

This is the identifier of the database your Infinity product uses. This is also known as the 'database key'. You can find this value in the URL when you are using the product. For example, on the landing page of Blackbaud CRM/Research Point the URL is

http://localhost/.../webshellpage.aspx?databasename=BBInfinity

and we can see that the database identifier is `BBInfinity`.

ClientAppName

This is a name that you should come up with to identify your application to the API. It should be unique and specific to your application. The Infinity application can use this application name for auditing purposes when additions, edits, or deletes occur to the data within the database tables.

TimeOutSeconds

The number of seconds before the request times out. I will use 120 seconds for this setting.

There are other attributes within the ClientAppInfo element. A brief description is provided below:

RunAsUserID

Optional. This attribute is not relevant for API Development and should be omitted. Within the Infinity user interface, this attribute is necessary to support system administrators who which to verify security for specific users.

SessionKey

Optional. The value for this attribute can be obtained via a prior call to the SessionStart operation on the AppFxWebService.asmx. SessionStart returns a session key to be used to main client state between calls to the service. Using this setting provides a slight performance benefit as some internal data is cached for the user during the session.

SOAP gotchas

Because Infinity's web service uses SOAP, it is important to be aware of some of the intricacies of SOAP that might not be immediately obvious and are not present in the sample request. It may be beneficial to have the SOAP standard definition on hand.

Strict typing of ambiguous data

In SOAP, data values that have an ambiguous type must have their type declared in the request so they can be properly serialized. With Infinity applications, this mostly only applies to the `Values` elements in a request's `Parameters`. The Rules for Encoding Types in XML can help to describe what you must do, and a list of included datatypes in XML is also useful when typing request parameters.

A complete SimpleDataListLoad SOAP 1.2 request

Non-functional, with parameters

Here is an example of a complete SimpleDataListLoad, with parameters. Sending this request, while valid, will probably not return meaningful results.

Headers:

Host: localhost
Content-Type: application/soap+xml; charset=utf-8
Content-Length: LENGTH
Authorization: Basic 11111111111111111111

Request Body:

<?xml version="1.0" encoding="utf-8"?>
    <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
      <soap12:Body>
        <SimpleDataListLoadRequest xmlns="Blackbaud.AppFx.WebService.API.1">
          <ClientAppInfo REDatabaseToUse="BBInfinity" ClientAppName="Test App" TimeOutSeconds="100" RunAsUserID="00000000-0000-0000-0000-000000000000" xmlns="Blackbaud.AppFx.WebService.API.1" />
          <DataListID>1d5fc077-0049-483f-a65c-0c17d57476a4</DataListID>
          <DataListName>Scheduled Programs By Date Simple List</DataListName>
          <Parameters>
            <Values xmlns="bb_appfx_dataforms">
              <fv ID="DATE">
                <Value xsi:type="xsd:string">08/21/2013</Value>
                <ValueTranslation>08/21/2013</ValueTranslation>
              </fv>
              <fv ID="EVENTDATE">
                <Value xsi:type="xsd:string">08/22/2013</Value>
                <ValueTranslation>08/22/2013</ValueTranslation>
              </fv>
              <fv ID="SALESMETHODTYPECODE">
                <Value xsi:type="xsd:int">0</Value>
                <ValueTranslation>0</ValueTranslation>
              </fv>
            </Values>
          </Parameters>
          <SecurityContext>
            <SecurityFeatureID>1d5fc077-0049-483f-a65c-0c17d57476a4</SecurityFeatureID>
            <SecurityFeatureType>SimpleDataList</SecurityFeatureType>
            <RecordContext>
              <RecordID/>
              <RecordType/>
            </RecordContext>
            <AttributeContext>
              <AttributeCategoryID/>
            </AttributeContext>
          </SecurityContext>
        </SimpleDataListLoadRequest>
      </soap12:Body>
    </soap12:Envelope>

Functional, without parameters

This request has no parameters, but once adjusted to use values specific to your Infinity product, will return meaningful results in a response for you to examine.

Headers:

Host: localhost
Content-Type: application/soap+xml; charset=utf-8
Content-Length: LENGTH
Authorization: Basic 11111111111111111111

Request Body:

<?xml version="1.0" encoding="utf-8"?>
    <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
      <soap12:Body>
        <SimpleDataListLoadRequest xmlns="Blackbaud.AppFx.WebService.API.1">
          <ClientAppInfo REDatabaseToUse="BBInfinity" ClientAppName="Test App" TimeOutSeconds="100" RunAsUserID="00000000-0000-0000-0000-000000000000" xmlns="Blackbaud.AppFx.WebService.API.1" />
          <DataListID>ea2c8565-85cb-433c-94f8-229e079f0445</DataListID>
          <DataListName>Record Types</DataListName>
          <Parameters/>
          <SecurityContext>
            <SecurityFeatureID>ea2c8565-85cb-433c-94f8-229e079f0445</SecurityFeatureID>
            <SecurityFeatureType>SimpleDataList</SecurityFeatureType>
            <RecordContext>
              <RecordID/>
              <RecordType/>
            </RecordContext>
            <AttributeContext>
              <AttributeCategoryID/>
            </AttributeContext>
          </SecurityContext>
        </SimpleDataListLoadRequest>
      </soap12:Body>
    </soap12:Envelope>
 

Tip: Those new to Infinity API development or those who want more details on the underlying concepts need to check out our step by step tutorial: Using Fiddler to Compose HTTP Requests