Validation
June 10, 2026 · View on GitHub
DataSurface provides comprehensive built-in validation driven by the ResourceContract. Validation rules are declared via [CrudField] attributes and enforced automatically on create and update operations.
Validation Rules
| Rule | Attribute Property | Applies To | Description |
|---|---|---|---|
| Required on create | RequiredOnCreate = true | POST | Field must be present in the request body |
| Immutable | Immutable = true | PATCH | Field is rejected on update — can only be set on create |
| Min length | MinLength = N | POST, PATCH | Minimum string length |
| Max length | MaxLength = N | POST, PATCH | Maximum string length |
| Min value | Min = N | POST, PATCH | Minimum numeric value |
| Max value | Max = N | POST, PATCH | Maximum numeric value |
| Regex pattern | Regex = "..." | POST, PATCH | Value must match the regular expression |
| Allowed values | AllowedValues = "a|b|c" | POST, PATCH | Value must be one of the pipe-separated options |
| JSON type check | (automatic) | POST, PATCH | Wrong JSON type for a field is rejected with 400 — e.g. a number sent for a string field returns "Value must be a string.", a non-numeric value for a numeric field returns "Value must be a valid number." |
| Unknown field rejection | (automatic) | POST, PATCH | Fields not in the contract are rejected |
Example
[CrudResource("users")]
public class User
{
[CrudKey]
public int Id { get; set; }
// Required on create, with regex pattern
[CrudField(CrudDto.Read | CrudDto.Create | CrudDto.Update,
RequiredOnCreate = true,
Regex = @"^[\w.+-]+@[\w-]+\.[\w.]+$")]
public string Email { get; set; } = default!;
// Immutable — set once on create, rejected on PATCH
[CrudField(CrudDto.Read | CrudDto.Create, Immutable = true)]
public string Username { get; set; } = default!;
// String length validation
[CrudField(CrudDto.Read | CrudDto.Create | CrudDto.Update,
MinLength = 8, MaxLength = 100)]
public string Password { get; set; } = default!;
// Numeric range validation
[CrudField(CrudDto.Read | CrudDto.Create | CrudDto.Update,
Min = 0, Max = 150)]
public int Age { get; set; }
// Regex pattern validation
[CrudField(CrudDto.Read | CrudDto.Create | CrudDto.Update,
Regex = @"^\+?[1-9]\d{1,14}$")]
public string? PhoneNumber { get; set; }
// Allowed values — enum-like restriction
[CrudField(CrudDto.Read | CrudDto.Create | CrudDto.Update,
AllowedValues = "Active|Inactive|Pending")]
public string Status { get; set; } = default!;
}
Validation Behavior
On Create (POST)
- Unknown fields → rejected
RequiredOnCreatefields → must be present- String length checks →
MinLength,MaxLength - Numeric range checks →
Min,Max - Pattern matching →
Regex - Value restriction →
AllowedValues
On Update (PATCH)
- Unknown fields → rejected
Immutablefields → rejected (cannot be changed)- Concurrency token → required if
RequiredOnUpdate = true - String length checks → on provided fields
- Numeric range checks → on provided fields
- Pattern matching → on provided fields
- Value restriction → on provided fields
Validation only runs on fields actually present in the request body. Omitted fields on PATCH are left unchanged and not validated.
Error Response
Validation errors return HTTP 400 with RFC 7807 Problem Details:
{
"title": "Validation failed",
"status": 400,
"detail": "One or more validation errors occurred.",
"traceId": "00-abc123...",
"errors": {
"email": ["Field is required."],
"password": ["Minimum length is 8."],
"age": ["Maximum value is 150."],
"status": ["Value must be one of: Active, Inactive, Pending."]
}
}
Multiple validation errors are collected and returned together — the response includes all failures, not just the first one.
Feature Flag
Validation can be disabled via feature flags:
opt.Features = new DataSurfaceFeatures
{
EnableFieldValidation = false // Disables MinLength, MaxLength, Min, Max, Regex, AllowedValues and the JSON type check
};
Note: RequiredOnCreate, Immutable, and unknown field rejection are always enforced regardless of the feature flag.
Related
- Error Responses Reference — All error types and status codes
- Attributes Reference — Full
[CrudField]property list