Kentico Xperience Design Patterns: Handling Failures - The Result Monad
Tags: xperience, kentico, aspnetcore, csharp
Published: 2022-08-29 13:32:35

---
title: Kentico Xperience Design Patterns: Handling Failures - The Result Monad
published: true
description: Learn how we can use the Result monad to clearly model failures and handle errors in our applications.
tags: xperience, kentico, aspnetcore, csharp
series: Kentico Xperience Design Patterns
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/hcusgcjdsp4aozej50g9.jpg
---

In a [previous post](https://dev.to/seangwright/kentico-xperience-design-patterns-handling-failures-return-errors-dont-throw-them-4apa) we looked at the benefits of returning failures instead of throwing exceptions.

We came up with a `Result` type that could represent an failure or a success of a given operation, either containing a `string` error message or the value of our operation.

This custom `Result` type met most of our requirements, but to really unlock its power 🦾 we need to turn it into the `Result` [monad](https://en.wikipedia.org/wiki/Monad_(functional_programming)).

> Note: This is part 3 of a 3 part series on handling failures.

> [Part 1](https://dev.to/seangwright/kentico-xperience-design-patterns-handling-failures-centralized-exception-handling-4p3n) and [Part 2](https://dev.to/seangwright/kentico-xperience-design-patterns-handling-failures-return-errors-dont-throw-them-4apa)

## 📚 What Will We Learn?

- [A Refresher on Monads](#refresher)
- [Modeling Data Access](#modeling-data-access)
- [Handling Results](#handling-results)
- [Map and Bind](#map-and-bind)
- [Handling Failures](#handling-failures)

## [A Refresher on Monads](#refresher)

If you are unsure 😕 of what a monad is, I give a description with some analogies in my previous post [Kentico Xperience Design Patterns: Modeling Missing Data - The Maybe Monad](https://dev.to/seangwright/kentico-xperience-design-patterns-modeling-missing-data-the-maybe-monad-2c7i#what-is-a-monad).

However, if you don't feel like navigating away and want a quick explanation, think of a monad as a container 🥫, in the same way that `Task<T>` and `List<T>` are containers in C# (they are also monads).

You can manipulate these containers in a standard way, independent of what's inside and each type of monad represents a unique concept 🧠. A `Task<T>` represents a value `T` that will be available at some point in the future and `List<T>` represents a collection of 0 or more of some type `T`.

> It's worth noting that monads can contain other monads, because they don't care what kind of data they contain (ex: `Task<List<T>>` or `List<Task<T>>`).

Let's consider the `Result<TValue, TError>` monad 😮.

It is a container that represents an operation that either succeeded or failed (past tense). If it succeeded then it will have a value of type `TValue` and if it failed it will have an error of type `TError`.

The specific implementation of the `Result` monad that we will be using comes from the C# library [CSharpFunctionalExtensions](https://github.com/vkhorikov/CSharpFunctionalExtensions) 🎉 and we will use the simplified `Result<T>` where the `TError` error type is a `string` and doesn't need to be specified.

## [Modeling Data Access](#modeling-data-access)

Now we can answer the question of when and where do we actually use `Result<T>`.

I recommend starting somewhere our application is performing an 'operation' which could succeed or fail and we're currently modeling the failure case with a `throw new Exception(...);` or by ignoring it altogether.

Here's an example that might look similar to some Kentico Xperience code we have written:

```csharp
public async Task<IActionResult> Index()
{
    BlogPost page = pageDataContextRetriever
        .Retrieve<BlogPost>()
        .Page;

    Author author = await authorService.GetAuthor(page);

    Image bgImage = await blogService.GetDefaultBackgroundImage();

    Image heroImage = await blogService.GetHero(page);

    return new BlogPostViewModel(
        page, 
        author, 
        bgImage, 
        heroImage);
}
```

In the applications I work on, it's pretty common to grab bits of data from various pages, custom module classes, the media library, ect... to gather all the content needed to render a page 🤓.

However, each of these operations needs to go to the database, an external web service, or the file system to look for something. It might even have some business rules 📃 around how the data is retrieved. 

If something goes wrong in the sample code above we can assume that an exception is going to thrown and [centralized exception handling](https://dev.to/seangwright/kentico-xperience-design-patterns-handling-failures-centralized-exception-handling-4p3n) will catch it and display an error page.

We end up skipping the rest of the operations, even if they would have succeeded 😞. With centralized exception handling we typically never partially display a page that experienced some failures.

Let's update the code to use `Result<T>` and see where that gets us:

```csharp
public async Task<IActionResult> Index()
{
    BlogPost page = pageDataContextRetriever
        .Retrieve<BlogPost>()
        .Page;

    Result<Author> author = await authorService.GetAuthor(page);

    Result<Image> bgImage = await blogService
        .GetDefaultBackgroundImage();

    Result<Image> heroImage = await blogService.GetHero(page);

    return new BlogPostViewModel(...); // 🤔
}
```

Our potential failures are no longer hidden as exceptions behind a method signature. Instead, we're requiring consumers of the `authorService` and `blogService` to deal with both the success and failure cases.

However, we now have a bunch of `Result<T>` instances that are useless to our `BlogPostViewModel` 😩, so we'll need to do something to get the data they potentially contain to our Razor views.

## [Handling Results](#handling-results)

One option for rendering when using `Result<T>` is to update the `BlogPostViewModel` to use `Result` properties and 'unwrap' them in the View:

```csharp
public record BlogPostViewModel(
  BlogPost Post,
  Result<Author> Author,
  Result<Image> HeroImage,
  Result<Image> BgImage);
```

In this case, we'd pass our results directly to the `BlogPostViewModel` constructor in our `Index()` method:

```csharp
public async Task<IActionResult> Index()
{
    BlogPost page = // ...
    Result<Author> author = // ...
    Result<Image> bgImage = // ...
    Result<Image> heroImage = // ...

    return new BlogPostViewModel(
        page, author, heroImage, bgImage);
}
```

Then, in our View we can unwrap conditionally to access the values or errors that were the outcomes of each operation:

```html
@model Sandbox.BlogPostViewModel

@if (Model.HeroImage.TryGetValue(out var img))
{
  <!-- We retrieved content successfully -->
  <div>
    <img src="img.Path" alt="img.AltText" />
  </div>
}
else if (Model.HeroImage.TryGetError(out string err))
{
  <!-- Content retrieval failed - show error to admins -->
  <page-builder-mode exclude="Live">
    <p>Could not retrieve hero image:</p>
    <p>@err</p>
  </page-builder-mode>
}
```

This is an interesting approach because it allows us to gracefully 💃🏽 display error information for any operations that failed, while continuing to show the correct content for those that succeed.

In this example we were able to treat all the `Result<T>` as independent because _none of the operations were conditional on the others_, but that's not always the case 😮.

Let's enhance our `BlogPostViewModel` to include related posts (by author) and those post's taxonomies:

```csharp
public async Task<IActionResult> Index()
{
    BlogPost page = // ...
    Result<Author> author = // ...
    Result<Image> bgImage = // ...
    Result<Image> heroImage = // ...

    Result<List<BlogPost>> relatedPosts = await blogService
        .GetRelatedPostsByAuthor(page, author);

    Result<List<Taxonomy>> taxonomies = await taxonomyService
        .GetForPages(relatedPosts);

    return new BlogPostViewModel(...);
}
```

We're now an in awkward situation where we have to pass `Result<T>` to our services. Those service methods will have to do some checks to see if the results succeeded or failed and conditionally perform the operations.

The monad is 'infecting' 😷 our code, and not in a good way.

Ideally we'd only call our services if the depending operations (getting the `Author` and related `BlogPost`s) succeeded. As with most monads, we'll have a better experience by "lifting" our code up into the `Result` instead of bringing the `Result` down into our code 😉.

> This is similar to how we work with `Task<T>`. We don't often pass values of this type as arguments to methods. Instead we `await` them to get their values and pass those to our methods.

> We can also compare this to creating methods that operate on a single value of type `T` vs updating all of them to accept `List<T>`.

Fortunately there's [an API for that](https://youtu.be/EhkxDIr0y2U). We want to use `Result<T>.Bind()` and `Result<T>.Map()`:

```csharp
public async Task<IActionResult> Index()
{
    BlogPost page = // ...
    Result<Image> bgImage = // ...
    Result<Image> heroImage = // ...

    // result is Result<(Author, List<BlogPost>, List<Taxonomy>)>
    var result = await authorService.GetAuthor(page)
           .Bind((Author author) => 
           {
               return blogService
                   .GetRelatedPostsByAuthor(page, author)
                   .Map((List<BlogPost> posts) => 
                   {
                       return (author, posts);
                   });
           })
           .Bind(((Author, List<BlogPost>) t) => 
           {
               return taxonomyService
                   .GetForPages(t.posts)
                   .Map((List<Taxonomy> taxonomies) => 
                   {
                       return (t.author, t.posts, taxonomies);
                   });
           });

    return new BlogPostViewModel(...);
}
```

So, what's going on here 😵😵?

Let's break it down piece by piece 🤗.

`authorService.GetAuthor()`, `blogService.GetRelatedPostsByAuthor()` and `taxonomyService.GetForPages()` return `Result<T>`, so we can chain off them with `Result<T>`'s extension methods.

The `Map()` and `Bind()` extension methods will only execute their delegate parameter _if_ the `Result` is in a successful state - that is, if the previous operation didn't fail 👍🏾.

This means we only get related blog posts if we were able to get the current post's author. And, we only get the taxonomies if we were able to get related blog posts.

If any part of this dependency chain fails, all later operations are skipped and the failed `Result` is returned from the final extension method 🙌🏼.

## [Map and Bind](#map-and-bind)

To help make the above code a bit more transparent, let's review the functionality of `Map()` and `Bind()`:

`Map()` is like LINQ's [Select](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/projection-operations#select) method, which converts the contents of the `Result<T>` from one value to another (it could be to the same or different types).

We often use `Map()` when we want to transform the data returned from a method call to something else - like converting a [DTO](https://en.wikipedia.org/wiki/Data_transfer_object) to a view model. We don't know if the method successfully completed its operation 😏, we assume it did and *declare* how to transform the result. Our transformation is skipped if the data retrieval failed.

`Bind()` is like LINQ's [SelectMany](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/projection-operations#selectmany), which flattens out a nested `Result` (ex `IEnumerable<IEnumerable<T>>` or `Result<Result<T>>`).

We'll typically use `Bind()` when we have dependent operations.

When one service returns a `Result` and we only want to call another service if the first one succeeded we will write something like: 

```csharp
Result<OtherData> result = service1
    .GetData()
    .Bind(data => service2.GetOtherData())
```

You'll notice 🧐 we have a common pattern of `Bind()` followed by a nested `Map()`. `Bind()` is calling the dependent operation and `Map()` lets us continue to gather up the data from each operation into a new C# [tuple](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-tuples).

We can skip the braces, type annotations, and `return` keywords and use expressions to keep our code terse and declarative - reading like a recipe 👩🏻‍🍳:

```csharp
public async Task<IActionResult> Index()
{
    BlogPost page = // ...
    Result<Image> bgImage = // ...
    Result<Image> heroImage = // ...

    // result is Result<(Author, List<BlogPost>, List<Taxonomy>)
    var result = await authorService.GetAuthor(page)
           .Bind(author => blogService
               .GetRelatedPostsByAuthor(page, author)
               .Map(posts => (author, posts)))
           .Bind(set => taxonomyService
               .GetForPages(set.posts)
               .Map(taxonomies => (set.author, set.posts, taxonomies)));

    return new BlogPostViewModel(...);
}
```

If this feels too unfamiliar, and we want a place to add breakpoints for debuggability, we can extract each delegate to a method and pass the [method group](https://stackoverflow.com/questions/3841990/are-there-any-benefits-to-using-a-c-sharp-method-group-if-available), which can be even more readable 😁:

```csharp
public async Task<IActionResult> Index()
{
    BlogPost page = // ...
    Result<Image> bgImage = // ...
    Result<Image> heroImage = // ...

    // Here is our recipe of operations
    var result = await Result.Success(page)
           .Bind(GetAuthor)
           .Bind(GetRelatedPosts)
           .Bind(GetTaxonomies);

    return new BlogPostViewModel(...);
}

private Task<Result<(BlogPost, Author)>> GetAuthor(BlogPost page)
{
    return authorService.GetAuthor(page)
        .Map(author => (page, author));
}

private Task<Result<(List<BlogPost>, Author)>> GetRelatedPosts(
    (BlogPost page, Author author) t)
{
    return blogService.GetRelatedPostsByAuthor(
            t.page, t.author)
        .Map(posts => (posts, t.author));
}

private Task<Result<(Author, List<BlogPost>, List<Taxonomy>)>> GetTaxonomies(
    (List<BlogPost> posts, Author author) t)
{
    return taxonomyService
        .GetForPages(t.posts)
        .Map(taxonomies => (t.author, t.posts, taxonomies));
}
```

## [Handling Failures](#handling-failures)

If our entire pipeline of operations are dependent and we should skip trying to render content if we can't access everything we need, we can use the `Match()` extension and provide delegates that define what should happen for both success and failure scenarios:

```csharp
public async Task<IActionResult> Index()
{
    BlogPost page = // ...

    return await authorService.GetAuthor(page)
           .Bind(author => blogService
               .GetRelatedPostsByAuthor(page, author)
               .Map(posts => (author, posts)))
           .Bind(t => taxonomyService
               .GetForPages(t.posts)
               .Map(taxonomies => new BlogPostViewModel(t.author, t.posts, taxonomies)))
           .Match(
               viewModel => View(viewModel),
               error => View("Error", error));
}
```

Now we're really seeing the power of composing `Result<T>` 💪🏽. Each of our services _can_ fail, but that doesn't complicate our logic that composes the data returned by each service.

Without `Result<T>` we could use exceptions to signal errors - hidden from method signatures and used as secret control flow 😝. 

Or, we have a bunch of conditional statements 😝, checking to see what 'state' we are in (success/failure), often modeled with [Nullable Reference Types](https://devblogs.microsoft.com/dotnet/nullable-reference-types-in-csharp/).

With `Result<T>` we let the monad maintain the internal success/failure state and write our code as a series of steps that clearly defines what we need to proceed.

If we have operations that aren't dependent, we can gather up all the various `Result<T>` values, put them in our view model and handle the conditional rendering in the view 🤘🏼.

My general recommendation is to separate independent sets of operations into View Components 🤔. We treat each View Component as a boundary for errors or failures instead of populating a view model with a bunch of `Result<T>` values, potentially making our views overly complex.

We can create a `ViewComponent` extension method to help us easily convert a failed `Result` to an error View:

```csharp
public static class ViewComponentResultExtensions
{
    public static Task<IViewComponentResult> View<T>(
        this Task<Result<T>> result, 
        ViewComponent vc)
    {
        return result.Match(
            value => vc.View(value),
            error => vc.View("ComponentFailure", error));
    }
}
```

We can place the failure View in a shared location `~/Views/Shared/ComponentFailure.cshtml` and have it show an error message in the Page Builder and Preview modes, but hide everything on the Live site 🙂:

```html
@model string

<page-builder-mode exclude="Live">
    <p>There was a problem loading this component.</p>
    <p>@Model</p>
</page-builder-mode>
```

If we're following the [PTVC pattern](https://dev.to/seangwright/kentico-xperience-design-patterns-mvc-is-dead-long-live-ptvc-4635), we can use this in a View Component as follows:

```csharp
public class BlogViewComponent : ViewComponent
{
    public Task<IViewComponentResult> InvokeAsync(
        BlogPost post) =>
        authorService.GetAuthor(page)
           .Bind(author => blogService
               .GetRelatedPostsByAuthor(page, author)
               .Map(posts => (author, posts)))
           .Bind(t => taxonomyService
               .GetForPages(t.posts)
               .Map(taxonomies => new BlogPostViewModel(t.author, t.posts, taxonomies)))
           .View(this);
    }
}
```

We now have the added benefit of an [expression bodied member](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/expression-bodied-members#methods) as a method implementation 😲!

## Conclusion

Moving from C# exceptions to the `Result` monad can take some getting used to. It's also a change that should be discussed with out team members and implemented where appropriate (Exceptions still have their place! 🧐).

If we do decide it's an option worth exploring, what do we gain?

- Honest methods that don't hide the possibility of failures from their signatures.
- A consistent set of patterns and tools for combining `Result`s.
- Local, targeted handling of failures that prevents them from failing an entire page (unlike centralized exception handling).
- A recipe of operations that reads like a set of instructions on how to gather up the data we need to proceed through our app.
- No repeated boilerplate if/else statements to handle various failures.

If you think your Kentico Xperience site might benefit from returning failures and using the `Result` monad, checkout the [CSharpFunctionalExtensions](https://github.com/vkhorikov/CSharpFunctionalExtensions) library and my library-in-progress [XperienceCommunity.CQRS](https://github.com/wiredviews/xperience-community-cqrs). It codifies these patterns for data retrieval and integrates cross-cutting concerns like logging and caching.

I'd love to hear your thoughts 👋!

...

As always, thanks for reading 🙏!

## References

- [Kentico Xperience Design Patterns: Handling Failures - Return Errors, Don't Throw Them](https://dev.to/seangwright/kentico-xperience-design-patterns-handling-failures-return-errors-dont-throw-them-4apa)
- [Monad](https://en.wikipedia.org/wiki/Monad_(functional_programming)) - Wikipedia
- [Kentico Xperience Design Patterns: Modeling Missing Data - The Maybe Monad](https://dev.to/seangwright/kentico-xperience-design-patterns-modeling-missing-data-the-maybe-monad-2c7i#what-is-a-monad)
- [CSharpFunctionalExtensions](https://github.com/vkhorikov/CSharpFunctionalExtensions)
- [Kentico Xperience Design Patterns: Handling Failures - Centralized Exception Handling ](https://dev.to/seangwright/kentico-xperience-design-patterns-handling-failures-centralized-exception-handling-4p3n)
- [LINQ Select](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/projection-operations#select) - Microsoft Docs
- [LINQ SelectMany](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/projection-operations#selectmany) - Microsoft Docs
- [C# Tuple](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-tuples) - Microsoft Docs
- [C# Method Groups](https://stackoverflow.com/questions/3841990/are-there-any-benefits-to-using-a-c-sharp-method-group-if-available) - Stack Overflow
- [Nullable Reference Types](https://devblogs.microsoft.com/dotnet/nullable-reference-types-in-csharp/) - Microsoft Docs
- [Kentico Xperience Design Patterns: MVC is Dead, Long Live PTVC](https://dev.to/seangwright/kentico-xperience-design-patterns-mvc-is-dead-long-live-ptvc-4635)
- [C# Expression Bodied Member](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/expression-bodied-members#methods) - Microsoft Docs
- [XperienceCommunity.CQRS](https://github.com/wiredviews/xperience-community-cqrs) - GitHub

---

<figcaption>Photo by <a href="https://unsplash.com/@jordanmadrid">Jordan Madrid
</a> on <a href="https://unsplash.com">Unsplash</a></figcaption>

---

We've put together a list over on [Kentico's GitHub account](https://github.com/Kentico/Home/blob/master/RESOURCES.md) of developer resources. Go check it out!

If you are looking for additional Kentico content, checkout the Kentico or Xperience tags here on DEV.

{% tag kentico %}

{% tag xperience %}

Or my [Kentico Xperience blog series](https://dev.to/seangwright/series), like:

- [Kentico Xperience Xplorations](https://dev.to/seangwright/series/8185)
- [Kentico Xperience MVC Widget Experiments](https://dev.to/seangwright/series/9483)
- [Bits of Xperience](https://dev.to/seangwright/series/8740)