Skip to content
skwasjer edited this page Feb 10, 2021 · 44 revisions

The default options are fine for most use cases. IbanNet however does have a limited set of options:

  • Registry
  • Strict vs loose validation
  • Custom post-validation rules

Registry

IbanNet is using the Swift registry in strict validation mode to ensure validation is done according to the ISO 13616 standard. Swift is the official registration authority for national IBAN formats.

Custom registry provider

You can choose to implement a different provider by implementing IIbanRegistryProvider and IStructureValidationFactory and provide IbanCountry definitions based on different patterns.

Configure the new provider through the options:

var validator = new IbanValidator(new IbanValidatorOptions
{
    Registry = new IbanRegistry
    {
        Providers =
        {
            new MyCustomProvider()
        }
    }
});

More providers may be added in the future to IbanNet, f.ex. for unofficial, or pending IBAN formats. But this is still TBD.

Strict vs loose validation

IbanNet by default validates every IBAN using strict validation rules. You can choose to use loose validation mode, which then ignores the structure of an IBAN but does validate for check digits, length, etc. Potentially this could lead to false positives but on the flip side is around 20% faster.

To enable loose mode, configure the validator:

var validator = new IbanValidator(new IbanValidatorOptions
{
    ValidationMethod = ValidationMethod.Loose
});

There are some legitimate use cases where loose validation is acceptable, for instance within internal service domain boundaries, where the assumption can be safely made that an IBAN has already been strictly validated in prior workflows/processes (for example through user input).

Custom post-validation rules

To apply additional validation logic, implement IIbanValidationRule and a custom error result. Custom rules will always be executed 'after' built-in validation has succeeded, so in that respect you can be sure the IBAN is valid when the rule executes. What extra logic is applied is up to you.

Use cases could be to verify banks, branch codes, etc. or for example to reject certain countries:

class CountryNotAcceptedError : ErrorResult
{
    public CountryNotAcceptedError(string countryCode)
        : base($"Bank account numbers from country '{countryCode}' not accepted.")
    {
    }
}

class RejectCountryRule : IIbanValidationRule
{
    private readonly ISet<string> _rejectedCountryCodes;

    public RejectCountryRule(IEnumerable<string> rejectedCountryCodes)
    {
        _rejectedCountryCodes = new HashSet<string>(rejectedCountryCodes);
    }

    public ValidationRuleResult Validate(ValidationRuleContext context)
    {
        if (_rejectedCountryCodes.Contains(context.Country.TwoLetterISORegionName))
        {
            // Return custom error if not valid.
            return new CountryNotAcceptedError(context.Country.TwoLetterISORegionName);
        }

        // Success.
        return ValidationRuleResult.Success;
    }
}

Register the rule through the options:

var validator = new IbanValidator(new IbanValidatorOptions
{
    Rules =
    {
        // Reject IBAN's from NL and GB.
        new RejectCountryRule(new [] { "NL", "GB" })
    }
});

Note: you can also implement these types of extra validation through FluentValidation or DataAnnotations, but this is up to you. If you do not want to impose a specific dependency on any of these validation frameworks, implementing a custom rule may be a good idea.