Validate user input

What options do you have?

Paul

7 minute read

Mendix offers various mechanisms to validate data input. This can be triggered by a user when he edits data in a form and clicks the save button. But it can also be a background process, for example a webservice or an import processing large amounts of objects.

Choosing a validation pattern might save you some time today, but as your application grows you might have to refactor a lot over time. Therefore make a good decision on what to use and use it consistently.

Why do you need input validation?

When the user or a process creates or changes objects, you want to be sure that they are technically and functionally valid. Technical and functional processes will fail when the data is not valid. Examples are:

  • Functionally valid
    • Every Address object requires attributes Street and City to be filled, attribute Zipcode can be left empty. When we do not have the minimum amount of data we cannot deliver the packages.
  • Technically valid
    • Every Address object requires its ForeignID attribute to filled with a UUID type 4 otherwise the integration with our SAP system fails.

What techniques are available?

Here’s a list of known techniques:

  • Validation rules in entities
  • Validation properties on widgets in forms
  • Events on widgets in forms
  • Validating data in before-commit microflows
  • Validating data in save microflows

In the paragraphs below I will explain the pros and cons of each technique.

Validation rules in entities

Have a look at the properties of an entity in your data model. There’s a tab called Validation rules where you can add your entity specific rules. It is simple and easy and in your domain model you will see immediately on which attributes have validation rules.

The screenshot below shows an entity and its validation rules. The green checkmarks next to the attributes in the entity show where validation rules are defined.

This is simple and easy and very visible. However what if your entity grows and becomes a logical entity consisting of multiple entities.

The screenshot below shows the issue. This time entity Address does not have a City attribute anymore; it is an association to a reference table with all available cities. An address has become a logical entity in your model because it consists of entity Address including the association to entity City. You cannot define a validation rule on the existence of a city in your address.

Pros:

  • Very easy to use
  • Very visible and works great for a demo

Cons:

  • Cannot be used with logical entities or any other case where validation is more complex

Validation properties on widgets in forms

Input widgets on forms have multiple properties to guide the user in editing data. For example the input mask or defining the maximum number of characters in a text widget. And there’s also a Validation property where the application can validate the user’s input; see the screenshot below. This is user interface level input validation where you are limited in validating against current database data.

Pros:

  • Validation at the user interface level brings the process to the browser

Cons:

  • Multiple pages where the data can be managed requires maintenance of the validation rules at multiple places
  • Hard to see where validations are defined, you have to look at the properties of each widget
  • Cannot be used in (background) server processes

Events on widgets in forms

Most widgets allow assigning microflows to them that are trigged on events like on-change, on-enter and on-leave. They are UI triggered but the actual execution is server side. This allows more complex validations (or other actions).

However my personal experience with on-enter and on-leave events is that they might not trigger in all cases; I cannot get them to work consistently. I definitely do not recommend them. The on-change event seems to work pretty consistent, but I would use it to enhance the user experience and not to validate data. If you want to use it for data validation then I would keep the functionality in the microflow limited to that attribute and not in combination with other attributes on that same page. User’s might and will use your application in another way than you expect so your UI flow that you created will fail.

Pros:

  • Opportunity to enhance the user experience
  • User feedback while changing the data and not when clicking the save button

Cons:

  • Do not rely on this when there are multiple attributes to be checked; a user will never fill out the form as you want so you need to validate on save anyway
  • My personal experience with on-enter and on-leave is bad

Validating data in before-commit microflows

I have seen people validating input in before-commit microflows. Mendix supports this, because the microflow has to return a boolean result to tell whether the commit should continue or not. And you can provide a message to the user to inform about the result, the Show message action works as long as there a user session available.

However, when you allow this pattern in your application then you know that importing and any foreground and background batch processing of your data will become a mess. In case of background processes the messages cannot be shown to a user or you have to log them. If it is a foreground process then the user might get large amounts of messages about the data validation. Importing and similar processes require a specific behavior, import all or nothing, so do not validate the input in before-commit.

And when you use a database - business logic - user interface layered approach then you know that you should never interact with the user interface while running at the database level. So no UI stuff at DB level! Mendix allows you to, but as a developer you have to define the rules.

The amount of use cases to use validation in before-commit microflows is limited, but personally this is the best option so far. Below is an example of what such a microflow could look like.

Pros:

  • You can prevent incomplete or incorrect objects to be committed
  • Great opportunity to combine it with additional actions like data transformation

Cons:

  • Hard to give feedback to the user; technically you can but you should not

Validating data in save microflows

When we move the before-commit validation approach to a save microflow then we can validate the data before committing it. Messages can be shown to a user, no issue with the three layered approach and you can adjust data before committing it; for example transform the email address in an attribute to lowercase (can be put in a before-commit microflow too, is probably even better for this example).

This is what a generic save microflow looks like:

First you validate the input via a sub-microflow (see below) to keep your microflows tidy and to the point. When the result is positive then you continue, otherwise do nothing.

Validating the data is pretty straight forward and you have all microflow capabilities to check the data. And if you want to be able to re-use the validation in other processes then you can put each check in its own sub-microflow and re-use those among the validation microflows.

Pros:

  • User initiated server side validation where complex validations can be created
  • When validation microflows for batch imports etc. must be created, this validation microflow can be used as an example or you can make parts re-usable
  • Data manipulation before saving it

Cons:

  • Feels like a lot of work for entities with a large amount attributes to validate

Personal preference

I never use validation in entities or pages, I even forgot that they existed until I started working on this blog post.

In before-commit microflows I transform data, but I expect data to be validated before it is committed. Validation here is only added to for example signal (existing) data integrity issues.

Save microflows with validation as shown above is what I use consistently. The same approach can be used where you have to check a set of data, for example when importing Excel files or processing post webservices. Then you don’t show messages to a user, but you collect the validation messages in a dedicated mechanism to inform the user or webservice about the process.

I hope you learned something here and that it inspires you to do fun stuff.