At Optimove, we’re shifting our architecture from monolith to micro-services.
Why are we undergoing this transition? Our motivation comes from wanting to deploy and deliver small pieces of code to production, without depending on other components or teams. Thus, the cycles will become much shorter and the quality – much higher.
We’re currently using .Net Core, swagger, and docker for this task. In this blog post, we will cover some basic concepts that will help you create an API used as a micro service, utilizing .Net Core.
We’ll create a basic API with a customized response.
But let’s back up for a moment; what is a micro service? And why do we want to create one?
What are Micro-services?
To help you grasp the concept, I’ve posted some quotes about micro-services below:
“A distinctive method of developing software systems that tries to focus on building single-function modules with well-defined interfaces and operations” (Smarbear)
“A micro-service is a self-contained piece of business functionality with clear interfaces, and may, through its own internal components, implement a layered architecture” (Wikipedia)
Why use Micro-services?
Micro-services have several benefits. They’re:
Simple to deploy
Easy to scale
Simple to understand
Easy to find (and isolate) bugs
Loosely coupled
Testable
And many more
Of course, there are a few downsides to microservices:
They require cultural changes and aren’t backward compatible
There are security challenges due to inter-service communication system-wide
Two popular tools that will help us build our micro-service are Docker and Swagger. Let’s delve into both.
Docker
“In simple terms, Docker is a software platform that simplifies the process of building, running, managing and distributing applications. It does this by virtualizing the operating system of the computer on which it is installed and running.” (FreeCodeCamp)
“Docker is a tool designed to make it easier to create, deploy, and run applications by using containers. Containers allow a developer to package up an application with all of the parts it needs, such as libraries and other dependencies, and ship it all out as one package.” (Noteworthy)
Swagger
Swagger is the most widely used tooling ecosystem for developing APIs with the OpenAPI Specification (OAS). Swagger consists of both open source as well as professional tools, catering to almost every need and use case.
Basically Swagger is great for API documentation, testing, and helping create both server projects in the language of your choice as well as client SDK projects.
This example will make it
clearer:
API documentation:
Testing your API via the comfortable UI:
Once you’ve designed your API, you can generate both server and client code to get started.
In an approach called Design first, you begin with your API design and generate the code from the design.
But what if you want to write your code first and then create a Swagger documentation?
A Code first approach is the more traditional route. Once the API is directly coded, you can generate a Swagger document using different tools, such as Swashbuckle.
Now, let’s combine the above tools and create a basic micro-service using the Design-First approach.
Let’s start with creating a
simple API generated from Swagger.Once you open a Swagger editor, there are several options:
Use the Swagger plugin for Visual Studio Code (ctrl+shift+p Swagger editor)
2. I created a very basic API with 3 calls and 2 modules:
This is the YAML code:
swagger: “2.0” info: description: “This is a demo for a basic micro service” version: “1.0.0” title: “Micro-Service demo” termsOfService: “http://swagger.io/terms/” contact: email: “[email protected]” license: name: “Apache 2.0” url: “http://www.apache.org/licenses/LICENSE-2.0.html” host: “dummy-api.com” basePath: “/v2” tags: – name: “actors” description: “Data about actors” externalDocs: description: “Find out more” url: “http://swagger.io” – name: “movies” description: “Data about movies” – name: “status” description: “API status” schemes: – “https” – “http” paths: /actors: post: tags: – “actors” summary: “Add a new actor” description: “” operationId: “addActor” consumes: – “application/json” produces: – “application/json” parameters: – in: “body” name: “body” description: “Actor object that needs to be added to the DB” required: true schema: $ref: “#/definitions/Actor” responses: 405: description: “Invalid input” /actors/{actorId}: get: tags: – “actors” summary: “Find actor by ID” description: “Returns a single actor” operationId: “getActorsById” produces: – “application/json” parameters: – name: “actorId” in: “path” description: “ID of actor to return” required: true type: “integer” format: “int64” responses: 200: description: “successful operation” schema: $ref: “#/definitions/Actor” 400: description: “Invalid ID supplied” 404: description: “Actor not found” security: – api_key: [] /status: get: tags: – “status” summary: “return API status” description: “Returns a single actor” operationId: “getStatus” produces: – “application/json” responses: 200: description: “API is OK” schema: $ref: “#/definitions/ApiStatus” 404: description: “API not found” security: – api_key: [] securityDefinitions: imdb_auth: type: “oauth2” authorizationUrl: “http://imdb.swagger.io/oauth/dialog” flow: “implicit” scopes: write:imdb: “modify movies and actors in your account” read:imdb: “read your movies and actors data” api_key: type: “apiKey” name: “api_key” in: “header” definitions: ApiStatus: type: “object” properties: message: type: “string” description: “API Status” Actor: type: “object” required: – “id” – “firstName” – “lastName” properties: id: type: “integer” format: “int64” firstName: type: “string” example: “Ryan” lastName: type: “string” example: “Gosling” xml: name: “Actor” externalDocs: description: “Find out more about Swagger” url: “http://swagger.io”
This is how it looks:
3. Click on ‘Generate Server’ and click on your chosen language to export the server stub:
I chose aspnetcore, but of course, you can choose any language.
4. Using the command line, go to the project folder and open it in Visual Studio Code, using: ‘code .’ command.
5. Go to /src/IO.Swagger/Controllers/StatusApi.cs
Look at this method:
Let’s change the response to something more personalized:
public virtual IActionResult GetStatus() { //TODO: Uncomment the next line to return response 200 or use other options such as return this.NotFound(), return this.BadRequest(..), … ApiStatus res= new ApiStatus(); res.Message=”The Notebook is great and the API is up!”; return StatusCode(200, res); {
6. Open Terminal (Terminal->New Terminal) or CTRL+Shift+’ and run build command: donet build
Now, let’s look at the dockerfile. You can find it here:
In order to create an image, we need to run the docker file:
7. Let’s take a look at the images. Use this command:
sudo docker images
8. Run the docker image so that you can access the API via localhost:
Go back to Visual Studio code and write:
sudo docker run -d -p 3003:80 –name imdblocal imdb-demo:1.0.0
We chose port 3003 to access the API
‘Imdblocal’ is the name of this certain instance
9. Let’s go to localhost/3003
Click on /status:
And then ‘Try it out!’
This is the custom response we wrote.
We can also access it with this Url:
Localhost:3003/v2/status
Code First
If you still want to use the code-first approach (If you already have an API code ready, or just prefer to write it from scratch), you can use a tool to help you generate your API Swagger documentation.
Using Swagger and .Net Core, we learned how to easily create a basic API project. We Created a Docker image and ran it so we can access our service via localhost. Stay tuned, next time, we’ll discuss deploying to production!
Rima Granovsky has been working as a Software Developer at Optimove for the last four years (and counting). She has a BSC in Information System Engineering from Ben Gurion University. Among other projects, she leads the development of APIs.