The Get Request is something we can’t miss while creating API because it is the most common request. So, it is very important to learn more about handling that kind of request.

In the previous post, we have created a repository pattern for collecting the data from the database.

Now, it is time to use that repository for the business logic.

We are going to keep all the database logic inside the repository classes. Controllers will be responsible for handling requests, model validation and returning responses to the frontend part of the application.

By doing so, our controllers won’t be overwhelmed with the code thus making the code easier to read and maintain as well.

If you want to see all the basic instructions and complete navigation for this series, please follow the following link: Introduction page for this tutorial.

For the previous part check out: Creating .NET Core WebApi project – Repository pattern in .NET Core

The source code is available for download at .NET Core, Angular and MySQL. Part 5 – Source Code

This post is divided into several sections:

Controllers and Routing in WEB API

To create a controller, right-click on the Controllers folder inside the main project and Add/Controller. Then from the menu choose API Controller - Empty and name it OwnerController.cs:

Adding owner controller

Our controller should look like this:

Every web API controller class inherits from the ControllerBase abstract class that provides all the necessary behavior for the derived class.

Also, above the controller class we can see this part of code:

This represents the routing and we will talk a little bit about the routing inside Web APIs.

Web API routing routes the incoming HTTP requests to the particular action method inside the Web API controller.

There are two types of routings:

  1. Convention based routing and
  2. Attribute routing

Convention based routing is called that way because it establishes a convention for the URL paths. The first part makes the mapping for the controller name, the second part makes the mapping for the action method and the third part is used for the optional parameter. We can configure this type of routing in the Startup class in the Configure method:

convention based routing http get requests

Attribute routing uses the attributes to map the routes directly to the action methods inside the controller. Usually, we place the base rout above the controller class, as you can notice in our Web API controller class. Similarly, for the specific action methods, we create their routes right above them.

GetAllOwners GET Request in .NET Core

So let’s start.

First, let’s change the base route from: [Route("api/[controller]")] to: [Route("api/owner")]. Even though the first rout will work just fine, with the second example we are more specific to show that this routing should point to the OwnerController.

Now it is time to create the first action method to return all the owners from the database.

In the IOwnerRepository interface create a definition for theGetAllOwners method :

Then implement that interface inside the OwnerRepository class:

Finally, we need to return all the owners by using the GetAllOwners method inside the Web API action.

The purpose of the action methods, inside Web API controllers, is not only to return the results. It is the main purpose, but not the only one. You need to pay attention to the status codes of your Web API responses as well. Additionally, you’ll have to decorate your actions with the HTTP attributes which will mark the type of the HTTP request to that action.

You can read more on HTTP and find some HTTP request examples in part 1 of our HTTP series.

Finally, let’s modify the OwnerController:

Let us explain this code a bit.

First of all, we inject the logger and repository services inside the constructor. Then by decorating the GetAllOwners action with [HttpGet] attribute, we are mapping this action to the GET request. Finally, we use both injected parameters to log the messages and to get the data from the repository class.

The IActionResult interface supports using a variety of methods, which return not only the result but the status codes as well. In this situation, the OK method returns all the owners and also the status code 200 which stands for OK. If an exception occurs, we will return the internal server error with the status code 500.

You can read more about status codes by reading The HTTP series – References

