We have clients using both Xojo and FileMaker, so we made the MBS Xojo FMAPI Plugin to connect them both. Write a Xojo application to connect to the FileMaker server using our FMDataMBS class and query, update or create records.
With the FMDataMBS class, you can integrate FileMaker data directly into your Xojo applications—without relying on manual exports, ODBC bridges, or clunky middle layers. This plugin allows you to perform full CRUD operations (Create, Read, Update, Delete) over HTTPS using the FileMaker Data API, all via simple Xojo code and powered internally by the proven CURL library.
This is ideal for:
- Creating desktop or web frontends in Xojo that interact in real-time with your FileMaker server.
- Automating background tasks or server-side scripts using Xojo that manipulate FileMaker data.
- Extending FileMaker solutions with cross-platform apps, IoT, or REST integrations using Xojo’s flexibility.
Connect
Let us connect to a server. For this we need the domain name or IP of the server, the name of the database file, the username and password. The account referenced must have the fmrest privilege allowed.
In our sample Xojo project we have a login window with various fields to enter the credentials. We login and either get response code 200 for success or other codes for various errors. Take a look:
// new connection to FileMaker Server
Var d As New FMDataMBS
'd.Version = "v2" // default is vLatest
d.Database = DatabaseNameField.Text.Trim
d.Password = PasswordField.Text.Trim
d.Username = UserNameField.Text.Trim
d.Server = ServerField.Text.trim
Var r As FMResponseMBS = d.Login
// connection worked?
If r.CURLErrorCode <> 0 Then
ShowLog r
MsgBox r.CURLErrorMessage
Return
End If
Select Case r.ResponseCode
Case 200
Var m As New MainWindow
m.connection = d
m.response = r
m.UpdateResponse
Case 401
ShowLog r
MsgBox "Invalid credentials."
else
ShowLog r
MsgBox "ResponseCode: "+Str(r.ResponseCode)
End Select
Query version
After you connect, you can do various calls to the API. For example you may query the version of the server by asking for product information.
response = connection.ProductInfo
// {"response":{"productInfo":{"name":"FileMaker Data API Engine","buildDate":"07/28/2020","version":"19.1.1.54",
"dateFormat":"MM/dd/yyyy","timeFormat":"HH:mm:ss","timeStampFormat":"MM/dd/yyyy HH:mm:ss"}},
"messages":[{"code":"0","message":"OK"}]}
If response.ErrorCode = 0 Then
// show version number in dialog box
Var result As Dictionary = response.Result
Var productInfo As Dictionary = result.value("productInfo")
If productInfo <> Nil Then
Var version As String = productInfo.Value("version")
MsgBox version
End If
End If
Query database names
Next you may ask for the database names and show them in a dialog:
response = connection.DatabaseNames
// {"response":{"databases":[{"name":"Contacts"}]},
"messages":[{"code":"0","message":"OK"}]}
If response.ErrorCode = 0 Then
// show names of databases in dialog box
Var result As Dictionary = response.Result
Var Names() as string
Var databases() As Variant = result.Value("databases")
For Each entry As Dictionary In databases
Var name As String = entry.Value("name")
Names.Append name
Next
MsgBox "Database Names" + EndOfLine + EndOfLine + Join(names, EndOfLine)
End If
Query layout names
Since you need layouts for accessing records, you may need to ask for the layout names with the LayoutNames method:
response = connection.LayoutNames
// {"response":{"layouts":[{"name":"Contacts","table":""},{"name":"Contacts Details","table":""}]},
"messages":[{"code":"0","message":"OK"}]}
If response.ErrorCode = 0 Then
LayoutMenu.DeleteAllRows
Var result As Dictionary = response.Result
Var layouts() As Variant = result.Value("layouts")
Var Names() As String
WalkLayouts Layouts, Names
'MsgBox "Layout Names" + EndOfLine + EndOfLine + Join(names, EndOfLine)
End If
Query script names
You may also query script names the same way with the ScriptNames method.
Since you have the layout names, you can use LayoutMetadata() to query metadata for each layout. This contains the list of fields on the layout. This let's you know what fields you may get when you load records using this layout.
// which layout to use
connection.Layout = LayoutMenu.Text
response = connection.LayoutMetadata("")
// {"response":{"fieldMetaData":[{"name":"SomeText","type":"normal","displayType":"editText","result":"text",
"global":false,"autoEnter":false,"fourDigitYear":false,"maxRepeat":1,"maxCharacters":0,"notEmpty":false,
"numeric":false,"timeOfDay":false,"repetitionStart":1,"repetitionEnd":1},...
If response.ErrorCode = 0 Then
Var result As Dictionary = response.Result
Var fields() As Variant = result.value("fieldMetaData")
Var Names() As String
For Each entry As Dictionary In fields
Var name As String = entry.Value("name")
Names.Append name
Next
MsgBox "Field Names" + EndOfLine + EndOfLine + Join(names, EndOfLine)
End If
Query records
Next we can use GetRecords to query the records based on the layout. If needed, you can set offset and limit properties to only query some records. To get just one record, you can use GetRecord() method.
// which layout to use
connection.Layout = LayoutMenu.Text
Var request As New FMRequestMBS
request.offset = 1
request.limit = 100
response = connection.GetRecords(request)
Execute scripts
You can trigger a script by using ExecuteScript method. Optionally you can pass a script parameter.
connection.Layout = LayoutMenu.text
Var scriptName As String = ScriptMenu.Text
response = connection.ExecuteScript(scriptName, "TestParam")
The result will contain the script result and/or an error code.
Create a record
To duplicate a record, you can use DuplicateRecord method and pass a record id. Samed for DeleteRecord to delete a record. To set global fields, you may use SetGlobalFields method and pass a dictionary with field names and values.
When you like to create a new record, you an collect field values in a dictionary. Then pass that to the request as field data and call CreateRecord method. Or for editing the records, you use EditRecord method.
// which layout to use
connection.Layout = LayoutMenu.Text
Var request As New FMRequestMBS
Var fieldData as new Dictionary
fieldData.Value("First Name") = "Joe"
fieldData.Value("Last Name") = "Smith"
fieldData.Value("Title") = "Mr."
fieldData.Value("Company") = "Test Ltd."
fieldData.Value("Website") = "https://www.mbsplugins.de/filemaker"
request.fieldData = fieldData
response = connection.CreateRecord(request)
Find records
To find records, you 'd use the FindRecords method (see documentation) and pass the search criteria as JSON.
// which layout to use
connection.Layout = LayoutMenu.Text
Var request As New FMRequestMBS
// just query first 100 records
request.offset = 1
request.limit = 100
// e.g. [{"Name" : "=Test"}]
response = connection.FindRecords(request, queryField.Text.Trim)
You can continue and use more methods to implement your Xojo application. This may be a web application, an iOS application or a desktop one. You may be able to write a nice utility to do something in your business and talk tot he
Please try and let us know if you miss something.