Repository navigation
platform sdk custom fields
Custom fields are application-defined attributes attached to supported Security Center entities, such as cardholders, areas, and doors. Access custom field definitions and values through the ICustomFieldService exposed on the system configuration entity.
The examples on this page are partial and assume that engine is a connected Engine instance and that customFieldGuid, ownerGuid, and cardholder identify existing objects:
SystemConfiguration systemConfig = engine.GetEntity<SystemConfiguration>(
SystemConfiguration.SystemConfigurationGuid);
ICustomFieldService service = systemConfig.CustomFieldService;Use ICustomFieldService with the target entity's Guid, or call GetCustomFields and SetCustomField on an Entity. The entity methods target that entity's own Guid, so both approaches provide the same read and write operations.
Each custom field is described by a CustomField object. Enumerate every defined field through service.CustomFields, or fetch one by identifier, by name and entity type, or by name, entity type, and owner:
IReadOnlyList<CustomField> all = service.CustomFields;
CustomField byId = service.GetCustomField(customFieldGuid);
CustomField byName = service.GetCustomField(
"Department", EntityType.Cardholder);
CustomField byOwner = service.GetCustomField(
"Department", EntityType.Cardholder, ownerGuid);CustomField identifies the definition through Guid, Name, EntityType, ValueType, and Owner. It also exposes Mandatory, Unique, IsEncrypted, DefaultValue, GroupName, GroupPriority, and ShowInReports. You can set Name, GroupName, GroupPriority, IsEncrypted, and DefaultValue. The remaining properties are read-only after the field is built.
The CustomFieldValueType enum selects the value type used by a custom field:
| Member | Value | Use for |
|---|---|---|
Text |
0 | String values. |
Numeric |
1 | Integer values. |
Boolean |
2 | True or false. |
DateTime |
3 | Date and time values. |
Decimal |
4 | Decimal values. |
Image |
5 | Image values; the boxed value must be a System.Drawing.Image. |
Entity |
6 | A reference to another entity, stored as a Guid. |
Date |
7 | Date-only values. |
Use service.CreateCustomFieldBuilder() and the fluent setters, and then call Build() to produce a CustomField. Persist the new definition with AddCustomFieldAsync(...) or the synchronous AddCustomFields(...):
CustomField field = service.CreateCustomFieldBuilder()
.SetName("Department")
.SetEntityType(EntityType.Cardholder)
.SetValueType(CustomFieldValueType.Text)
.SetDefaultValue("Unassigned")
.Build();
await service.AddCustomFieldAsync(field);Build() enforces these rules:
-
SetName,SetEntityType, andSetValueTypeare required. ForText,Numeric,Boolean,DateTime,Decimal, andDatefields, also callSetDefaultValuewith a value valid for the selected type before callingBuild(). -
Namemust be unique by the combination ofEntityType,Owner, andCustomEntityTypeId.Build()rejects a definition whose combination already exists. - A unique custom field must also be mandatory.
Build()rejects a definition marked unique without also being mandatory. -
Mandatoryis not supported on theUnit(access control unit),VideoUnit,LprUnit, orIntrusionUnitentity types.SetMandatory(true)is rejected for these types, as isBuild()after such an attempt. - When
EntityTypeisEntityType.CustomEntity,SetCustomEntityTypeIdis required and must be a non-emptyGuid. For every other entity type,SetCustomEntityTypeIdmust not be set. -
GroupPrioritymust be greater than zero. - For
DateTimevalue types, the default value must be aDateTimeinstance or a parseable date string. Values withDateTimeKind.Localare converted to Coordinated Universal Time (UTC). Values withDateTimeKind.Unspecifiedare treated as UTC.
AddCustomFieldAsync and AddCustomFields throw an SdkException with SdkError.AlreadyExist for a duplicate definition and SdkError.InvalidEntityType for an unsupported entity type.
To reuse a previously defined CustomFieldType (a constrained list of allowed values), pass it to the SetValueType(CustomFieldType) overload instead of the value-type enum.
CustomField.Guid identifies the field definition. Name and GroupName are stored display text, and Security Center does not resolve them through a per-client resource key. Native Security Center pages display the same stored text after the client language changes.
Create one custom field for the data, not one field per language. Use its GUID in integration logic. A custom Workspace view can map that GUID to an integration resource key and resolve the label with Workspace.Culture. For this pattern, see Workspace SDK localization.
Read through the service or through the entity. Both return the boxed value, with generic <T> overloads for typed access:
object department = service.GetValue(field, cardholder.Guid);
string typed = service.GetValue<string>(field, cardholder.Guid);
string byName = service.GetValue<string>(
"Department", cardholder.Guid);
IReadOnlyList<CustomFieldValue> values =
await cardholder.GetCustomFieldsAsync();
CustomFieldValue companyValue = values.FirstOrDefault(
v => v.Name == "Company");GetCustomFields() and GetCustomFieldsAsync() return IReadOnlyList<CustomFieldValue>, with one entry for every custom field defined for the entity's type; a field that has not been assigned a value is still included. Each CustomFieldValue exposes CustomField, Name, ValueType, and Value.
Write through the service (synchronous or asynchronous) or through the entity:
service.SetValue(field, cardholder.Guid, "Engineering");
await service.SetValueAsync(field, cardholder.Guid, "Engineering");
cardholder.SetCustomField(field, "Engineering");
await cardholder.SetCustomFieldAsync("Department", "Engineering");A custom field value change raises the target entity's CustomFieldsChanged event, not its FieldsChanged event. The event does not identify which custom field changed. For subscription and refresh guidance, see Detecting entity changes.
SetValue and SetValueAsync do not write an update when the new value equals the current value. Image-typed fields require the value to be a System.Drawing.Image instance.
To reset a field, call ClearValue:
service.ClearValue(field, cardholder.Guid);ClearValue writes a type-specific empty value for most fields: an empty string for text, 0 for numeric and decimal, false for Boolean, and an empty GUID for image and entity fields. For Date and DateTime fields, and for text fields constrained to a custom data type, it writes the configured DefaultValue instead.
Remove a definition by its identifier:
service.RemoveCustomField(field.Guid);
await service.RemoveCustomFieldAsync(field.Guid);Both overloads verify access to and local ownership of each definition. They throw an SdkException with SdkError.UnsufficientPrivilege when either check fails. A removal can throw KeyNotFoundException when no requested definition matches after validation.
-
About entities: Entity model and
IPartitionSupport. - About cardholders and credentials: Cardholder and credential lifecycle in depth.
- Overview
- Connecting to Security Center
- SDK certificates
- Referencing SDK assemblies
- ASP.NET hosting
- SDK compatibility
- Migrating to modern .NET
- Entities
- Entity cache
- Entity loading, cache, and query options
- Detecting entity changes
- Entity change event reference
- Transactions
- Security Center events
- Actions
- Security Desk
- Custom events
- Event-to-actions
- Managing macros
- ReportManager
- ReportManager query reference
- Access control raw events
- DownloadAllRelatedData and StrictResults
- Privileges
- Partitions
- Entity write restrictions
- About custom fields
- About video
- About cameras
- Enrolling a video unit
- Ingesting third-party video
- Archiver and auxiliary archiver roles
- Archive transfer
- About access control
- About cardholders and credentials
- About doors, areas, elevators, and access points
- About access rules and schedules
- About access control units and interface modules
- Enrolling an access control unit
- Door templates
- Visitors
- Mobile credentials
- About threat levels
- About alarms
- About incidents
- Maps
- Logging
- Overview
- Localization
- Certificates
- Lifecycle
- Threading
- State management
- Configuration
- Restricted configuration
- Events
- Queries
- Request manager
- Database
- Entity ownership
- Engine extensions
- Entity mappings
- Server management
- Custom privileges
- Custom entity types
- Resolving non-SDK assemblies
- Deploying plugins
- Modern .NET support
- Overview
- Localization
- Certificates
- Creating modules
- Tasks
- Pages
- Components
- Tile extensions
- Services
- Contextual actions
- Custom actions
- Options extensions
- Configuration pages
- Monitors
- Shared components
- Commands
- Extending events
- Map extensions
- Timeline providers
- Image extractors
- Credential encoders
- Credential readers
- Cardholder fields extractors
- Badge printers
- Content builders
- Dashboard widgets
- Incidents
- Logon providers
- Pinnable content builders
- Custom report pages
- Overview
- Getting started
- Media file formats
- MediaPlayer
- VideoSourceFilter
- MediaExporter
- MediaFile
- G64 converters
- FileCryptingManager
- PlaybackSequenceQuerier
- PlaybackStreamReader
- OverlayFactory
- PtzCoordinatesManager
- AudioTransmitter
- AudioRecorder
- AnalogMonitorController
- Camera blocking
- Overview
- Getting started
- Referencing entities
- Entity operations
- About access control in the Web SDK
- About video in the Web SDK
- Users and user groups
- Partitions
- Custom fields
- Custom card formats
- Actions
- Events and alarms
- Incidents
- Reports
- Tasks
- Macros
- Custom entity types
- System endpoints
- Performance guide
- Reference
- Endpoints
- Constants
- Enumerations
- Under the hood
- Troubleshooting