Member preview

We’re Integrated! Axios, DogeBot & .NET Core API — A Strong Bond

We thought our current user base of 0 might be a little taxing in the future, so as a priority we gave doge the ability to scale endlessly within the azure clouds.


Our users API in action

Hello again! Last post outlined the creation of the project and the initial journey to getting DogeBot to woof his first words (it wasn’t woof). The topic covered today is the initial development into incorporating the npm package Axios into the project and using it to integrate with our .NET Core API, which is now up and running in the azure clouds somewhere. You’re busting at the seams with anticipation so let’s crack on ASAP.

Key Information

  • What is Axios? Axios is a Promise based Javascript library with a primary function to make HTTP requests from node.js or XMLHttpRequests from compatible browsers (ES6 Promise API).
  • Why do we use Axios over Fetch? One of the benefits of using Axios is that we remove the requirement to pass the results of the HTTP request to the .json() function on response — instead the data object will be returned how you expect . Another key benefit is that Axios will successfully execute the .catch() block upon any HTTP request error automatically with no intervention.

Implementation

Using axios in a simple context is extremely straightforward to use, which is a testament to its popularity. To get it within the project we ran ‘npm install axios’ within the terminal, which installs the packages required to the project, then subsequently we imported the module into our ‘base-service.js’ file consumption.

base-service.js

BaseService Class File

So what is this base service file I hear you ask? Well it contains our class BaseService, which is our parent class in charge of initialising the axios instance with our desired config. We do this here because all of our future services will require this instance and therefore it saves a lot of code duplication.

The initAxios method is what runs when the class is first instantiated (see constructor) and ultimately will return a custom configured axios instance for all services to use. This custom configuration I have set up for the axios instance is basic but still powerful and fit for purpose, here is a brief outline of what’s included:

  • Setting our base URL: are setting the base URL of the API we are using (our .NET Core layer), this prevents code duplication as you don’t have to write the base URL of your end points within every request.
  • Access control: We have specified whether or not cross-site Access-Control requests should be made using credentials or not, in this case the false flag has been set.
  • Set request headers: The API layer is expecting a content type of ‘application/json’ when making requests, so we can specify that once here for it to be used across the application.
  • Axios interceptors: These utilities let you intercept requests and responses mid-flight. In this case I am just interested in the status code of the response and the url of the requests for debugging purposes, so I log those to the console.

So with a configured axios service, what do we do with it? Well we now create more specific services that use this axios instance to connect with our external API to retrieve data.

UserService Class File

This class extends from our BaseService that we saw earlier, meaning that it has access to all of its properties and methods including our all important axios instance. Therefore, we can access our axios instance with the ‘this.api’ property, lets take a deeper look at how this will be used.

user-service.js

There are 5 API requests in this file, but we will just cover one in detail as they all follow the same pattern but just with different request types and parameters. Let's take a look at the ‘getUserList’ async method, here we are wrapping an axios API call within a new Promise to control what to return to the caller regarding resolution or rejection.

Past this point it’s very simple, we are using our axios instance (this.api) to make a GET request to our api where the base URL is derived from our configuration and our end point is given as a parameter to the axios instance, in this case it is ‘/users’, which is quite relevant as we want to retrieve a list of all our current users that we have saved in the database. If the call is successful (often represented as status code 200 or 201) we jump into our ‘.then( res => {})’ code block where we have access to the response data.

Response data example:

{ Users:{ { username: ‘Bill’, score: 1000 }, { username: ‘Ben’’, score: 750 }, { username: ‘Bob’’, score: 500 } } }

In this case we convert the response object into an array of users via the method ‘Object.entries()’ and then after some crude iterating and string manipulation we return a formatted string of users and scores via the initial promise resolution (.resolve()). So that is our happy path through the promise — if our call is unsuccessful with status codes 401, 402, 404, for example, then we will jump into our .catch(err =>{}) code block, which as we mentioned earlier is automatic when using Axios but not when using fetch API. From here we can return details about why the request failed to to caller, great for debugging purposes.

So now we have our Base Service and User Service implemented, which will return a list of users when called — lets dive into what is actually calling the method and replying to the user message in the chat channel.

Users Controller

Users.js

We’ve seen this file in the previous post, it controls what actions happen when the user types ‘!users <arguments>’, however it has had numerous changes to accommodate the new service structure regarding sending requests and receiving data from the .NET Core API as opposed to handling it on the node.js client. With the aim of keeping it concise, i’ll summarise what is going on here as we have covered the primary topic with the axios implementation and integration and don’t want to bloat. If you would like to see the code in more detail and what some utility functions shown but not discussed are doing please don’t hesitate to visit the Github repository.

Scenario: Retrieving a user list —

  • User types ‘!users list’ into the discord chat channel
  • The user message gets redirected to our Users.js file where it enters the execute() method as parameter.
  • We process the message and split it into the service call and the arguments. In this case the service call is ‘list’ and there are no subsequent arguments.
  • We execute the method within the Object literal that corresponds to the service request in the message, in this case we want to execute the ‘list’ service.
  • Once we have executed the list service which is the one we detailed in the UserService class earlier, we get a promise returned. From here it is simply extracting the data from the response (.then block), which is the list of users, and sending a formatted message back to the chat channel for the users to see (message.channel.send(‘xyz’)).
The list of users retrieved from the API, processed and sent to the requesting user in the chat channel

Success! That is the end to end process of our integration with the .NET Core API via axios. We didn’t get to talk about the other CRUD functionality we implemented into the User Service but here are a few screenshots which show the results — all inspectable at the github repository.


Further Scenarios!

Updating Gary to have 5000 points, lucky guy.
Creating myself as a user, 0 score though…
Retrieving a single user (Gary again)
Error handling even included to the client when an API call fails

And that’s it!

For this article anyway.. Thank you for reading if you made it this far and hopefully good ol’ DogeBot has made a memorable impact on your day. API integration and the project set up have now been covered and by far are the most lengthy to write about (even after trimming the excess), so whilst I won’t revisit these topics I will post updates when we have added much more advanced functionality that uses the API in nice bite size articles. Additionally, future DogeBot related stories will be covering smaller features such as message cooldown management, in-server user management such as banning or kicking and all that fun stuff!

Please feel free to comment or get in contact if there is any constructive criticism you might want to throw at me regarding the project, I’m always looking to learn from my mistakes and improve my code.

Till next time,

Cheers!

Github: https://github.com/DogeNet

Instagram: https://www.instagram.com/andydwilkinson/