How to Avoid Duplicate 404 Code in .NET Core APIs - Part 2

How to Avoid Duplicate 404 Code in .NET Core APIs - Part 2

Part 1: https://thedoodledad.hashnode.dev/how-to-avoid-duplicate-404-code-in-net-core-apis-part-1

Taking Advantage of TypeFilterAttribute

Last time we looked at how to make NotFound entities much simpler, by using the IAsyncActionFilter. However, even with this pattern we still need to write a NotFound filter for each top-level entity. This means we need to write this same function over and over just with different types. We also saw in the last example the challenge of needing to ensure the id name stays the same in each controller. This is where the TypeFilterAttribute comes in! Lets take a look at the code for this:

entity_not_found.png OK now what does this code actually do?

  • We pass in a type argument so we know which type we are going to be using to allow the repository to pull back the right entity.
  • Next we pass in idName which solves the problem of having to worry about naming the ids the same in every controller (we can now use id in one endpoint and bookId in another endpoint).
  • Now we have the IAsyncActionFilter again which is the same functionality as before except that it takes in the type we passed in.

You might be wondering why we need the TypeFilterAttribute and cannot simply use the IAsyncActionFilter here. The reason is that the IAsyncAcrtionFilter does not allow us to pass in parameters like this, which means we would not be able to pass idName.

Controller Code

Now that we have looked at the new generic implementation, let's take a look at what we put in the controller to make this work.

entity_not_found_controller.png Notice here we do not need the ServiceFilter and we can actually pass parameters in here. This makes things much cleaner since we can now use this for books, authors, and libraries instead of having one NotFound class per entity.

Further Points to Consider

There are some more pieces we need to think about here:

  • What if some of our entities do not use int for their id? This would obviously make things more difficult, but we can still make this work by passing in the type of the id to the TypeFilter.
  • How do we handle the more complex entities where it's a combination of ids? These would be a bit more difficult to achieve, though there is potential that it could be done. However these are less of a concern since we are checking for our top level entities much more than these more complex join entities.

What's Next?

Next we will be looking at how to prevent calling the repository method twice every time we have to check for NotFound. We do not want to be making extra database calls whenever it can be avoided. In the next section we will look at how we can prevent these duplicated calls.