Today’s header image was created by Mike Wilson, the original source for the image is available here

Stop!

Hammer time?

This is the third in a series of blog posts related to building a WebApi application.

If you haven’t read the previous parts, I’d recommend starting there.

Let’s Go

If you remember, last time we built a basic WebApi application, added Entity Framework Core, added a DbContext, and a service. In this post we’ll build on that application.

What We’ll Be Doing

In this post we’ll:

Create the Character class

Create the Character service

Create the Controller to handle GET requests for Characters

Do a little refactoring

Create the static POCO to transform Character data models into Character view models

Create the static POCO to transform Book data models into Book view models

As with the previous parts in this series, I’ve already uploaded all of the code to a GitHub repository. You can head over there if you want to take a sneak peak at what we’re going to create in this tutorial.

Also, as with the previous part in the series, I’m not going to be including Visual Studio specific steps for this tutorial.

You can read about why, here.

Running the Service

The first thing I would recommend that you do is make sure that the code from last time still runs. So cd into the src directory and issue the run command:

Then head over to ‘http://localhost:5000/Books/Get/1’ in your browser:

If something doesn’t go quite right, then take a quick look at the the previous part of this series, or clone the code from the GitHub repository for this part of the series.

Creating The Character Data Model

Cast your mind back to the first part in this tutorial series and you might remember our entity relationship diagram:

Ignoring the Books and BookCharacters tables, our Character table looks really quite simple: just a primary key (which is an integer) and a string.

As long as you ignore the audit fields (Created and Modified) for now, too. We’ll get to them next time.

Over in the Models directory, you’ll need to add a file called “Character.cs” and paste the following code into it:

We’ve seen all of this before (in the form of our Book model), so let’s go build the Service.

Creating The Character Service

The Character service will be quite similar to the Book service. Just like the Book service, we’ll need an interface (ICharacterService) so that we can consume it via Dependency Injection and an implementation of it (CharacterService).

Head over to the Services directory, create a file called “ICharacterService.cs” and paste the following code into it:

Then create a file called “CharacterService.cs” and paste the following code into it:

Almost all of this service is similar to the Book service, except for one key difference: the Book model has an ordinal, whereas our Character model does not.

Because of this key difference, we’re not ordering the results returned from the search method.

Not that it would make much of a difference if we did. Although, we could order them by name if we wanted.

Transforming Our Data Models to View Models

Before we go ahead and create our Character controller, we’re going to do a little refactoring and create some extension methods to create instance of Character View Models from our Character Data Models.

In a real world application, especially where your Data Model has navigation properties,

In Entity Framework, navigation properties represent the foreign key relationships between tables.

you won’t want to pull all of the data related to a record and display it on the view.

Looking at our ERD again for a moment

We have a foreign key from the Books table to the BookCharacters table (this will be our join table, when we cover those), and one from the Characters table to the BookCharacters join table.

We haven’t covered this yet, but we will in the next tutorial.

So, if we wrote a service to get all of the BookCharacter entries, Entity Framework would pull all of the Character and Book records for each entry in the BookCharacters table. This isn’t so bad in our example, because the data set will be quite small.

But imagine that you have a Data Model which represents Students, Parents, Exams and Grades:

If we wanted to create a page in the system where we listed every student by name, we could write a service that would return all of the student records. But Entity Framework (by default) would give us all of that student exam and parent data, too. That could end up being a massive amount of data to send to the view, if we didn’t strip those navigation properties out.

That’s one of the reasons why we have separate view and data models.

There are other reasons, but for the purposes of this example we’ll focus on that one reason.

So you can (hopefully) agree that it’s good practise to send only the data that we want to display, over to the view. Traditionally, you might achieve this with a library like AutoMapper or any of it’s alternatives. But our data models are quite small and we can do it much quicker by hand writing the conversion methods ourselves rather than relying on AutoMapper, reflection or boxing.

The Character and Book View Models

Our View Models aren’t going to be that dissimilar to the Data Models (but they will change a little once we’ve added the join table), but it’s good practise to separate them out. So let’s do that.

Create a sub-directory within your src directory called “ViewModels”

Within here create a new file called “BaseViewModel.cs”, this will be an abstract class that we’ll use when we refactor our controllers.

But more on that in a moment.

Paste the following code into the BaseViewModel.cs file:

Now create a file (in the same ViewModels directory) called “BookViewModel.cs”, and paste the following code into it:

And finally, do the same for a file called “CharacterViewModel.cs”, pasting the following code into it:

Looking at the View Models and comparing them to the Data Models, you should notice that the only differences between them is the lack of the primary key in the View Model. We really don’t need to display this to the user, so we won’t include it.

Instantiating the Character and Book View Models from DB Models

To instantiate our View Models from the Data Models, we’ll use some helper classes.

We could do the instantiation, inline, within the controllers but we’ll extract the logic to Helper methods. That way, if anything changes

Like, for instance, once we’ve added the join table and navigation properties.

then we only have to change the methods that do the instantiation, rather than the controller methods.

For an interesting discussion on how much Business Logic should happen in controllers, see this Stack Exchange question.

To that end we’ll need a new sub-directory within the src directory, this time called “Helpers”.

Within this directory, create a file called “BookViewModelHelper.cs” and paste the following code into it:

This static class has two methods: “ConvertToViewModel” and “ConvertToViewModels”.

