Manual Validation in the Business Layer without Exceptions

David Rogers
The Cloud Builders Guild
4 min readApr 20, 2020

This is the second post in a 2 post series:

(1) Validation without Exceptions using a MediatR Pipeline Behavior; and
(2) Manual Validation in the Business Layer without Exceptions

In my last post, I covered a scenario of using a Mediatr Pipeline Behavior to perform validation of a command object in such a way that no exception is thrown in the event of a validation failure. Today, I’m going to cover another strategy which involves manual validation in the Business Layer, rather than handing it off to the framework (as described in that previous post).

Synopsis

There may be times where you need to perform manual validation in the business layer, for one reason or another. Perhaps some code needs to run before the validation is performed and this may not be something which can happen if the validation happens automatically in the Mediatr pipeline. In such a case, we are faced with the same challenge as in my previous post; how do we bubble a validation failure up to the View, without just doing the throw/catch exception thing?

The solution which I’m putting forward in this post uses a Functional Programming construct known as a Discriminated Union. But we’ll get to that in time. First, I’ll set out the scenario. I’ll try to keep it simple, yet at the same time, keep a realistic number of layers to be comparable to a real world application.

The trivial example which I will use as a vehicle to demonstrate the concepts in this post will involve a simple validator, which merely validates whether a collection of Colors is not empty. Again, using FluentValidation, such a validator would look like this:

Introducing “Either”

So, lets look at the service in which the validation will be performed. The relevant method in this service will need to return either the ValidationResult or the collection itself. And that brings us to the custom class Either (which you can see used as the return type of the GetColorsAsync method below). I have obtained the Either class from Mikhail Shilkov’s blog (thanks Mikhail!). Whilst I’m demonstrating how to use Either in my architecture, all credit goes to Mikhail for the class itself.

GetColorsAsync Method

Either is also used as the delineated return Type of the query object (I’ll explain how it works next):

IRequest has a Closed Generic Type of Either<IEnumerable<ColorPayloadDto>, ValidationResult>

So what is this Either class of which I speak? The code for Either is:

If you look at the GetColorsAsync method above, the return Type is Either<IEnumerable<ColorPayloadDto>, ValidationResult> (wrapped in a Task). But if you look at the body of the method, depending on whether the ValidationResult is valid, it returns 1 of 2 Types of objects (see lines 34–37 of the GetColorsAsync method above) i.e.

  1. a List; or
  2. a ValidationResult.

They are objects of 2 differing Types! 😵 What the heck is this? Javascript?

Thus, you can see where the nomenclature for Either came from. Either one thing or another. How is this done using a strongly typed language like C#?

💡 The answer, is by the implicit operators of the Either class (otherwise known as the User-defined conversion operators). Because they are implicit, we don’t need use an explicit cast to return an object of either an IEnumerable collection or a ValidationResult. That’s what these 2 lines of code do:

public static implicit operator Either<TL, TR>(TL left) => new Either<TL, TR>(left);

public static implicit operator Either<TL, TR>(TR right) => new Either<TL, TR>(right);

So, to clarify, by putting it another way, because the closed generic Type of Either is Either<IEnumerable<ColorPayloadDto>, ValidationResult>, whether you return an IEnumerable<ColorPayloadDto> or a ValidationResult, the Type returned is an instance of the Either class. Ergo, we are actually only returning one Type, not 2.

The implicit operators also toggle the all-important _isLeft field, which determines what gets returned when the Match method is called (you’ll see where that comes in next). This enables us to write code like this (note the invocation of Match in the GetColors action method):

Where validation has passed, the OkResponse method will be passed the list of DTOs. Otherwise, the BadRequestResponse will be passed the ValidationResult (which will be a failed validation). Note the use of the LeftOrDefault and RightOrDefault convenience methods which make for more elegant readable code.

The reason that this works is because both the OkResponse and BadRequestResponse methods (on the parent controller class) return an IActionResult. Note, whilst Ok() returns OkObjectResult, BadRequest() returns an BadRequestObjectResult. But both of those implement IActionResult. So, we can create helper methods which return that abstraction. You can see my implementation of those methods in this class, here.

Hitting the API with Postman (or equivalent tool), if the list is empty, validation fails and the API response will look like this:

JSON API Response with Validation Fail Outcome

If the list is has ≥ 1 item, validation passes and the API response will look like this:

JSON API Response with Data Property Populated

So, again we have achieved an elegant implementation which has enabled us to bubble the validation failure up to the View (without throwing an exception). Our code will be more performant and our runtime will be all the more happier for it!

Feel free to hit me up in the comments if you have another way of dealing with validation failures that does not involved throwing exceptions.

This Github repo contains sample code which demonstrates the concepts set out in this article. Note, I’ve created a branch specific to this article called validation-article-2.

--

--