Field Flags and Relevant Attributes
Field Flags
Serenity has a set of field flags that controls the field behavior.
public enum FieldFlags
{
None = 0,
Insertable = 1,
Updatable = 2,
NotNull = 4,
PrimaryKey = 8,
AutoIncrement = 16,
Foreign = 32,
Calculated = 64,
Reflective = 128,
NotMapped = 256,
Trim = 512,
TrimToEmpty = 512 + 1024,
DenyFiltering = 2048,
Unique = 4096,
Default = Insertable | Updatable | Trim,
Required = Default | NotNull,
Identity = PrimaryKey | AutoIncrement | NotNull
}
An ordinary table field has the Insertable
, Updatable
, and Trim
flags set by default which corresponds to the Default
combination flag.
Insertable Flag
The Insertable
flag controls if the field is editable in new record mode. By default, all the ordinary fields are considered to be insertable.
Some fields might not be insertable in the database table, e.g. identity columns shouldn't have this flag set.
When a field doesn't have this flag, it won't be editable in forms in new record mode. This is also validated in services at the request handler level.
Sometimes, there might be internal fields that are perfectly valid in an SQL INSERT statement but shouldn't be edited in forms.
One example might be an InsertedByUserId
field which should be set on the service level, and not by an end user. If we would let an end user edit it in forms, this would be a security hole. Such fields shouldn't have the Insertable
flag set too.
This also means field flags don't have to exactly match the database table settings, as they are meant to be used at the application level, not SQL.
Insertable Attribute
To turn off the Insertable
flag for a field put an Insertable(false)
attribute on it:
[Insertable(false)]
public string MyField
{
get => fields.MyField[this];
set => fields.MyField[this] = value;
}
Use Insertable(true)
to turn it back on.
The non-insertable fields are not hidden. They are just read-only. If you want to hide them, use the HideOnInsert
attribute or write something like this.form.MyField.getGridField().toggle(this.isNew())
by overriding the updateInterface
method of your dialog.
Updatable Flag
This flag is just like the Insertable
flag, but controls edit record mode in forms and update operations in services. By default, all ordinary fields are considered to be updatable.
Updatable Attribute
To turn off the Updatable
flag for a field, put an [Updatable(false)]
attribute on it:
[Updatable(false)]
public string MyField
{
get => return fields.MyField[this];
set => fields.MyField[this] = value;
}
Use Updatable(true)
to turn it on.
Non-updatable fields are not hidden in dialogs. They are just read-only. If you want to hide them, use the HideOnUpdate
attribute or write something like this.form.MyField.getGridField().toggle(!this.isNew())
by overriding the updateInterface
method of your dialog.
Trim Flag
This flag is only meaningful for string-typed fields and controls whether their value should be trimmed before the save. All string fields have this flag on by default.
When a field value is an empty string or whitespace only, it is trimmed to null.
TrimToEmpty Flag
Use this flag if you prefer to trim string fields to an empty string instead of null.
When a field value is null or whitespace only, it is trimmed to an empty string.
SetFieldFlags Attribute
This attribute can be used on fields to include or exclude a set of flags. It takes a first required parameter to include flags, and a second optional parameter to exclude flags.
To turn on the TrimToEmpty flag on a field, we use it like this:
[SetFieldFlags(FieldFlags.TrimToEmpty)]
public string MyField
{
get => fields.MyField[this];
set => fields.MyField[this] = value;
}
To turn off the Trim flag:
[SetFieldFlags(FieldFlags.None, FieldFlags.TrimToEmpty)]
public string MyField
{
get => return fields.MyField[this];
set => fields.MyField[this] = value;
}
To include TrimToEmpty and Updatable but remove Insertable:
[SetFieldFlags(
FieldFlags.Updatable | FieldFlags.TrimToEmpty,
FieldFlags.Insertable)]
public string MyField
{
get => fields.MyField[this];
set => fields.MyField[this] = value;
}
Insertable and Updatable attributes are subclasses of the SetFieldFlags attribute.
NotNull Flag
Use this flag to set fields as not nullable. By default, this flag is set for fields that are not nullable in the database, using the NotNull
attribute.
When a field is not nullable, its corresponding label in forms has a red asterisk and they are required to be entered.
NotNull Attribute
This sets the NotNull attribute on a field to ON. Remove the attribute to turn it off.
You may also use [Required(false)]
to make a field not required in forms, even if it is not nullable in the database. This doesn't clear the NotNull flag.
Required Flag
This is a combination of Default and NotNullable flags.
It has no relation to the [Required]
attribute which controls validation in forms.
PrimaryKey Flag and PrimaryKey Attribute
Set this for primary key fields in the table.
Primary key fields are selected on Key column selection mode in List and Retrieve request handlers.
The [PrimaryKey]
attribute sets this flag ON.
AutoIncrement Flag and AutoIncrement Attribute
Set this for fields that are auto-incremented on the server side, e.g. identity columns, or columns using a generator.
Identity Flag and Identity Attribute
This is a combination of PrimaryKey, AutoIncrement, and NotNull flags, which is common for identity columns.
IdProperty
Attribute
This determines the ID property of a row class. It does not have to be an identity e.g. autoincrement property.
Foreign Flag
This flag is set for foreign view fields, that are originating from other tables through a join.
It is automatically set for fields with expressions containing table aliases other than T0.
For example, if a field has an attribute like [Expression("jCountry.CountryName")]
it will have this flag.
This has no relation to the ForeignKey attribute
Calculated Flag
If a field has an expression involving more than one field or some mathematical operations, it will have this flag.
This could also be set for fields that are calculated on the SQL server side.
NotMapped Flag and NotMapped Attribute
Corresponds to an unmapped field in Serenity entities. They don't have a corresponding field in the database table.
These kinds of fields can be used for temporary calculation, storage and transfer on client and service layers.
Reflective Flag
This is used for an advanced form of unmapped fields, where they don't have a storage of their own in the row, but reflect the value of another field in a different form. For example, a field that displays the absolute (positive) value of an integer field that could be negative.
This should only be used in rare cases for such unmapped fields.
DenyFiltering Flag
If set, it denies filtering operations on a sensitive field. This can be useful for secret fields like PasswordHash that shouldn't be allowed to be selected or filtered on the client side.
Unique Flag and Unique Attribute
When a field has this flag, its value is checked against existing values in the database to be unique.
You can turn on this flag with the Unique
attribute and determine if this constraint should be checked on the service level (before the check on the database level to avoid cryptic constraint errors).