Here we’re creating a single Book View Model instance from a Book Data Model instance. The conversion is pretty simple, we take the Book Data Model and populate the fields on a new Book View Model instance with the data from the Data Model.

I feel like I should write Data Model one more time, here.

Here we’re Creating a List of Book View Models from a list of Book Data Models. We do this by using a Lambda expression to iterate over the List of Data Models, passing each into the other method in this class, and populating a List of Book View Models.

If you’re not particularly familiar with Lambda expressions in C#, I’d recommend that you read this DotNetPerls article to get up to speed.

Now do the same for a “CharacterViewModelHelper.cs” file, but paste the following code into it:

This helper class works in much the same way as the BookViewModelHelper class, but by creating new instances of Character View Models from Character Data Models.

The Character Controller

Before we add the Character controller, we need to think about possible duplication of code. We already have a Book controller and that contains the following method:

But we might want this method available to our Character controller.

Spoiler: we definitely want this method in our Character controller.

So how can we do this? Why not use inheritance and boxing?

Even though we’ll take a slight performance hit due to the nature of boxing.

Base Controller

We can create base controller (which inherits from the MVC Controller class) and we can inherit from this base controller in both the Book and Character controllers.

And any others that we create, going forward.

In the Controllers directory, create a file called “BaseController.cs” file and paste the following code into it:

We’ll cover the SingleResult and MultipleResults methods in a moment.

Now we need to tell the Book controller to inherit from our BaseController:

We’ll now need to remove the ErrorResult method from the bottom of the Book controller too, as we’re already declaring it in the BaseController.

SingleResult and MultipleResults

Let’s take a look at the other two methods in the BaseController (SingleResult and MultipleResults)

Each method deals with instances of the BaseViewModel.

Here’s the slightly canny thing about the BaseViewModel: it’s an abstract class that both the BookViewModel and CharacterViewModel inherit from. This means that we can pass in an instance of either the BookViewModel or the CharacterViewModel and, through the magic of inheritance and boxing, the method will just work.

By the way: “Canny” can mean shrewd, wise or intelligent – in case you didn’t know.

Even though (as I’ve mentioned earlier) we’ll take a hit on performance due to the nature of boxing and unboxing. But the data here is relatively small, so we should be ok.

Let’s use it in our BooksController (before creating the CharacterController). You’ll need to alter your GetByOrdinal and Search methods within the BooksController to match the following:

Character Controller

Create a new file called “CharactersController.cs” in the Controllers directory, and paste the following code into it:

Pretty much everything we’re now doing in the CharactersController matches what we’re doing in the BooksController. The only differences being the services we’re calling (and the models we’re dealing with) and that the fact that the CharactersController doesn’t get by Ordinal.

Injecting the Character Service

In our CharacterController, we’ve relying on dependency injection to get an instance of the ICharacterService. We’d better make sure that .NET Core has access to the ICharacterService. So head over to your Startup.cs file and add it:

I’ve highlighted the line you need to add.

Adding Another Migration

Because we’ve changed the model (we’ve added the Character class), we need to add a new migration. Before we do that, we’d better make sure that there aren’t any build errors.

In the terminal, cd into the “src” directory and issue the following command:

Assuming that there are no build errors,

And if there are, take another look through the above steps. I’m writing the code as we go along here, so everything should work if you’ve pasted the code in as it is.

issue the following command to add our migration:

This will add a new migration to your Migrations directory which should look like this:

Now that we’ve added our migration, we need to tell Entity Framework Core to apply the migration, so run the following command:

This will do the magic of converting the Migration into SQLite statements, which will be run against our database.

Seeding the New Data

The last thing we need to do before we run the application is to ensure that we seed our Characters table. If you take a look at our “dwExtensions.cs” file, you should see a method called EnsureSeedData. We’re going to edit that method to seed our character data.

Remember this method is called whenever we start the application, to ensure that we have some data.

You’ll need to paste the following into the EnsureSeedData method:

I’ve highlighted the lines that you need to change.

The last thing we need to do is create the GenerateAllCharacterEntities method (which the EnsureSeedData method will now call). This method exists at the bottom of the dwExtensions class (but you can paste it anywhere within that class) and looks like this:

As with the Books table, we’re only going to seed a subset of the data for now.

Once you’ve added these all that’s left to do is run the application and check out our hard work:

This should start the application, and you should see a bunch of SQLite commands go by (which will be seeding our Characters table). Once the application has started, point your browser at “localhost:5000/Characters/Get/1”

Swapping out “localhost:5000” for the host and port that .NET Core give you (the default is localhost:5000)

And you should get a response that looks like this:

Taking a look at the database itself, you should be able to see the new table and the seed data:

Again, Entity Framework doesn’t guarantee that the data we’ve added to the DbSet (in the GenerateAllCharacterEntries method) will be persisted to the database in the same order that we added them to the DbSet. So yours might be in a slightly different order.

Conclusion

We’ve added a new service, Data Model type, Controller and View Models. We’ve added Helper methods to create instances of the relevant view models from a given data model. We’ve refactored our controllers to include a base controller and we’ve seeded our database with more data.

Not necessarily all in that order, though.

Next time, we’ll take a look at adding Shadow Properties, how EF Core handles Many to Many relationships and a better way to seed the database.