BBCRM SDK – Spec Development

If you’re starting out customizing BBCRM, or even if you’ve been doing so for several years, it’s not unusual to run into frustrations that you feel should be solvable, but that you can’t find a ready answer for among the excellent BBCRM customization resources already out there.  If you’re not already aware, the website provides a great technical reference along with a reasonably well-trafficked Q&A site.  Even so, sometimes it’s hard to find the answer you’re looking for.

This blog introduces a series of posts with practical advice and guidance based on real-world customization development and several years of questions from BBCRM SDK trainings I’ve conducted.  Please feel free to contact me if I can clarify or explain any of this–or if you’ve found alternative ways to address the topic.


  • CRM includes 2 database roles BBAPPFXSERVICEROLE and BBAPPFXREPORTROLE used by the web service and the reporting service respectively.
  • Objects used within SP specs are automatically permissioned correctly for BBAPPFXSERVICEROLE. However, if you create write a CLR spec that references external objects you will need to list them in the CLR spec to ensure they are permissioned correctly:
  • Objects defined within report specs are generally permissioned correctly for BBAPPFXREPORTROLE if the SQL is defined within the stored procedure. If it is referenced externally the report spec will need to list the object(s) to ensure they are updated with the correct permissions:

 Refresh Shell Navigation

  • If you load or modify a custom functional area or task within a functional area and the change is not appearing, you can use “Refresh Shell Navigation” within the “Catalog Browser” to flush the cached Web Shell navigation (or you can use “iisreset” to flush everything):

Data Form Instance IDs vs Data Form IDs

  • Most of the time you will reference data forms from other specs using the data form’s “DataFormInstanceID”:
  • One major exception to this is batch specs—these use the “ID” attribute:
  • When in doubt, use Intellisense:

Author Attribute

  • It is recommended that you use a common “Author” attribute for your organization’s customizations (as opposed to the default value of the current user’s login). This allows you to identify all of your organization’s customizations via the author attribute:
  • You can set this value after SDK installation from the registry under HKEY_CURRENT_USER\Software\Blackbaud\AppFx\SDK\Installer.

Package Specs

  • Use package specs to group all of your customizations together in one item that can be loaded via “Load Spec”.
  • The ordering of your specs matters, make sure to pay attention to dependencies between specs to ensure items are loaded before other specs that depend on them (e.g. data list is loaded before a page that references the data list).
  • Make extra sure to get the CatalogAssembly and CatalogItem names completely correct—including casing. The best way to do this is to create a “template” item within your package spec with everything filled in except the spec name—e.g.
  • Then when filling it in, copy/paste the spec name onto the end of the “CatalogItem” to ensure you get the spelling and casing exactly correct.
  • To find items that might not have loaded from the package spec, filter “Catalog Browser” down to the “Author” for your organization and check the “Exclude loaded items” checkbox—items appearing in the data list might indicate items that were supposed to be loaded via the package spec but weren’t for some reason (typically misspelling or incorrect case):

ID Attributes and GUIDs

  • When copying/pasting specs, make sure to update the “ID” attributes in your pasted version. If you leave the original ID attributes you might get unexpected behavior, such as the newly copied version of the spec overriding the originally loaded version of the spec due to the CRM framework believing they are the same spec.
  • You can create new GUIDs from within Visual Studio by going to “Tools -> Create Guid”, use the “Registry Format” (option 4) and remove the leading and trailing brackets from the generated GUID.

Using a Selection as a Parameter

  • To use a selection as a parameter within CRM, create a form field similar to the following:
  • In the “FormFieldOverrides” element, set the “DefaultValueText” to the record type for the type of selection your form field expects (e.g. “Constituent” to limit the selections to constituent selections).
  • In your stored procedure, you can use this selection like this: 

Creating a Data Form Add-In

To add a data form add-in (see reference docs on BBDevNetwork for details on Add-Ins), use the following steps as a guideline:

  1. Add a new item to your Visual Studio project of type “Data Form AddIn Spec”:
  2. The first time you create an add-in in a given environment you will need to configure the Add-In plugin in Visual Studio, use values similar to the ones in the screen-shot below (updated to reflect your local environment’s settings):
  3. You will be prompted with a “Data Form Instance Search” screen to select the data form you wish to extend. If you don’t already know the data form’s name, you can find it by viewing the target data form’s spec XML in the application via design mode.  In the below screen-shot I’ve selected the “Individual, Spouse, Business Add Form”:
  4. The .NET class should open for editing. Note that the add-in has an XML spec of its own (see below screen-cap).  If you created the Add-In in a UI model project, you may want to move the XML spec into a catalog project.  Either way, make sure to include a reference to the XML spec in a package file, whether the XML spec lives in a UI model or catalog project. 

Creating a Data Form Extension

To create a data form extension (see reference docs on BBDevNetwork for additional detail on data form extensions), use the following steps as a guideline:

  1. Create an add, edit, or view data form as you normally would in Visual Studio.
    1. The extension will require a context record of the same type as the data form you are extending. For example, if you are extending the “Individual, Spouse, Business Add Form”, you can see via the “Administration -> Features -> Data Form Search” view of the data form that it adds a record of type “Constituent”:
  1. Data form extensions are the dame as regular data form specs except for an additional “<DataFormExtension>” tag at the end of the spec. This tag will indicate the form being extended (use the “DataFormInstanceID” attribute from the target form).  In the below screen-shot, the data form being edited is extending the “Individual, Spouse, Business Add Form”: 
  1. Use the “RenderStyle” attribute to indicate where the data form should be rendered.
    1. “Tab” indicates on a new tab, for example:
    2. “AfterParent” indicates after the parent data form record:

Share this post