ASP.NET Core 2.0: Input Validation - Creating a Problem Factory

When creating Web APIs we create endpoints that people can use to interact with our Web Service. Often these endpoints will have a parameter that we can enter as part of the request. These parameters that someone can enter are what we want to make sure we validate on. We don’t want to be passing around input values that are not what we are expecting. We want to gracefully handle invalid values.

Handling Invalid Input

We could easily handle invalid inputs inside our controller by adding an if statement that checks for a null or empty then simply returning a 400 Bad Request. While this is perfectly acceptable for certain projects, often when we create Web APIs, we will have more then one endpoint that will need validating. If this is the case, then creating a Problem Factory could be the way to go.

Problem Factory

What is a Factory

I will be writing a blog series on design patterns that will include factories, what they are and how they are used. In the meantime if you are unsure on what a factory is and want to know more, head along to the following link. https://www.dotnetperls.com/factory

What is a Problem Factory

A Problem Factory holds a set of problems with each problem assigned different details about the problem.

The details can include but are not limited to Title, Status, Detail. When we encounter a problem that we are checking for, the person making the request is returned these details back.

It gives us an opportunity to return more detail back to the person making the request then simply returning a Bad Request.

While we could return all this detail inside our controller, as you can imagine, our controller will start to get quite large. The controller is also doing to many things. Our aim when writing code is to keep it clean, readable and to make sure we are seperating out each concern.

Implementing the Problem Factory

The first thing we need to do when implementing our problem factory is to

Add a question mark (?) to {searchCritera} this will make the searchCritera nullable.

If we didn't do this, then when we try and hit our endpoint without any searchCritera, it wouldn't find our route.

We need to make it nullable in order to hit our route without searchCritera.

[HttpGet]
[Route("v1/giphy/random/{searchCritera?}")]

We then add an if statement to our GetRandomGif Method. This if statement will check for IsNullorEmpty.

In the ProblemFactory we will add our first problem that we want to return back to the user, MissingPayLoad.

public Problem MissingPayLoad(string value)
{
return new Problem
{
Title = "Payload is not well formed or was not provided",
Details = $"Missing Data {value}",
StatusCode = HttpStatusCode.BadRequest
};
}

The ProblemFactory is where we would add all of our problems, while we have one at the moment, often you would have more then one, such as UnexpectedError, that would return a status code of 500

Heading back to the GiphyController, make sure you add the reference the ProblemFactory.

Lastly we need to make sure that our IProblemFactory and ProblemFactory are added to the ConfigureServices method in the startup.cs, so we are able to use dependency injection and inject our interfaces in the classes that use them.