Microsoft’s ASP.Net Web API 2.2 allows you to easily create REST style APIs on an IIS website. Microsoft has some great documentation on how to get started with it, so I won’t rehash that here. Instead, I’m going to go a little deeper into some powerful features that can be used with Web API.
- Part 1 - Customizing auto-generated documentation
- Part 2 - HTTP Response Codes
- Part 3 - HTTP Error Codes from Exceptions
- Part 4 - OData URL Query Options
- Part 5 - DTO Transformations and Automapper (this article)
- Part 6 - Testing with EF Rollbacks across HTTP
First, off what is this DTO thing? A Data Transfer Object is an object structure that you use to transfer data across the wire. Sometimes it will look exactly like your entity framework entities. Sometimes it will be different.
For example, suppose you have a database with Customers and Invoices, and your tables look like this:
These are also what your Entity models look like, because entity models reflect the database structure.
Now suppose that you want to provide an API endpoint that returns a list of customers in a particular city with the number of invoices for each customer.
The data you want to return from your API looks like this:
This is your DTO. You can make out where the data comes from in your database, but there is no table structure in your database that has this exact collection of fields, and thus no entity model that looks exactly like this. You will need to retrieve the data from your database and then map/transform it into this structure.
How do you map your data? You can do it manually.
// Get the customers from the database
This works. But it will become tedious very quickly - you will be writing many, many lines of code that do nothing more than copy a property from an entity to a DTO (and for POSTs/PUTs, you’ll do the same in reverse).
Enter Automapper. It is designed specifically to relieve you of this tedium. It involves two steps:
1. Setup Automappper. This can be done once in a centralized location for your entire application. Here is the basic mapping setup:
// Customer is your Entities Customer class, and CustomerDTO is,
Assuming that the property types and names on the two classes match, Automapper can figure out how to copy properties from one to the other. However, we have one property that can’t be directly copied - the
InvoiceCount property. Thankfully, Automapper has a way to help us manually map properties. We just extend the mapping definition a little:
ForMember() call, we’re telling Automapper that when it sees the
InvoiceCount property on the DTO, it should populate the property by calling
Invoices.Count() on the object it’s copying things from. The rest of the properties are figured out automatically.
2. Use Automapper to perform the mappings.
To map a single item:
CustomerDTO customerWithInvoicesCounted = Mapper.Map<CustomerDTO>(customer);
This is nice and simple - there is no need to manually map every single property. However, it’s slightly different when you’re dealing with a collection of items. If you have an
IQueryable of customer entities, and you want to ‘preserve the
IQueryable‘ if you will, Automapper can still help. Continuing with our example above, where we want to find customers from a specified city and the number of invoices they each have, you can map the data like this:
// Get the customers from the database
Notice what’s going on here - Automapper has just mapped your
IQueryable<Customer> into an
IQueryable<CustomerDTO> using the mapping instructions defined above. You can then perform a query on this
IQueryable<CustomerDTO>, and the query will be executed on your SQL server. Furthermore, if OData URL Query options are turned on, you can return this
There are some limitations on what can be projected in this way - see the ‘Supported Mapping options’ section at the bottom of https://github.com/AutoMapper/AutoMapper/wiki/Queryable-Extensions for details.