Because there is no route attribute right above the action, the route for the action GetAllOwners will be api/owner (http://localhost:5000/api/owner).

Code Permissions and Testing the Result

We would like to point out one more thing inside GetAllOwners action. Right now, if you look at the repository structure, its classes inherit from the abstract RepositoryBase<T> class and also from its own interface which then inherits from the IRepositoryBase<T> interface. With this hierarchy in place, by typing _repository.Owner. you are able to call the custom method from the OwnerRepository class and also all of the methods from the abstract RepositoryBase<T> class.

If you want to avoid that type of behavior and to allow actions inside the controller to call only methods from the repository user classes, all you need to do is to remove IRepositoryBase<T> inheritance from IOwnerRepository. Consequently, only repository user classes will be able to call generic methods from RepositoryBase<T> class. Likewise, action methods communicate only with repository user classes.

It is all up to you, how you want to organize your code and permissions.

To check the result, we are going to use the Postman tool to send requests towards the application.

Also, you can learn more about how to consume web API programmatically using C# by reading A few great ways to consume restful api in c#.

Let’s start the application, start the Postman and create a request:

get all owners http get requests

Excellent, everything is working as planned.

Before we continue, we would like to show you one more thing. If you look at the model classes, you’ll notice that all properties have the same name as the columns they are mapped to. But you can have the property with a different name than the column it points to, and still to map each other. To achieve that you need to use attribute [Column]

So, let’s do something like that.

We are going to change the property names from AccountId and OwnerId to just Id in the Owner and Account classes. Also, we are going to add the [Column] property which will map the Id property to the right column in the database:

Now let’s continue.

Using DTO and AutoMapper

DTO or Data Transfer Object serves the purpose to transfer data from the server to the client. That is exactly what are we going to use it for.

If we take a look at the GetAllOwners action, we can see that we use the model Owner class to fetch the data from the database (_repository.Owner.GetAllOwners()returns a list of  Owner objects) and also to return that result to the client. And that is not a good practice. A much better practice is to have a model class to fetch the data from the database and to have a DTO class to return that result to the client. The DTO object could be exactly the same as the model object but still, it is much better to use DTO objects because if something changes in the database the model class must change but that doesn’t mean that the client wants changed results. Thus the DTO object will not change.

Having that said, let’s create a new folder DataTransferObjects in the Entities project and let’s create OwnerDto class inside:

As you can see, we don’t have the Accounts property, because we don’t want to show that information to the client right now.

Now, all we would have to do is to map a returned list of owners from the database to the list of ownerDto. But, doing that manually is a boring job and if we have twenty or even more properties in our DTO class, it would be time-consuming as well. Luckily for us, there is a great tool that could help us a lot in the mapping process. Yes, it is AutoMapper.

Working with AutoMapper

AutoMapper is a library that helps us mapping different objects. To install it, we have to type this command in the Package Manager Console window:

PM> Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection

After the installation, we have to register it in the ConfigureServices method in the Startup class:

services.AddAutoMapper(typeof(Startup));

Now, we have to create a mapping profile class to tell AutoMapper how to execute mapping actions. So, let’s create a new class MappingProfile in the main project and modify it:

Finally, we can modify the OwnerController:

We can send the same request from Postman and we are going to get the same result (without accounts), but now, with much better implementation. AutoMapper has great capabilities and you can learn more by reading Getting Started With AutoMapper in ASP.NET Core.

GetOwnerById GET Request in .NET Core

To continue, let’s modify the IOwnerRepository interface:

Then, let’s implement the interface in the OwnerRepository.cs:

Finally, let’s change the OwnerController:

We are going to use the Postman to send valid and invalid requests to check the results:

valid postman request http get requests

Invalid request:

invalid request http get requests

Owner Details Request

Let’s continue by creating a logic to return the owner object with its account details.

First, we need to create the AccountDto class:

Then, we have to modify our OwnerDto class that will help us return the owner with all related accounts to it. If you want you can create additional DTO class with name OwnerWithAccountsDto, but for the sake of simplicity, we are going to modify the existing DTO class:

Notice the property Accounts which will bind all the accounts related to the certain owner. 

Let’s modify the interface accordingly:

Also, let’s modify the repository class:

We are using the Include method to include all the accounts related to the current owner.

We have to add two additional mapping rules in the MappingProfile class:

Finally, let’s modify the controller:

Result:

ownerdetails http get request

We have created these actions that use Repository Pattern logic synchronously but it could be done asynchronously as well. If you want to learn how to do that you can visit Implementing Async Repository in .NET Core. Although we strongly recommend finishing all the parts from this series for an easier understanding of the project’s business logic.

Conclusion

Requests using GET should only retrieve the data from the database, and all the actions inside the OwnerController class are written like that.

By reading this post you’ve  learned:

  • How to work with a controller class
  • What is routing and how to use it
  • How to handle GET requests in a web API
  • The way to use DTO’s while handling requests

Thank you all for reading and I hope you found something useful in it.

In the next article, where we are going to apply the same principles learned here to support the POST, PUT and DELETE requests in our application.

If you have enjoyed reading this article and if you would like to receive the notifications about the freshly published .NET Core content we encourage you to subscribe to our blog.