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

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

You will 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, your 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: Part 4 – Creating .NET Core WebApi project – Repository pattern in .NET Core

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

This post is divided into several sections:

Controllers and Routing in WEB API

To create the controller, right click on the Controllers folder inside the main project and add the new item. Then from the menu choose Web API Controller Class and name it OwnerController.cs.

Because we are going to start from the scratch, delete all actions inside controller class to look like this:

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

Also, above the controller class you 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 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. You 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 HTTP GET request

So let’s start.

First, 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 the method GetAllOwners:

Then implement that interface inside the OwnerRepository class:

Finally, you 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.

Modify OwnerController with the following code:

Let me explain this code a bit.

First of all, you inject the logger and repository services inside the constructor. Then by decorating the GetAllOwners action with [HttpGet] attribute, you are mapping this action to the GET request. Finally, you 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 returns 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

I 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 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, 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#.

Start the application, start the Postman and create a request like this:

get all owners http get requests

Click on the picture to zoom in

Excellent, everything is working as planned.

Before you continue, I 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 the 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.

Change property names from AccountId and OwnerId to just Id in the Owner and Account classes. Also, add the [Column] property which will map the Id property to the right column in the database. Your classes should look like this:

Now let’s continue.

GetOwnerById HTTP GET request

Modify IOwnerRepository interface like this:

Then implement the interface in OwnerRepository.cs:

Finally, change the OwnerController like this:

Use the Postman to send valid and invalid requests to check the results.

valid postman request http get requests

Click on the picture to zoom

invalid request http get requests

Click on the picture to zoom

Code refactoring

The code above works great, but could it work even better?

Whenever you can, you should try to avoid returning null as much as possible because null could be the reason for many potential bugs in your code.  So, let’s change the code a bit, to avoid working with nulls.

First, change the repository method:

Right here you did a nice trick. You are no longer returning Null if OwnerId is invalid, but returning the new Owner object with all the default property values inside it.  By doing this you are ensuring that the OwnerId property will always return the new GUID value because the new Owner object is created. With that knowledge it is easy to change owner == null to something different:

This is just one of many solutions you could write. Similarly, you could write different condition or an extension method and then call it like: if(owner.IsEmptyObject()).

DTO and owner details request

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

First, you will create extended owner model (or DTO) which will help you return the owner with all related accounts to it.

In the Entities project create the new folder. Add it a name ExtendedModels and inside it create class OwnerExtended:

You don’t want to touch the Owner model, let’s keep it clean as it is. If you want to add some properties to the model class, you can always create the new extended models as you just did. Notice the property Accounts which will bind all accounts related to the certain owner. Also, there is a constructor which takes the owner object as the parameter and maps it to all properties inside this class. All you have to do is to bind all accounts related to the owner object using the foreign key.

Let’s modify the interface accordingly:

Also, modify the repository class:

You can see the advantage of removing the null value from the GetOwnerById method. Because now if you send a wrong ownerId value, GetOwnerById will always return at least an empty owner object. Thus mapping it into ownerExtended won’t throw an error as it would if it was a null.

Finally, modify the controller:


ownerdetails http get request

Click on the picture to zoom


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 controller class
  • What is routing and how to use it
  • How to handle GET requests in 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.

Stay tuned for the next article, where we will apply the same principles learned here to support the POST, PUT and DELETE requests in our application.

For any suggestions or questions, don’t hesitate to leave the comment in the comment section below.