# Validation

## When it runs

`SwiftParser.GetMessage` / `GetMessages` validate by default (`validate: true`). You can also call validation yourself:

```csharp
bool ok = message.Validate();

var errors = new List<ValidationError>();
bool ok2 = message.Validate(errors);
```

`Validate()` with no list still runs the rules; pass a list to collect details.

Parse without validating the definition:

```csharp
var message = parser.GetMessage(text, errors, validate: false);
```

Use this for damaged or non-standard traffic you still want to inspect or re-emit as raw XML.

## What is checked

- Block 1: application id, service id, LT address, session, sequence
- Block 2: message type, priority, input/output-specific fields
- Block 3 / 5: present tags
- Block 4: tag order and presence against the MT definition; per-tag length, range, enumeration, regex
- Missing Block 1, 2, or 4 is an error

Block 4 mismatches produce `ValidationErrorType.UsupportedBlockFormat` (historical spelling) with a description such as:

> Message 103 has wrong format in Block 4. Tag ":99:" not found in the definition.

## ValidationError

```csharp
namespace SWIFTFramework.Validation
{
    public class ValidationError
    {
        public ValidationErrorType Type { get; set; }
        public string Description { get; set; }
        public object ParentPropertyObject { get; set; }
        public string PropertyName { get; set; }
    }

    public enum ValidationErrorType
    {
        Unknown,
        UnsupportedValue,
        UsupportedBlockFormat, // spelling is part of the public API
        UnrecognizedValue,
        WrongLength,
        WrongRange,
        MissingBlock1,
        MissingBlock2,
        MissingBlock4,
        MissingBlock5,
        UserError
    }
}
```

`ToString()` is not customized — print `Type` and `Description`.

## Custom rules (advanced)

The library includes rule types you can attach when extending validation:

| Class | Role |
|---|---|
| `ValidationRule_Length` | Min/max length |
| `ValidationRule_Range` | Numeric range |
| `ValidationRule_Enumeration` | Allowed codes |
| `ValidationRule_RegEx` | Pattern |
| `ValidatePropertyBase` | Property-level validator |
| `ValidateTagBase` | Tag-level validator |

Tutorial sources under `Framework/Tutorials` show adding a custom property/tag validator. For application code, collecting `ValidationError` from `Validate` is usually enough.

## Practical pattern

```csharp
var errors = new List<ValidationError>();
var message = parser.GetMessage(text, errors);

if (errors.Count > 0)
{
    // still have a typed object; decide whether to reject
    throw new InvalidOperationException(
        string.Join(Environment.NewLine, errors.Select(e => $"{e.Type}: {e.Description}")));
}
```
