A Simple Organization for ASP.NET Web API Producer/Consumer Apps

My team regularly writes ASP.NET Web API projects which have multiple consumers, and oftentimes we also write at least one of said consumers. To accomplish this, we often invoke a project layout and architecture that doesn't seem terribly obvious to newcomers to my group. I hope to better explain myself as to why this project organization works in this post (so I can just say, "Hey, new guy, lookie here!" and point them at this post.)

Sample Architecture

So, let's get the spoilers out of the way first: this architecture works because both the API and the MVC app use a common library of DTO objects. In this way, whenever an object being returned from the API is deserialized from its JSON representation, the MVC app knows what object to deserialize it to. This is directly a benefit of being in charge of both producer (the API) and consumer (the MVC web project).

The Common project holds what are known as the DTOs (Data Transfer Objects). The DTOs do nothing but move data from one place to another; they will not ever have any methods or logic contained within them.

Once we have a place to put the DTOs, we can begin building the API which uses them.

Building the API

Let's now see how we might build both the DTO objects and the API which serializes them to JSON. First, here's a sample User class:

Now, to prove this works, we can call this action using something like Postman:

As we would expect, calling the path /users/all results in us getting back the list of users.

Now let's see how we might build an MVC web app to consume this API call.

Building the MVC API Client

The MVC app will use the brilliant NuGet package RestSharp to simplify our calls to the API. Once we've downloaded the package, we can create a class which derives from that package's RestClient like so:

Finally, all we have to do is run the MVC app and we'll see that the users are returned and displayed exactly as we thought they would be:

Summary

This organization allows both producer and consumer to use the same Data Transfer Objects (DTOs) when serializing to or deserializing from JSON objects. Consequently, both "sides" of the relationship can use the same objects without needing to write and maintain their own definitions.

I understand that this organization is only useful in situations where the developers control both sides of the producer/consumer relationship; but in those situations, it's been invaluable for me and my team.

Don't forget to check out the sample project on GitHub, and feel free to submit suggestions for improvements there or in the comments below.