Entity Contracts
Serenity uses marker interfaces (contracts) to give a row special capabilities. By implementing one of these interfaces, your row tells the framework "I have an ID field", "I support soft delete", "I have logging fields", etc. — and the corresponding behaviors, handlers, and UI features activate automatically.
Identity & Name
- IIdRow — the row has an ID field. Put
[IdProperty]on the corresponding field. This is the most common contract; most rows implement it. - INameRow — the row has a name/description field. Put
[NameProperty]on the corresponding field. Used for the row's display title and quick search. - IDisplayNameRow — exposes a
DisplayNameField(aStringField).
public sealed class PersonRow : Row<PersonRow.RowFields>, IIdRow, INameRow
{
[DisplayName("Person Id"), Identity, IdProperty]
public int? PersonId { get => fields.PersonId[this]; set => fields.PersonId[this] = value; }
[DisplayName("Full Name"), NameProperty]
public string FullName { get => fields.FullName[this]; set => fields.FullName[this] = value; }
}
Active / Deleted (Soft Delete)
- IIsActiveRow — the row has an
IsActiveField(Int16Field).1= active,0= inactive. - IIsActiveDeletedRow — an
IIsActiveRowwhere-1means deleted (soft delete via the active flag). - IIsDeletedRow — the row has an
IsDeletedField(BooleanField) for soft delete.
Rows implementing these are not physically deleted — the delete handler sets the flag instead, and list queries filter out deleted rows.
Logging Fields
- IInsertDateRow — has an
InsertDateField. - IInsertUserIdRow — has an
InsertUserIdField. - IUpdateDateRow — has an
UpdateDateField. - IUpdateUserIdRow — has an
UpdateUserIdField. - IInsertLogRow — combination of
IInsertDateRow+IInsertUserIdRow. - IUpdateLogRow — combination of
IUpdateDateRow+IUpdateUserIdRow. - ILoggingRow — combination of
IUpdateLogRow+IInsertLogRow. This is the one you implement for full insert/update audit logging. - IDeleteLogRow — has
DeleteUserIdFieldandDeleteDateField(delete audit logging).
The UpdateInsertLogBehavior fills these fields automatically on save. See Built-in Service Behaviors.
Ordering & Hierarchy
- IDisplayOrderRow — has a
DisplayOrderField(Int32Field); the row is kept in order automatically. - IParentIdRow — has a
ParentIdField; used for tree/hierarchical rows and parent validation.
Other Contracts
- IEmailRow — exposes an
EmailField(used by membership/account features). - IPasswordRow — exposes
PasswordHashFieldandPasswordSaltField(used by authentication). - IFieldWithJoinInfo — a field that exposes its referenced aliases and the row's joins (used by query building).
How Contracts Are Used
These interfaces are what make the framework's conventions work:
- Request handlers check for
IIdRowto know the ID field,INameRowfor the name field,IIsActiveRow/IIsDeletedRowfor soft delete,ILoggingRowfor audit fields. - Behaviors activate based on these interfaces (e.g.
CaptureLogBehaviorrequiresIIdRow;UpdateInsertLogBehavioractivates for logging rows). - The UI uses
IIdRow/INameRowfor dialog titles, quick search, and lookup scripts.
Implementing a contract is usually just adding the interface to the row declaration and marking the corresponding field with the matching attribute ([IdProperty], [NameProperty], etc.).