Extending SuperEmailClerk.NET to call your own APIs

 SuperEmailClerk.NET (SEC.NET), when running in API Invoke mode, will invoke requested APIs and return the results in a reply email. SEC.NET can be configured to execute API toolkits purchased from Dovetail Software, such as the ClearSupport toolkit, or custom-built APIs.

This post will walk through creating a custom API in .NET that can be invoked by SEC.NET.

The example will be a CreateAddress method. Even though there is an existing CreateAddress method in our Interfaces toolkit, we chose this as an example because it illustrates how to use the AdditionalFields property of the Toolkit Setup objects, which allows you to re-use our toolkits, but with an unlimited number of additional fields being set.

Overview of the steps involved:

  • Create a SecApiInvokeExample class with a CreateAddress method
  • Create a SecApiInvokeExampleTests class for our tests
  • Create the tags and subtags and add these to the tags.xml file
  • Copy the DLL to the SEC.NET directory
  • Test

1. Develop the tests and the code.

We’re using TestDriven.NET for running our tests. This allows us to prove that our code works before we even get near SEC.NET itself.

The important things:

  • There must be an Initialize method that takes an fcApplication and an fcSession object.
  • We’ve added the new CreateAddress method that returns an integer return code (0 means success, anything else means failure)
  • We’ve added AddressObjid as a public property so that we can have SEC.NET send this data back to the email sender.

1.1 SecApiInvokeExample.cs

using FChoice.Toolkits.Clarify.Interfaces;
using FChoice.Toolkits.Clarify;
using FChoice.Foundation.Clarify.Compatibility;

namespace SecApiInvokeExample
    public class SecApiInvokeExample
        private FCApplication _fcApplication;
        private FCSession _fcSession;
        private int _addressObjid;

        public FCApplication fcApplication
            get { return _fcApplication; }

        public FCSession fcSession
            get { return _fcSession; }

        public int AddressObjid
            get { return _addressObjid; }

        public void Initialize(FCApplication fcApplication, FCSession fcSession)
            _fcApplication = fcApplication;
            _fcSession = fcSession;

        public int CreateAddress(string address, string address2, string city, string state, string zipcode, string country,
 string timeZone)
            InterfacesToolkit interToolkit = new InterfacesToolkit(_fcApplication, _fcSession);
            CreateAddressSetup createAddressSetup = new CreateAddressSetup(address, city, state, zipcode, country, timeZone);
            createAddressSetup.AdditionalFields.Append("address_2", AdditionalFieldType.String, address2);

            ToolkitResult createAddressResult = interToolkit.CreateAddress(createAddressSetup);
            _addressObjid = createAddressResult.Objid;

            return createAddressResult.ReturnCode;


1.2 SecApiInvokeExampleTests.cs

using System;
using NUnit.Framework;
using FChoice.Foundation.Clarify;
using FChoice.Foundation.Clarify.Compatibility;
using System.Collections.Specialized;
using FChoice.Toolkits.Clarify.Interfaces;

namespace SecApiInvokeExample.Test
    public class SecApiInvokeExampleTests
        private FCApplication _fcApplication;
        private FCSession _fcSession;

        public void TestFixtureSetup()
            NameValueCollection config = new NameValueCollection();
            config.Add("fchoice.connectionstring","Data Source=localhost;Initial Catalog=fcclient;uid=sa;pwd=sa;");
            config.Add("fchoice.disableloginfromfcapp", "false");

            _fcApplication = new FCApplication();

        public void Setup()
            _fcSession = _fcApplication.CreateSession(null);

        public void TearDown()

        public void Initialize_should_set_the_fcApplication_and_fcSession()
            SecApiInvokeExample secApiInvokeExample = new SecApiInvokeExample();
            secApiInvokeExample.Initialize(_fcApplication, _fcSession);

            Assert.AreEqual(_fcApplication, secApiInvokeExample.fcApplication);
            Assert.AreEqual(_fcSession, secApiInvokeExample.fcSession);

        public void CreateAddress_should_return_zero_indicating_success()
            SecApiInvokeExample secApiInvokeExample = new SecApiInvokeExample();
            secApiInvokeExample.Initialize(_fcApplication, _fcSession);

            string address ="address";
            string address2="address2";
            string city="city";
            string state="TX";
            string country="USA";
            string timeZone="CST";
            string zipcode="zipcode";

            int returnCode = secApiInvokeExample.CreateAddress(address, address2, city, state, zipcode, country, timeZone);

            Assert.AreEqual(0, returnCode);

2. Create the tag and subtags XML

When operating in API Invoke mode, the tags.xml file is used to define how APIs are processed, including:

  • Which APIs are enabled
  • Tag and subtag names
  • Which subtags are required
  • Which data gets sent back to the sender
  • Subtag default data
  • etc.

We’ll add the following to tags.xml:

  object="SecApiInvokeExample.SecApiInvokeExample, SecApiInvokeExample"
 inSubject="true" inBody="false" isActive="true">


3. Copy the DLL to the SEC.NET directory

In my environment, I copied SecApiInvokeExample.dll to C:Program FilesFirst Choice SoftwareFirst Choice Super Email Clerk.NET.

My ever-so-helpful programming pair Kevin Miller added a post-build event task in Visual Studio so that this step is done automatically:

copy $(TargetPath) "C:Program FilesFirst Choice SoftwareFirst Choice Super Email Clerk.NET"

4. Test using SEC.NET and an actual email

 I sent the following email to my SEC Test address:

Subject: createAddress


address: 123 main street

address2: suite 100

city: austin
state: TX

country: USA

zipcode: 12345


And the following was returned:

Subject: RE: createAddress


API Result

This message is in reply to your createAddress api request.

The operation completed successfully.

The return value was:

Operation Results
addressObjid: 268435564


Tips/Lessons Learned:

  • The API must return an integer to indicate success/failure (0=success). You can add additional properties for returning other data.
  • There must be an Initialize method that takes two parameters: fcApplication and fcSession
  • You do not need a constructor in your custom class. Notice that the SecApiInvokeExample class doesn’t have one. It’s OK to have one, it’s just not required.
  • When adding a reference to the fcSDK, be sure to use the fcsdk.dll that is shipped with SEC.NET (Typically C:Program FilesFirst Choice SoftwareFirst Choice Super Email Clerk.NETfcsdk.dll). Otherwise, you may end up with a very unhelpful (at least to me) error:
    Object of type ‘FChoice.Foundation.Clarify.Compatibility.FCApplication’ cannot be converted to type ‘FChoice.Foundation.Clarify.Compatibility.FCApplication’.
  • The method name and parameter names are case sensitive. The case of the the methodName and paramName in the tags.xml must be the same case as the actual code.
  • The order of the subtags in tags.xml muct be in the same order as the API parameters.
  • We created our class in Visual Studio 2005 (.NET 2.0). However, SEC.NET is based on .NET 1.1. To allow for this, we added a startup section to the SecService.exe.config file:

       <supportedRuntime version="v2.0.50727" />
       <supportedRuntime version="v1.1.4322" />


The current layout of our blog site caused some of the code to be chopped off when viewing this post on the website.
You can download a zip file containing the class files and xml here: