<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ahmet Küçükoğlu</title>
    <description>The latest articles on DEV Community by Ahmet Küçükoğlu (@ahmetkucukoglu).</description>
    <link>https://dev.to/ahmetkucukoglu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F185345%2Fbfb086d2-bb17-4f59-9235-30e64f3275f1.jpeg</url>
      <title>DEV Community: Ahmet Küçükoğlu</title>
      <link>https://dev.to/ahmetkucukoglu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ahmetkucukoglu"/>
    <language>en</language>
    <item>
      <title>What is Modular Monolith?</title>
      <dc:creator>Ahmet Küçükoğlu</dc:creator>
      <pubDate>Wed, 09 Mar 2022 15:48:51 +0000</pubDate>
      <link>https://dev.to/ahmetkucukoglu/what-is-modular-monolith-4ej8</link>
      <guid>https://dev.to/ahmetkucukoglu/what-is-modular-monolith-4ej8</guid>
      <description>&lt;p&gt;This article was originally published at: &lt;a href="https://www.ahmetkucukoglu.com/en/what-is-modular-monolith"&gt;https://www.ahmetkucukoglu.com/en/what-is-modular-monolith&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Traditional Monolith
&lt;/h3&gt;

&lt;p&gt;Firstly, let's talk about Traditional Monolith approach. This approach focuses on layers. It includes three layers, UI, Business and Data. All features in a project are vertically separated into these layers. Among those three layers, the business layer is the one that contains business logics of all features. Each feature knows business logic of other features, which is a fact we call tightly coupled.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XobhL0mL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2022/03/TraditionalMonolith.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XobhL0mL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2022/03/TraditionalMonolith.png" alt="Traditional Monolith" width="219" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Modular Monolith
&lt;/h3&gt;

&lt;p&gt;The main focus of Modular Monolith is to separate modules. Each module has its own layers ( Domain, Infrastructure and API etc.). Thus, they can use different database solutions. On the other hand, modules don’t share their own business logics with each other. They can communicate with each other with sync or async approaches. These approaches are called loosely coupled.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KjKSPmD8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2022/03/ModularMonolith.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KjKSPmD8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2022/03/ModularMonolith.png" alt="Modular Monolith" width="601" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Modular Monolith has a single binary. Therefore, apps that implement Modular Monolith can’t be scaled horizontally. Also modules are separated logically, not physically. So Modular Monolith doesn’t have a physically distributed structure. If we want to physically separate it, we have to implement the microservice approach.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3EpyyJ5F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2022/03/PhysicalLogicalArchitectures.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3EpyyJ5F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2022/03/PhysicalLogicalArchitectures.png" alt="Physical and Logical Architectures" width="381" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Traditional Monolith isn’t a bad choice but it is likely to turn into a big ball of mud due to its structure. Its transition to microservice is also very difficult. On the other hand, Modular Monolith can easily migrate to microservice. Microservice is a good choice if your application will be published at internet scale. But Modular Monolith is a better option if your application will be published just within an organization.&lt;/p&gt;

&lt;h4&gt;
  
  
  Communication in Modular Monolith
&lt;/h4&gt;

&lt;p&gt;Let’s consider an ordering system in an e-commerce app. Basic modules in an ordering system are Inventory, Order and Payment. During a buying process, order is received, stock is checked and payment is made. If a product is out of stock or payment hasn’t been made, that order is cancelled. Then how does such a communication occur in Modular Monolith?&lt;/p&gt;

&lt;p&gt;There are two approaches (sync, async) for communication. In the sync approach, each module exposes an interface. These interfaces are defined in the shared layers of modules. The inventory module exposes IInventoryService which has the methods of ReserveStock, ReleaseStock. Likewise, the payment module exposes IPaymentService which has the MakePayment method. The order module communicates with other modules by using these interfaces.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--okoi20LL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2022/03/SyncCommunication.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--okoi20LL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2022/03/SyncCommunication.png" alt="Sync Communication" width="443" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the async approach, each module raises events. These events are defined in the shared layers of modules. The order module raises the OrderReceived event. The inventory module raises the events of ReserveStock, OutOfStock and ReleaseStock. Likewise, the payment module raises the events of MakePayment, PaymentMade and PaymentFailed. Each module subscribes to related events. So the communication occurs through the message broker.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G_-l2r9C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2022/03/AsyncCommunication.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G_-l2r9C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2022/03/AsyncCommunication.png" alt="Async Communication" width="541" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are two approaches (choreography, orchestration) in async communication. It doesn’t matter which one is preferred. I preferred the orchestration approach because it is more efficient than the choreography approach for this scenario.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I3HfGAEg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2022/03/Orchestration.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I3HfGAEg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2022/03/Orchestration.png" alt="Orchestration" width="643" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  How is the project structure?
&lt;/h4&gt;

&lt;p&gt;Bootstrapper is the entry point of the project. So it is a WebApp.&lt;/p&gt;

&lt;p&gt;Each module has its own layers which aren’t standard. You can apply Onion or Hexagonal Architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shared.Abstractions :&lt;/strong&gt; It is used by Modules.Core and Modules.Infrastructure. It contains interfaces, abstractions such as DDD, CQRS etc.&lt;br&gt;
&lt;strong&gt;Shared :&lt;/strong&gt; It is used for cross-cutting concern. It also includes implementations of the abstractions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ecommerce.Inventory :&lt;/strong&gt; It is a class library. It contains the controllers of the inventory module. If you intend to use async method for communication, you can add the consumers (ReserveStockConsumer, ReleaseStockConsumer etc.) in Ecommerce.Inventory.&lt;br&gt;
&lt;strong&gt;Ecommerce.Inventory.Core :&lt;/strong&gt; It contains the domain or business logic of the inventory module. If you wish, you can separate Ecommerce.Inventory.Core into two parts, Application and Domain.&lt;br&gt;
&lt;strong&gt;Ecommerce.Inventory.Infrastructure :&lt;/strong&gt; It is where the modules are connected to external services or components such as database, message queue etc.&lt;br&gt;
&lt;strong&gt;Ecommerce.Inventory.Shared :&lt;/strong&gt; It is used to expose some classes (OutOfStock, StockReserved etc.) and allow the other layers to use those classes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pTnjuAmN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2022/02/ProjectStructure.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pTnjuAmN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2022/02/ProjectStructure.png" alt="Project Structure" width="722" height="1002"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;Using Modular Monolith is a better choice if you don’t want your project become a big ball of mud, and your project doesn’t require internet scale, or if you are likely to convert your project to a microservice architecture later.&lt;/p&gt;

&lt;p&gt;You can access the sample projects from my Github address.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ahmetkucukoglu"&gt;
        ahmetkucukoglu
      &lt;/a&gt; / &lt;a href="https://github.com/ahmetkucukoglu/modular-monolith-async"&gt;
        modular-monolith-async
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Ecommerce Modular Monolith App with Async
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
modular-monolith-async&lt;/h1&gt;
&lt;p&gt;Ecommerce Modular Monolith App with Async&lt;/p&gt;
&lt;p&gt;Run the following command to start the project.&lt;/p&gt;
&lt;div class="snippet-clipboard-content position-relative overflow-auto"&gt;&lt;pre&gt;&lt;code&gt;docker-compose up -d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;
Postman Collection&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://www.getpostman.com/collections/b39f4227fc3f0f9b9f99" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/16a903fe0c8e857e22585b47d674a11dc7fd16a2d4ef6a2d0e932e70a62cb0d6/68747470733a2f2f72756e2e7073746d6e2e696f2f627574746f6e2e737667" alt="Run in Postman"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ahmetkucukoglu/modular-monolith-async"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;



&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ahmetkucukoglu"&gt;
        ahmetkucukoglu
      &lt;/a&gt; / &lt;a href="https://github.com/ahmetkucukoglu/modular-monolith-sync"&gt;
        modular-monolith-sync
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Ecommerce Modular Monolith App with Sync
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
modular-monolith-sync&lt;/h1&gt;
&lt;p&gt;Ecommerce Modular Monolith App with Sync&lt;/p&gt;
&lt;p&gt;Run the following command to start the project.&lt;/p&gt;
&lt;div class="snippet-clipboard-content position-relative overflow-auto"&gt;&lt;pre&gt;&lt;code&gt;docker-compose up -d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;
Postman Collection&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://www.getpostman.com/collections/b39f4227fc3f0f9b9f99" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/16a903fe0c8e857e22585b47d674a11dc7fd16a2d4ef6a2d0e932e70a62cb0d6/68747470733a2f2f72756e2e7073746d6e2e696f2f627574746f6e2e737667" alt="Run in Postman"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ahmetkucukoglu/modular-monolith-sync"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;Good luck.&lt;/p&gt;

</description>
      <category>modularmonolith</category>
      <category>aspnetcore</category>
    </item>
    <item>
      <title>Developing Blockchain App – #1 Create Smart Contract</title>
      <dc:creator>Ahmet Küçükoğlu</dc:creator>
      <pubDate>Wed, 14 Jul 2021 20:25:28 +0000</pubDate>
      <link>https://dev.to/ahmetkucukoglu/developing-blockchain-app-1-create-smart-contract-1n8b</link>
      <guid>https://dev.to/ahmetkucukoglu/developing-blockchain-app-1-create-smart-contract-1n8b</guid>
      <description>&lt;p&gt;This article was originally published at: &lt;a href="https://www.ahmetkucukoglu.com/en/developing-blockchain-app-1-create-smart-contract/"&gt;https://www.ahmetkucukoglu.com/en/developing-blockchain-app-1-create-smart-contract/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This series of articles will be 3 parts. We will develop a blockchain app in this series of article. It will be like Hand-on Labs. So we prefer way of learning by developing an application. The subject of this article is to create a smart contract.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smart Contract ve Solidity
&lt;/h3&gt;

&lt;p&gt;Smart Contract is code parts that also store data in it. Programming language that used to write smart contract is Solidity. It isn't very advanced but it is enough to write.&lt;/p&gt;

&lt;p&gt;Let's take an example to better understand smart contract. Shipping date is specified by sellers in the product description. We also order according to this date. But the product may not be shipped in this date. Or it may not be delivered by courier companies. If we look from the viewpoint of buyer, these two problems are not the seller's or the cargo company's. Because our interlocutor is the marketplace. If our order is shipped late or delivered late, we should be able to cancel it. But It is not possible to trust marketplace. Smart contract provide a nice solution. We create this business process on the smart contract and show the contract transparently. So we make sure that the process will be executed. We remember that a published contract can't be change.&lt;/p&gt;

&lt;p&gt;Let's start to develop this contract. Our process will include below steps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Own of the contract, so marketplace , will write an order on the contract.&lt;/li&gt;
&lt;li&gt;  Buyer will make payment for the order.&lt;/li&gt;
&lt;li&gt;  If the order isn't sent at specified date, buyer can cancel the order and get her payment back.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Preparing the Environment
&lt;/h3&gt;

&lt;p&gt;Let's install Truffle which provides a development environment. We compile, test and publish of contracts by using Truffle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g truffle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let's install Ganache to create a local blockchain network on our machine. Ganache creates a local local blockchain network accessible on port 7545. This network have 10 accounts with balance of 100ETH. We will make test by using these accounts. You can install from the link below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.trufflesuite.com/ganache"&gt;https://www.trufflesuite.com/ganache&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Creating Smart Contract
&lt;/h4&gt;

&lt;p&gt;Let's run the following command.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir order-dapp-sample
cd order-dapp-sample
mkdir backend
cd backend
truffle init
code .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Application directory have contracts, migrations ve test directories. We create a contract named &lt;em&gt;Orders.sol&lt;/em&gt; under the contracts directory.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;We add a migration named &lt;em&gt;2_deploy_contracts.js&lt;/em&gt; under the migrations directory.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We add a test named &lt;em&gt;order.js&lt;/em&gt; under the test directory.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We adjust the network section in the file truffle-config.js.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Developing Order Adding and Querying Functions
&lt;/h4&gt;

&lt;p&gt;Marketplace will write OrderId, TotalPrice, DeliveryDate to the contract. So we create a struct named Order. It resembles struct in C#.&lt;/p&gt;

&lt;p&gt;We store id as string type because Solidity don't have Guid type. Solidity have numeric types from uint8 to uint256. We use uint256 for totalPrice. Solidity don't have DateTime type. We have to store it in unix timestamp format. So We use uint256 for deliveryDate.&lt;/p&gt;

&lt;p&gt;We add the createdDate for creation date of the order, the deliveredDate for delivery date of the order and the status for status of the order. We store status as enum type. It resembles that enum in C# but we can't specify number.&lt;/p&gt;

&lt;p&gt;We create a mapping type variable named &lt;em&gt;orders&lt;/em&gt; in order to store the order information by id and to query the order by id. It resembles that Dictionary in C#.&lt;/p&gt;

&lt;p&gt;Every account or contract on the blockchain has a 160-bit address. We must save the address of the account that created the contract so that only this account can add orders. So only the marketplace can add orders. We access the account address from &lt;em&gt;msg.sender&lt;/em&gt;. We get this information from the constructor function and store it in the &lt;em&gt;owner&lt;/em&gt; variable. In Solidity, the address data type is used for address information.&lt;/p&gt;

&lt;p&gt;We add a function named &lt;em&gt;add&lt;/em&gt; to get the order information. We store this information in the orders variable. We need an authorization. So only the contract owner should be able to call this function. For this, we create a modifier named &lt;em&gt;onlyOwner&lt;/em&gt;. In this modifier, we compare the account address that calls the function with the account address that creates the contract. If it doesn't match, we throw "The sender isn't authorized" error. Finally, we add this modifier to the add function. We can add many modifiers here. These modifiers are run orderly and the function is run if there is no error.&lt;/p&gt;

&lt;p&gt;We add a function named &lt;em&gt;get&lt;/em&gt; to return the details about the order. This function takes the order id as parameter. We check the order and if there is no order, we throw an error.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In Solidity, two keywords, memory and storage, are used for reference types. Smart Contracts consume RAM each time a function is called. Variables marked with memory are cleared when the function completes its work. Variables marked with storage live as long as the contract lives.&lt;/p&gt;

&lt;p&gt;Since smart contracts cannot be edited, we need to test contracts before publishing. That's why TDD is important. We write tests for the add function in orders.js under the test folder.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;When the test starts running, Ganache defines 10 accounts. We can access these accounts from accounts parameter on line 3.&lt;/p&gt;

&lt;p&gt;There are three units in the Ethereum network namely Ether, Gwei and Wei. Although Ether is the largest unit, all transactions are made with the smallest unit Wei. In the 8th line, so we convert 2.5 Ether to Wei.&lt;/p&gt;

&lt;p&gt;The contract is always created with the first account. In the 16th line, we give the second account to the from parameter so that we expect an error to occur.&lt;/p&gt;

&lt;p&gt;We run the Ganache application and click the &lt;em&gt;QuickStart Ethereum&lt;/em&gt; button to activate the local blockchain network.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hipvKTBM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/01_Ganache-1024x712.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hipvKTBM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/01_Ganache-1024x712.png" alt="Ganache" width="880" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ganache&lt;/p&gt;

&lt;p&gt;We run the test with the following command line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;truffle test ./test/orders.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LDN7_cuQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/02_TestingAddFunction-1024x541.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LDN7_cuQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/02_TestingAddFunction-1024x541.png" alt="Add Fonksiyonu Test Sonucu" width="880" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Test Result of The Add Function&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8RG3snv0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/03_AfterTestingAddFunction-1024x712.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8RG3snv0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/03_AfterTestingAddFunction-1024x712.png" alt="Add Fonksiyonu Testi Sonrası Hesap Durumu" width="880" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Account Status After The Test of Add Function&lt;/p&gt;
&lt;h4&gt;
  
  
  Developing Order Paying Function
&lt;/h4&gt;

&lt;p&gt;We create a struct named &lt;em&gt;Payment&lt;/em&gt; to store the information that we have received the payment. We add id for the id of the order, buyerAddress for the address of the paying account, paidDate for the payment date, and refundedDate for the refund date. We mark the buyerAddress with &lt;em&gt;payable&lt;/em&gt; so that we can refund to that address. We create a variable named payments.&lt;/p&gt;

&lt;p&gt;Let's publish an event when the payment is made. We create an event named &lt;em&gt;OrderPaid&lt;/em&gt;. The event arguments are id, paidAddress, paidAmount and date.&lt;/p&gt;

&lt;p&gt;We add a function named &lt;em&gt;pay&lt;/em&gt; to receive the payment. This function takes the order id as a parameter. The difference of this function from the add function is that it can receive payment. That's why we add the &lt;em&gt;payable&lt;/em&gt; keyword. We check the order. We throw an error if it has already been paid. Then we compare the price of the order with the payment amount and throw an error if they don't match. We access the payment amount from &lt;em&gt;msg.value&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We update the status of the order to Paid. We store the address of the paying account and the payment date. When payment is made with this function, the amount is stored in the contract. Finally, we publish the OrderPaid event.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;block.timestamp returns the time of the current block in milliseconds.&lt;br&gt;
msg.value returns the amount entered when the function was executed.&lt;br&gt;
msg.sender returns the address of the account running the function.&lt;/p&gt;

&lt;p&gt;We write tests for the pay function in orders.js under the test folder.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Because the pay method is marked as &lt;em&gt;payable&lt;/em&gt;, it can receive payment. In the 16th and 27th lines, we enter 200 Wei to the value parameter, we expect an error because the order amount (2.5 Ether) doesn't match 200 Wei.&lt;/p&gt;

&lt;p&gt;We published an event when the payment was successful. In the 37th line, we check whether the event is published or not.&lt;/p&gt;

&lt;p&gt;We run the test with the following command line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;truffle test ./test/orders.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w1IJl6Ew--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/04_TestingPayFunction-1024x592.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w1IJl6Ew--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/04_TestingPayFunction-1024x592.png" alt="Pay Fonksiyonu Test Sonucu" width="880" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Test Result of The Pay Function&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D1t-QCLH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/05_AfterTestingPayFunction-1024x712.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D1t-QCLH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/05_AfterTestingPayFunction-1024x712.png" alt="Pay Fonksiyonu Testi Sonrası Hesap Durumu" width="880" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Account Status After The Test of Pay Function&lt;/p&gt;
&lt;h4&gt;
  
  
  Developing Order Delivering Function
&lt;/h4&gt;

&lt;p&gt;Let's publish an event when the order is delivered. We create an event named &lt;em&gt;OrderDelivered&lt;/em&gt;. The event arguments are id and date.&lt;/p&gt;

&lt;p&gt;We add a function named &lt;em&gt;deliver&lt;/em&gt; to mark the order as delivered. This function takes the order id as a parameter. We also authorize this function for the marketplace. Just like the add function, we add the &lt;em&gt;onlyOwner&lt;/em&gt; modifier to this function.&lt;/p&gt;

&lt;p&gt;We check the order. We also throw an error if it has already been delivered.&lt;/p&gt;

&lt;p&gt;We update the status of the order to Delivered. We add the delivery date of the order. Finally, we publish the OrderDelivered event.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;We write tests for the deliver function in orders.js under the test folder.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We run the test with the following command line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;truffle test ./test/orders.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gI602X3U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/06_TestingDeliverFunction-1024x689.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gI602X3U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/06_TestingDeliverFunction-1024x689.png" alt="Deliver Fonksiyonu Test Sonucu" width="880" height="592"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Test Result of The Deliver Function&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MPBoZLC---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/07_AfterTestingDeliverFunction-1024x712.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MPBoZLC---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/07_AfterTestingDeliverFunction-1024x712.png" alt="Deliver Fonksiyonu Testi Sonrası Hesap Durumu" width="880" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Account Status After The Test of Deliver Function&lt;/p&gt;
&lt;h4&gt;
  
  
  Developing Order Refunding Function
&lt;/h4&gt;

&lt;p&gt;Let's publish an event when the refund is made. We create an event named &lt;em&gt;OrderRefunded&lt;/em&gt;. The event arguments are id and date.&lt;/p&gt;

&lt;p&gt;We add a function named &lt;em&gt;refund&lt;/em&gt; for process of returning. This function takes the order id as a parameter. We check the order. We throw an error if the order hasn't been paid for. We throw an error if the order has been delivered. We throw an error if a refund has been made. If the account that makes the payment and the account that calls the function are not the same, we throw an error. We throw an error if the promised delivery date hasn't yet been exceeded.&lt;/p&gt;

&lt;p&gt;We make the refund to the buyer. We update the status of the order to Refunded. We add the refund ​date. Finally, we publish the OrderRefunded event&lt;/p&gt;

&lt;p&gt;In order to test whether the promised delivery date has been exceeded, we need to mock &lt;em&gt;block.timestamp&lt;/em&gt; . For this, we add a function named &lt;em&gt;getTime&lt;/em&gt; and return the current date from this function.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;We add a contract named &lt;em&gt;MockedOrders.sol&lt;/em&gt; under the contracts folder. We extend this contract from the Orders contract. We add a function named &lt;em&gt;mockTimestamp&lt;/em&gt;. This function takes a timestamp as a parameter and stores it. The getTime function returns this timestamp. We will do our test on this contract.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We edit the &lt;em&gt;2_deploy_contracts.js&lt;/em&gt; migration under the migrations folder.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We write tests for the refund function in orders.js under the test folder.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Solidity has the concepts of Gas, Gas Price and Gas Cost. Each function executed in the contract has a certain cost. Gas is calculated automatically according to the size of the contract and the running code. For example, 1000 Gas is calculated for the pay method. Miners are needed to confirm the transactions made in the contract and create a new block. This is where Gas Price comes into play. Miners work with the Gas * GasPrice calculation. In other words, the higher the Gas Price, the faster the transactions are approved :) The result of this multiplication is called Gas Cost.&lt;/p&gt;

&lt;p&gt;In the 69th line, we get Gas Price which default value in Ganache is 20000000000 Gwei.&lt;br&gt;&lt;br&gt;
In the 82th line, we get the balance of the third account. Default 100 Ether in Ganache.&lt;br&gt;&lt;br&gt;
In the 85th to 88th lines, we calculate the Gas Cost for the pay and refund functions. The Gas Price is multiplied by the amount of Gas used.&lt;br&gt;&lt;br&gt;
In the 92th line, we again take the balance of the second account.&lt;br&gt;&lt;br&gt;
In the 93th to 94th lines, we add the Gas Costs that we calculated above to the final balance.&lt;br&gt;&lt;br&gt;
In the 96th line, we compare the balances to check if the refund has been successfully made.&lt;/p&gt;

&lt;p&gt;We run the test with the following command line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;truffle test ./test/orders.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bQRtYCZD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/08_TestingRefundFunction-1024x769.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bQRtYCZD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/08_TestingRefundFunction-1024x769.png" alt="Refund Fonksiyonu Test Sonucu" width="880" height="661"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Test Result of The Refund Function&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tIeKqDX5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/09_AfterTestingRefundFunction-1024x712.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tIeKqDX5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2021/05/09_AfterTestingRefundFunction-1024x712.png" alt="Refund Fonksiyon Testi Sonrası Hesap Durumu" width="880" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Account Status After The Test of Refund Function&lt;/p&gt;

&lt;p&gt;We have developed the contract. In the next post we will look at how to use it in web application.&lt;/p&gt;

&lt;p&gt;You can access the sample application on Github.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ahmetkucukoglu"&gt;
        ahmetkucukoglu
      &lt;/a&gt; / &lt;a href="https://github.com/ahmetkucukoglu/order-blockchain-app"&gt;
        order-blockchain-app
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Blockchain Uygulama Geliştirme&lt;/h1&gt;
&lt;p&gt;1.Bölüm Kontrat Oluşturma :
&lt;a href="https://www.ahmetkucukoglu.com/blockchain-uygulama-gelistirme-1-kontrat-olusturma" rel="nofollow"&gt;ahmetkucukoglu.com/blockchain-uygulama-gelistirme-1-kontrat-olusturma&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2.Bölüm UI İle Etkileşim :
&lt;a href="https://www.ahmetkucukoglu.com/blockchain-uygulama-gelistirme-2-ui-ile-etkilesim" rel="nofollow"&gt;ahmetkucukoglu.com/blockchain-uygulama-gelistirme-2-ui-ile-etkilesim&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;3.Bölüm Kontratı Yayınlama ve API Hazırlama :
&lt;a href="https://www.ahmetkucukoglu.com/blockchain-uygulama-gelistirme-3-kontrati-yayinlama-ve-api-hazirlama" rel="nofollow"&gt;ahmetkucukoglu.com/blockchain-uygulama-gelistirme-3-kontrati-yayinlama-ve-api-hazirlama&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ahmetkucukoglu/order-blockchain-app"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Good luck.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>dapp</category>
      <category>ethereum</category>
      <category>smartcontract</category>
    </item>
    <item>
      <title>Bootstrap Filter Plugin</title>
      <dc:creator>Ahmet Küçükoğlu</dc:creator>
      <pubDate>Mon, 16 Nov 2020 10:04:30 +0000</pubDate>
      <link>https://dev.to/ahmetkucukoglu/bootstrap-filter-plugin-59i6</link>
      <guid>https://dev.to/ahmetkucukoglu/bootstrap-filter-plugin-59i6</guid>
      <description>&lt;p&gt;This article was originally published at: &lt;a href="https://www.ahmetkucukoglu.com/en/bootstrap-filter-plugin-en/"&gt;https://www.ahmetkucukoglu.com/en/bootstrap-filter-plugin-en/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of the form elements being displayed side by side, it allows the form element to be displayed with the user action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YL0HKj6j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/11/BootstrapFilterPluginDemo-1024x311.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YL0HKj6j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/11/BootstrapFilterPluginDemo-1024x311.png" alt="Bootstrap Filter Plugin Demo" width="880" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Form Elements
&lt;/h2&gt;

&lt;p&gt;This use is recommended if the filter contains classic form elements (text, radio, checkbox, select-one or select-multiple). &lt;a href="https://www.ahmetkucukoglu.com/bootstrap-filter-plugin-demo/01-Basic.html"&gt;Click&lt;/a&gt; for sample page.&lt;/p&gt;

&lt;h4&gt;
  
  
  HTML
&lt;/h4&gt;

&lt;p&gt;The "data-filter" feature is added to the buttons. The name of the filter is given as a value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-sm btn-outline-secondary position-relative"&lt;/span&gt; &lt;span class="na"&gt;data-filter-button=&lt;/span&gt;&lt;span class="s"&gt;"monthOfBirth"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "data-filter-container" feature is added to the containers that will be opened when the buttons are clicked. The name of the filter is given as a value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"collapse bg-white border rounded pr-1"&lt;/span&gt; &lt;span class="na"&gt;data-filter-container=&lt;/span&gt;&lt;span class="s"&gt;"monthOfBirth"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The container may include the form elements of text, radio, checkbox, select-one or select-multiple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"p-3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-group mb-0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"monthOfBirthSelect"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Month of Birth&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-control"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"monthOfBirthSelect"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"monthOfBirthSelect"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Please select&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;January&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;February&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;March&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;April&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;May&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  JS
&lt;/h4&gt;

&lt;p&gt;JSON object is created that contains the filter's name, label, default text and default value.&lt;br&gt;&lt;br&gt;
The JSON key must be the same with the "data-filter value" which is added to HTML.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;monthOfBirth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;monthOfBirthSelect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Month of Birth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;defaultText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Please select&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;filterPlugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;The name of the form element in the container is indicated.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;label&lt;/td&gt;
&lt;td&gt;It is used to show the name of the filter in the filter button.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;defaultText&lt;/td&gt;
&lt;td&gt;It is used to show the default text in the filter button if there is no selection in the form element.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;defaultValue&lt;/td&gt;
&lt;td&gt;It specifies the value that will be selected in the form element when the reset button or the clear filter button is clicked.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Custom Form Elements
&lt;/h2&gt;

&lt;p&gt;This use is recommended if the filter contains more than one form element or different components. &lt;a href="https://www.ahmetkucukoglu.com/bootstrap-filter-plugin-demo/02-Custom.html"&gt;Click&lt;/a&gt; for sample page&lt;/p&gt;

&lt;h4&gt;
  
  
  JS
&lt;/h4&gt;

&lt;p&gt;Three methods are defined for each filter.&lt;br&gt;&lt;br&gt;
The method that returns the text of the filter is defined as "getText".&lt;br&gt;&lt;br&gt;
The method that returns the value of the filter is defined as "getValue".&lt;br&gt;&lt;br&gt;
The method to be called to clear the filter is defined as "clearValue".&lt;br&gt;&lt;br&gt;
The JSON key must be the same as the data-filter value added in HTML.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;birthDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;getText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;month&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;monthOfBirthSelect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;year&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yearOfBirthSelect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;month&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedIndex&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedIndex&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Birth date: Please select&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;month&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedIndex&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;month&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;month&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedIndex&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedIndex&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedIndex&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Birth date: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;month&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;monthOfBirthSelect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;year&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yearOfBirthSelect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;month&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedIndex&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedIndex&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;month&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedIndex&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;month&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;month&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;month&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedIndex&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedIndex&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;year&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedIndex&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;clearValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;monthOfBirthSelect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;selectedIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yearOfBirthSelect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;selectedIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;filterPlugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Handle Events
&lt;/h2&gt;

&lt;p&gt;This use is recommended if an event triggering is requested when the apply or reset buttons are clicked. &lt;a href="https://www.ahmetkucukoglu.com/bootstrap-filter-plugin-demo/03-Events.html"&gt;Click&lt;/a&gt; for sample page&lt;/p&gt;

&lt;h4&gt;
  
  
  JS
&lt;/h4&gt;

&lt;p&gt;Two methods are defined.&lt;br&gt;&lt;br&gt;
The method to be called when the reset button is clicked is defined as "clickedFilterResetButton".&lt;br&gt;&lt;br&gt;
The method to be called when the Apply button is clicked is defined as "clickedFilterApplyButton".&lt;br&gt;&lt;br&gt;
Filter values are passed as parameters (payload) to "clickedFilterApplyButton" method in JSON format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;monthOfBirth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;monthOfBirthSelect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Month&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;defaultText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Please select&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;callbacks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;clickedFilterResetButton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Clicked reset button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;clickedFilterApplyButton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Clicked apply button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;filterPlugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callbacks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can access source code and samples from &lt;a href="https://github.com/ahmetkucukoglu/bootstrap-filter-plugin"&gt;Github&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>bootstrap</category>
      <category>javascript</category>
    </item>
    <item>
      <title>ASP.NET Core Feature Management</title>
      <dc:creator>Ahmet Küçükoğlu</dc:creator>
      <pubDate>Sun, 15 Nov 2020 12:42:59 +0000</pubDate>
      <link>https://dev.to/ahmetkucukoglu/asp-net-core-feature-management-2bd</link>
      <guid>https://dev.to/ahmetkucukoglu/asp-net-core-feature-management-2bd</guid>
      <description>&lt;p&gt;This article was originally published at: &lt;a href="https://www.ahmetkucukoglu.com/en/asp-net-core-feature-management-en/"&gt;https://www.ahmetkucukoglu.com/en/asp-net-core-feature-management-en/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feature Management provides feature management in .NET Core applications. It allows the management and querying of the active / passive status of the features of the application. For example, you can ensure that a feature you have just developed is active in a certain date range. To give another example, you can ensure that a feature you have developed is active with a certain percentage. Like A/B testing.&lt;/p&gt;

&lt;p&gt;Let's test it by practicing. First, we need to install the package below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Microsoft.FeatureManagement.AspNetCore -version 2.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let's define our features in enum.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Let's activate the Feature Management in the Startup.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Because Feature Management reads features from IConfiguration, we can define features in environment variable, commandline argument or appsettings. Or, if you have a custom provider, you can define your features in the related source. We will use appsettings in our example. Let's define the feature named FeatureA.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We need to inject the "IFeatureManager" interface to query if the features are activated. By using the "IsEnabledAsync" method of this interface, we can query as follows if the "FeatureA" feature is activated.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h5&gt;
  
  
  &lt;strong&gt;TimeWindowFilter&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;If we want the feature to be active in a certain date range, we can use the internal "TimeWindowFilter". For this, we need to activate this filter in the Startup.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let's define the feature named FeatureB in appsettings.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;UTC Date is used as the date format. If you only give the Start parameter, the feature will be active from this date. If you only give the End parameter, the feature will be active until this date.&lt;/p&gt;

&lt;p&gt;Again, using the "IsEnabledAsync" method of the "IFeatureManager" interface, we can query if the "FeatureB" feature gets activated as follows.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h5&gt;
  
  
  &lt;strong&gt;PercentageFilter&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;If we want the feature to be active with a certain percentage, we can use the internal "PercentageFilter". For this, we need to activate this filter in the Startup.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let's define the feature named FeatureC in appsettings.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This feature will be active in 80% of the requests.&lt;/p&gt;

&lt;p&gt;Again, using the "IsEnabledAsync" method of the "IFeatureManager" interface, we can query if the "FeatureC" feature gets activated as follows.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h5&gt;
  
  
  &lt;strong&gt;Custom Filter&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Apart from these filters, you can also write your own filters. For example, a filter can be written as below for the feature to be active on a mobile device.&lt;/p&gt;

&lt;p&gt;Let's define the feature named FeatureD in appsettings.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let's create "MobileFilterSettings" class to access filter parameters.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let's write our special filter named "MobileFilter" as follows.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We need to activate this filter in the Startup.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Again, using the "IsEnabledAsync" method of the "IFeatureManager" interface, we can query if "FeatureD" feature gets activated as follows.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h5&gt;
  
  
  &lt;strong&gt;Mvc Action Filter Attribute&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Instead of using the IFeatureManager interface, you can set the activation of the attribute based Controller or Action, thanks to ActionFilter.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h5&gt;
  
  
  &lt;strong&gt;Razor Tag Helper&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;You can use the feature razor tag if you want to display the content in the View according to the activation status of the feature.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h5&gt;
  
  
  &lt;strong&gt;Middleware&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;If you want to add middleware according to the activation status of the feature, you can use the UseMiddlewareForFeature method.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;You can access the sample project from &lt;a href="https://github.com/ahmetkucukoglu/aspnetcore-feature-management"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Good luck.&lt;/p&gt;

</description>
      <category>aspnetcore</category>
    </item>
    <item>
      <title>Event Sourcing with ASP.NET Core - 02 Messaging</title>
      <dc:creator>Ahmet Küçükoğlu</dc:creator>
      <pubDate>Thu, 22 Oct 2020 23:15:20 +0000</pubDate>
      <link>https://dev.to/ahmetkucukoglu/event-sourcing-with-asp-net-core-02-messaging-54gb</link>
      <guid>https://dev.to/ahmetkucukoglu/event-sourcing-with-asp-net-core-02-messaging-54gb</guid>
      <description>&lt;p&gt;This article was originally published at: &lt;a href="https://www.ahmetkucukoglu.com/en/event-sourcing-with-aspnet-core-02-messaging/"&gt;https://www.ahmetkucukoglu.com/en/event-sourcing-with-aspnet-core-02-messaging/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Since this article is second part of the article below, I recommend you to read the following article before starting. We will continue with the sample project in the article below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.ahmetkucukoglu.com/en/event-sourcing-with-asp-net-core-01-store/"&gt;https://www.ahmetkucukoglu.com/en/event-sourcing-with-asp-net-core-01-store/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the previous article, we made the example of Kanban Board. By creating a RESTful API, we wrote the create, assign, move and complete endpoints. We recorded the requests coming to these endpoints as an event in the Event Store. So we focused on the store part of the Event Store. In this article, we will focus on with the messaging part.&lt;/p&gt;

&lt;p&gt;We will include the following endpoint in our RESTful API endpoints.&lt;/p&gt;

&lt;p&gt;[GET] api/tasks/{id}&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Preparing Couchbase&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Since the events are not queryable, the events must be stored as nosql documents or sql row to represent the whole. For example; We can't get tasks which their states appear as "Done, from the Event Store. For this reason, we need to keep the events as a whole in a queryable database. In this example, we will keep the tasks on the couchbase.&lt;/p&gt;

&lt;p&gt;We run Couchbase in Docker with the command line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d --name couchbase -p 8091-8094:8091-8094 -p 11210:11210 couchbase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When the Couchbase has been run, you should enter the panel at the address below and create a cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://localhost:8091/"&gt;http://localhost:8091/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's create two buckets named "checkpoints" and "tasks" in Couchbase with the curl command lines below. Remember to replace the -u parameter with the information you have provided when creating the cluster.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST -u [admin]:[password] http://localhost:8091/pools/default/buckets
  -d name=checkpoints -d ramQuotaMB=100 -d authType=none -d bucketType=couchbase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST -u [admin]:[password] http://localhost:8091/pools/default/buckets
  -d name=tasks -d ramQuotaMB=100 -d authType=none -d bucketType=couchbase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Adapting Couchbase to API&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We install the packages "CouchbaseNetClient" and "Couchbase.Extensions.DependencyInjection" to the API project with the following command lines.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package CouchbaseNetClient -v 2.7.16
dotnet add package Couchbase.Extensions.DependencyInjection -v 2.0.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We add Couchbase connection information to appsettings.json as follows.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;In the Startup.cs file, we configure the Couchbase.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Each event has a position value in the Event Store. After recording the events read from the Event Store to Couchbase, we must keep the position value of the last event read. We will store this position value in the CheckpointDocument type.&lt;/p&gt;

&lt;p&gt;Let's add a class named "CheckpointDocument.cs" in the Infrastructure folder. Let's paste the code below into the class.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We write the repository class to read the last position value that we have written to Couchbase or to record the position value.&lt;/p&gt;

&lt;p&gt;Let's add a class named "CheckpointRepository.cs" in the Infrastructure folder. Let's paste the code below into the class.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We will store task information in TaskDocument type. Let's add a class named "TaskDocument.cs" in the Infrastructure folder. Let's paste the code below into the class.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We write the repository class to write the events read from the Event Store to Couchbase and to query the tasks from Couchbase.&lt;/p&gt;

&lt;p&gt;Let's add a class named "TaskRepository.cs" in the Infrastructure folder. Let's paste the code below into the class.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the save method, we add the relevant task according to the type of the event recorded in the EventStore and update the related information of the task.&lt;br&gt;&lt;br&gt;
In the Get method, we query the tasks from Couchbase by id .&lt;/p&gt;

&lt;p&gt;Let's add CheckpointRepository and TaskRepository classes to DI Container in Startup.cs file as below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;4. Preparing Consumer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We need the consumer to listen to the events from the Event Store. For this reason, we will use the Hosted Service in ASP.NET Core.&lt;/p&gt;

&lt;p&gt;Let's add a folder named "HostedServices" to the project and add a class named "TaskHostedService.cs" into it. Let's paste the code below into the class.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the line 33, we query the position value of the last event recorded to Couchbase.&lt;br&gt;&lt;br&gt;
In the line 42, we subscribe to the Event Store and start listening to the events. If lastCheckpoint value is not given, all events are read repeatedly whenever we run the project. With lastCheckpoint, we state that we will read the events coming after the last position value we have read.&lt;br&gt;&lt;br&gt;
In the line 47, we skip in order not to take action on the Event Store's own events.&lt;br&gt;&lt;br&gt;
In the line 52, we find the type of the event which is read.&lt;br&gt;&lt;br&gt;
In the line 53, we deserialize the event according to its type.&lt;br&gt;&lt;br&gt;
In the line 55, we skip in order not to take action for events other than these events.&lt;br&gt;&lt;br&gt;
In the line 58, we record the task to Couchbase.&lt;br&gt;&lt;br&gt;
In the line 60, we record the position value of the event read from the Event Store to Couchbase.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;5. Preparing API Endpoint&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We add the endpoint where we will query the task to TasksController as follows.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Everything is ready now. We can run the API project. We can query the task we have added at the end of the previous article with the curl command line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://localhost:44361/api/tasks/3a7daba9-872c-4f4d-8d6f-e9700d78c4f5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can access the final version of the project from &lt;a href="https://github.com/ahmetkucukoglu/aspnetcore-event-sourcing-2"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Good luck.&lt;/p&gt;

</description>
      <category>aspnetcore</category>
      <category>eventstore</category>
      <category>eventsourcing</category>
    </item>
    <item>
      <title>Event Sourcing with ASP.NET Core – 01 Store</title>
      <dc:creator>Ahmet Küçükoğlu</dc:creator>
      <pubDate>Mon, 25 May 2020 14:54:41 +0000</pubDate>
      <link>https://dev.to/ahmetkucukoglu/event-sourcing-with-asp-net-core-01-store-3k04</link>
      <guid>https://dev.to/ahmetkucukoglu/event-sourcing-with-asp-net-core-01-store-3k04</guid>
      <description>&lt;p&gt;This article was originally published at: &lt;a href="https://www.ahmetkucukoglu.com/en/event-sourcing-with-asp-net-core-01-store/"&gt;https://www.ahmetkucukoglu.com/en/event-sourcing-with-asp-net-core-01-store/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I recommend you to read the article below before applying this example tutorial.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.ahmetkucukoglu.com/en/what-is-event-sourcing/"&gt;https://www.ahmetkucukoglu.com/en/what-is-event-sourcing/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the article I have mentioned above, I had formed a sentence as follows.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There is a technology called “Event Store” in the .NET world for Event Sourcing. This technology offers solutions for “Aggregate” and “Projection”. In other words, in addition to providing the store where we can record the events, it also provides the “Messaging” and “Projection” services, which are necessary for us to record in “Query” databases.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this article, we will deal with the store section of the Event Store. In other words, we will deal with the database feature where we can save events. In the next article, we will deal with the messaging part.&lt;/p&gt;

&lt;p&gt;As an sample application, I chose the classic Kanban Board sample.&lt;/p&gt;

&lt;p&gt;Our RESTful API endpoints will be as follows.&lt;/p&gt;

&lt;p&gt;[POST] api/tasks/{id}/create&lt;br&gt;&lt;br&gt;
[PATCH] api/tasks/{id}/assign&lt;br&gt;&lt;br&gt;
[PATCH] api/tasks/{id}/move&lt;br&gt;&lt;br&gt;
[PATCH] api/tasks/{id}/complete&lt;/p&gt;

&lt;p&gt;Our events will be as follows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CreatedTask&lt;/strong&gt; : When Task is created, an event with this name will be created.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;AssignedTask&lt;/strong&gt; : An event with this name will be created when Task is assigned to someone.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;MovedTask&lt;/strong&gt; : When Task is moved to a section (In Progress, Done), an event with this name will be created.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;CompletedTask&lt;/strong&gt; : When Task is completed, an event with this name will be created.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;2. Installing the Event Store&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We run the Event Store in Docker with the following command line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d --name eventstore -p 2113:2113 -p 1113:1113 eventstore/eventstore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When the Event Store run, you can enter the panel from the address below. The default username is "admin" and the password is "changeit".&lt;/p&gt;

&lt;p&gt;&lt;a href="http://localhost:2113/"&gt;http://localhost:2113/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;3. Creating the API Project&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We create an ASP.NET Core Web API Application project named "EventSourcingTaskApp". We install the "EventStore.Client" package to the project with the following command line.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package EventStore.Client -v 5.0.6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We add Event Store connection information to appsettings.json as follows.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;In the Startup.cs file, we connect the Event Store and add it to the DI Container.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;4. Aggregate Base Class and Aggregate Repository&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let's add two folders named "Core" and "Infrastructure" to the project. We will add Task-related entities, events and exceptions to the Core folder. For the Infrastructure folder, we will add our repository class that will connect the Event Store.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;4.1. Aggregate Base Class&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Let's add a folder named "Framework" inside the Core folder and add a class named "Aggregate.cs" into it. Let's paste the code below into the class.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This is a standard class. Aggregates are derived from this base class. In our example, Task is an aggregate and this will be derived from the base class.  &lt;/p&gt;

&lt;p&gt;In the line 9, we define the variable where aggregate events will be stored.&lt;br&gt;&lt;br&gt;
In the line 11 we state that aggregate will have an Id.&lt;br&gt;&lt;br&gt;
In the line 12 we state that the default version of aggregate is "-1".&lt;br&gt;&lt;br&gt;
In the line 16, we write the method that will add events to the variable defined on the line 9.&lt;br&gt;&lt;br&gt;
In the line 23, we write the method that will apply the events to aggregate. The final version of aggregate will be created by running this method for each event read from the Event Store.&lt;br&gt;&lt;br&gt;
In the line 33, we write the method that returns the events on aggregate. While sending events to the Event Store, this method will be run and events will be received.&lt;/p&gt;
&lt;h5&gt;
  
  
  &lt;strong&gt;4.2. Aggregate Repository&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Let's add a class named "AggregateRepository.cs" inside the Infrastructure folder. Let's paste the code below into the class.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This is also a standard class. We use this repository when sending events to the Event Store or receiving events from the Event Store.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;4.2.1. Sending an Event (Append Events to Stream)&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;In the line 22, we take the events on aggregate and map them to the EventData class. Event Store stores events in the EventData type.  &lt;/p&gt;

&lt;p&gt;As the first parameter, it takes for the event's id.&lt;br&gt;&lt;br&gt;
As the second parameter, it takes for the name of the event. Example event name; CreatedTask, AssignedTask etc.&lt;br&gt;&lt;br&gt;
As the third parameter, it takes whether the event data is in json type.&lt;br&gt;&lt;br&gt;
As the fourth parameter, it takes the event data. Since it takes in byte array type, serialize and encoding processes are performed.&lt;br&gt;&lt;br&gt;
As the fifth parameter, it takes the metadata. This parameter can be passed as null but we pass the type of the event class as "fullname" so that we can use this class type when deserializing the events. Example fullname; EventSourcingTaskApp.Core.Events.CreatedTask.  &lt;/p&gt;

&lt;p&gt;In the line 36, we set the stream name. Event aggregates in the Event Store is called stream. So aggregate is expressed as a stream in Event Store. Example stream name; Task-518e7c15-36ac-4edb-8fa5-931fb8ffa3a5.  &lt;/p&gt;

&lt;p&gt;In the 38th line, events are recorded in the Event Store.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cyLRAe2L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/Stream-1024x505.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cyLRAe2L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/Stream-1024x505.png" alt="Örnek Stream" width="880" height="434"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h5&gt;
  
  
  &lt;strong&gt;4.2.2. Reading an Event (Read Events from Stream)&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;In the line 47, we set the stream name.  &lt;/p&gt;

&lt;p&gt;In line 53, events are received from the Event Store in order according to the version numbers in the loop.  &lt;/p&gt;

&lt;p&gt;In the 58th line, the load method of aggregate is called and the events are applied to aggregate and the final form of aggregate is created.&lt;/p&gt;

&lt;p&gt;Let's add AggregateRepository class to DI Container in the Startup.cs file as below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;5. Defining Task and Use Cases&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In this part, we will start creating events, exceptions, and use cases related to Task.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;5.1. Defining Task&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Let's add an aggregate class named "Task.cs" in the Core folder. Let's paste the code below into the class.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Task will have the Title, Section, AssignedTo and IsCompleted.&lt;/p&gt;

&lt;p&gt;Again, let's add a class named "BoardSections.cs" into Core. Let's paste the code below into the class.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h5&gt;
  
  
  &lt;strong&gt;5.2. Defining Exceptions&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Let's add a folder named "Exceptions" inside the Core folder and add a class named "TaskAlreadyCreatedException.cs" in it. Let's paste the code below into the class. If it tries to create a task with the same id information, we will throw this error.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let's add a class named "TaskCompletedException.cs" in the Exceptions folder inside the Core folder. Let's paste the code below into the class. If any process is tried on the completed task, we will throw this error.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let's add a class named "TaskNotFoundException.cs" inside the Exceptions folder inside the Core folder. Let's paste the code below into the class. If Task is not found, we will throw this error.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now that we have created the Task aggregate and exceptions, we can start writing use cases related to the Task.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;5.3. Create Task&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;When Task is created; We will keep task id, its title and the information of who created the task, as event data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OMMdKxUj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/Event01_CreatedTask-e1582468202128-1024x768.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OMMdKxUj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/Event01_CreatedTask-e1582468202128-1024x768.png" alt="CreatedTask" width="880" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's add a folder named "Events" inside the Core folder and add an event class named "CreatedTask.cs" into it. Let's paste the code below into the class.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let's edit the Task.cs class as follows.&lt;/p&gt;

&lt;p&gt;With the Create method, we store the CreatedTask event on aggregate, so that we can send these stored events to the Event Store.&lt;br&gt;&lt;br&gt;
In the line 19, we apply the CreatedTask event from the Event Store to aggregate.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h5&gt;
  
  
  &lt;strong&gt;5.4. Assign Task&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;When Task is assigned to someone; We will keep task id , information of who has assigned the task and to whom the task has been assigned as event data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WFQUY86S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/Event02_AssignedTask-e1582468541972-1024x768.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WFQUY86S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/Event02_AssignedTask-e1582468541972-1024x768.png" alt="AssignedTask" width="880" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's add an event class named "AssignedTask.cs" to the Events folder inside the Core folder. Let's paste the code below into the class.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let's edit the Task.cs class as follows.&lt;/p&gt;

&lt;p&gt;With the Assign method, we store the AssignedTask event on aggregate so that we can send these stored events to the Event Store.&lt;br&gt;&lt;br&gt;
In the line 20, we apply AssignedTask event received from Event Store to aggregate.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h5&gt;
  
  
  &lt;strong&gt;5.5. Move Task&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;When Task is moved to "In Progress" or "Done" section; We will keep the task id, information of who has moved the task and to which part the task has been moved, as event data&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rnfYTHoG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/Event03_MovedTask-e1582468514718-1024x770.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rnfYTHoG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/Event03_MovedTask-e1582468514718-1024x770.png" alt="MovedTask" width="880" height="662"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's add an event class named "MovedTask.cs" to the Events folder inside the Core folder. Let's paste the code below into the class.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let's edit the Task.cs class as follows.&lt;/p&gt;

&lt;p&gt;We store the MovedTask event on aggregate with the Move method, so that we can send these stored events to the Event Store.&lt;br&gt;&lt;br&gt;
In the line 21, we apply the MovedTask event received from the Event Store to aggregate.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h5&gt;
  
  
  &lt;strong&gt;5.6. Complete Task&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;When Task is completed; We will keep task id, who has completed the task as event data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aOH8pntG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/Event05_CompletedTask-e1582468472380-1024x770.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aOH8pntG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/Event05_CompletedTask-e1582468472380-1024x770.png" alt="CompletedTask" width="880" height="662"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's add an event class named "CompletedTask.cs" to the Events folder inside the Core folder. Let's paste the code below into the class.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let's edit the Task.cs class as follows.&lt;/p&gt;

&lt;p&gt;With the Complete method, we store the CompletedTask event on aggregate so that we can send these stored events to the Event Store.&lt;br&gt;&lt;br&gt;
In the line 22, we apply the CompletedTask event received from the Event Store to aggregate.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;6. Preparing API Endpoints&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let's create a controller named "TasksController" and paste the code below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As you can see in the actions, firstly, events are taken from the Event Store with the AggregateRepository's Load method and aggregate is created. Then, new events are stored in aggregate with the use case methods on aggregate. With the AggregateRepository’s Save method, these stored events are sent to the Event Store.&lt;/p&gt;

&lt;p&gt;Let's run the API and send requests to the API.&lt;/p&gt;

&lt;p&gt;Let's create a task with the curl command line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -d "title=Event Store kurulacak" -H "Content-Type: application/x-www-form-urlencoded" -X POST https://localhost:44361/api/tasks/3a7daba9-872c-4f4d-8d6f-e9700d78c4f5/create
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's assign the task to someone with the curl command line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -d "assignedTo=Aziz CETİN" -H "Content-Type: application/x-www-form-urlencoded" -X PATCH https://localhost:44361/api/tasks/3a7daba9-872c-4f4d-8d6f-e9700d78c4f5/assign
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's pull the task to In-Progress with the curl command line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -d "section=2" -H "Content-Type: application/x-www-form-urlencoded" -X PATCH https://localhost:44361/api/tasks/3a7daba9-872c-4f4d-8d6f-e9700d78c4f5/move
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's pull the task to Done with the curl command line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -d "section=3" -H "Content-Type: application/x-www-form-urlencoded" -X PATCH https://localhost:44361/api/tasks/3a7daba9-872c-4f4d-8d6f-e9700d78c4f5/move
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's complete the task with the curl command line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -d -H "Content-Type: application/x-www-form-urlencoded" -X PATCH https://localhost:44361/api/tasks/3a7daba9-872c-4f4d-8d6f-e9700d78c4f5/complete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check the stream by entering the Event Store panel.  &lt;/p&gt;

&lt;p&gt;&lt;a href="http://localhost:2113/web/index.html#/streams/Task-3a7daba9-872c-4f4d-8d6f-e9700d78c4f5"&gt;http://localhost:2113/web/index.html#/streams/Task-3a7daba9-872c-4f4d-8d6f-e9700d78c4f5&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can access the final version of the project from &lt;a href="https://github.com/ahmetkucukoglu/aspnetcore-event-sourcing"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Good luck.&lt;/p&gt;

</description>
      <category>aspnetcore</category>
      <category>eventstore</category>
      <category>eventsourcing</category>
    </item>
    <item>
      <title>Couchbase GeoSearch with ASP.NET Core</title>
      <dc:creator>Ahmet Küçükoğlu</dc:creator>
      <pubDate>Wed, 20 May 2020 04:26:53 +0000</pubDate>
      <link>https://dev.to/ahmetkucukoglu/couchbase-geosearch-with-asp-net-core-i04</link>
      <guid>https://dev.to/ahmetkucukoglu/couchbase-geosearch-with-asp-net-core-i04</guid>
      <description>&lt;p&gt;This article was originally published at: &lt;a href="https://www.ahmetkucukoglu.com/en/couchbase-geosearch-with-asp-net-core/"&gt;https://www.ahmetkucukoglu.com/en/couchbase-geosearch-with-asp-net-core/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The subject of this article will be about how to do "GeoSearch" by using Couchbase.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Installing the Couchbase
&lt;/h2&gt;

&lt;p&gt;For this purpose, we create Couchbase cluster with the docker by running the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d --name couchbase -p 8091-8094:8091-8094 -p 11210:11210 couchbase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When Couchbase is up, it will start broadcasting at the address below.  &lt;/p&gt;

&lt;p&gt;&lt;a href="http://localhost:8091/"&gt;http://localhost:8091/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We create the cluster by clicking the "Setup New Cluster" button. We define the password as "123456".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--06W-Df6I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/03-Couchbase-Cluster.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--06W-Df6I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/03-Couchbase-Cluster.png" alt="Create New Cluster" width="587" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can make adjustment according to your current memory status. You can turn off "Analytics". We complete the cluster installation by clicking the "Save &amp;amp; Finish" button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--agVcJOm1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/05-Couchbase-Configure.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--agVcJOm1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/05-Couchbase-Configure.png" alt="Configure Cluster" width="590" height="718"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We go to "Buckets" from the left menu, click the "Add Bucket" button at the top of the right corner and create a bucket called "meetup".  &lt;/p&gt;

&lt;p&gt;&lt;a href="http://localhost:8091/ui/index.html#!/buckets"&gt;http://localhost:8091/ui/index.html#!/buckets&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EnYzx3kP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/07-Bucket-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EnYzx3kP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/07-Bucket-1.png" alt="Add Bucket" width="528" height="436"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Creating the API
&lt;/h2&gt;

&lt;p&gt;As an example, we will do the events section in the Meetup application that we all use. We will define events through the API. We will record the locations of these events. We will then query a list of events near by the current location.&lt;/p&gt;

&lt;p&gt;We create an ASP.NET Core API project. We install the nuget packages below.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package CouchbaseNetClient
dotnet add package Couchbase.Extensions.DependencyInjection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We add Couchbase connection information to the appsettings.json file.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;We define Couchbase in the Startup.cs file.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h5&gt;
  
  
  &lt;strong&gt;2.1. Creating an CreateEvent Endpoint&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;In the project, we create a folder named "Models" and add a class named "EventDocument" into it. This class will be the model of the document that we will add to the bucket named "events" in Couchbase.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Likewise, we add a class named "CreateEventRequest" under the "Models" folder. It will be the request model of endpoint, which will allow us to record this event.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We add a controller named "EventsController".&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now we can add events to Couchbase. Let's run the application and make requests from Postman as follows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6gXt4THa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/09-Create-AKS-1024x297.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6gXt4THa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/09-Create-AKS-1024x297.png" alt="Etkinlik Oluşturma - Azure Kubernetes Service (AKS)" width="880" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IhuUfN7Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/10-Create-GKE-1024x299.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IhuUfN7Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/10-Create-GKE-1024x299.png" alt="Etkinlik Oluşturma - Google Kubernetes Engine (GKE)" width="880" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IYWBk_HP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/11-Create-EKS-1024x299.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IYWBk_HP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/11-Create-EKS-1024x299.png" alt="" width="880" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we look at the documents of events bucket in Couchbase, we will see that it has been added.  &lt;/p&gt;

&lt;p&gt;&lt;a href="http://localhost:8091/ui/index.html#!/doc_editor?bucket=events"&gt;http://localhost:8091/ui/index.html#!/doc_editor?bucket=events&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9lLKEC8Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/12-Events-1024x551.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9lLKEC8Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/12-Events-1024x551.png" alt="Couchbase Event Buckets" width="880" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;2.2. Creating The Index That Allows Searching According To Location&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;In Couchbase, we come to "Search" from the left menu and click the "Add Index" button in the upper right corner.  &lt;/p&gt;

&lt;p&gt;&lt;a href="http://localhost:8091/ui/index.html#!/fts_new/?indexType=fulltext-index&amp;amp;sourceType=couchbase"&gt;http://localhost:8091/ui/index.html#!/fts_new/?indexType=fulltext-index&amp;amp;sourceType=couchbase&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We write "eventsgeoindex" in the Name field.&lt;br&gt;&lt;br&gt;
We select "events" from the Bucket field.&lt;/p&gt;

&lt;p&gt;Using the "+ insert child field" on the right side of the mapping named "default" under "Type Mappings", we add mappings as follows.&lt;/p&gt;

&lt;p&gt;We add mapping to save the "Subject" information in the event to "eventsgeoindex".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CIrDHr-k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/13-Events-Geo-Index-Subject.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CIrDHr-k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/13-Events-Geo-Index-Subject.png" alt="Events Geo Index Subject Mapping" width="880" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We add mapping to save the "Address" information in the event to "eventsgeoindex".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AsElWTfS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/14-Events-Geo-Index-Address.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AsElWTfS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/14-Events-Geo-Index-Address.png" alt="Events Geo Index Address Mapping" width="880" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We add mapping to save the "Date" information in the event to "eventsgeoindex".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C-VX8oYO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/15-Events-Geo-Index-Date.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C-VX8oYO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/15-Events-Geo-Index-Date.png" alt="Events Geo Index Date Mapping" width="880" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We add mapping to search according to the "Location" information in the event.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yGzQEHeK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/16-Events-Geo-Index-Location.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yGzQEHeK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/16-Events-Geo-Index-Location.png" alt=" Events Geo Index Location Mapping " width="880" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The final situation will be as in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b1V1HR1A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/17-Events-Geo-Index.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b1V1HR1A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/17-Events-Geo-Index.png" alt="Events Geo Index" width="880" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We create the index by clicking the "Create Index" button. When "Indexing progress" is 100%, it means that indexing has been finished.  &lt;/p&gt;

&lt;p&gt;&lt;a href="http://localhost:8091/ui/index.html#!/fts_list?open=eventsgeoindex"&gt;http://localhost:8091/ui/index.html#!/fts_list?open=eventsgeoindex&lt;/a&gt;&lt;/p&gt;
&lt;h5&gt;
  
  
  &lt;strong&gt;2.3. Creating The Endpoint GetNearbyEvents&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;We add a class named "GetUpcomingEventsRequest" under the "Models" folder. This will be the request model of endpoint, which will return events near by our location.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Likewise, we add a class named "GetUpcomingEventsResponse" under the "Models" file. This will be the endpoint's response model, which returns events that are near by our location.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We add a controller named "UpcomingEventsController".&lt;br&gt;&lt;br&gt;
In the line 30, we indicate that the search will be made on the basis of km.&lt;br&gt;&lt;br&gt;
In the line 40, we indicate the name of the "search index" that we will create in Couchbase.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now we can list events near by our location. Let's run the application and make requests from Postman as follows. By typing 1 and 2 to "Radius", you can see the events near 1 or 2km.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EpQ5xZ-1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/18-Upcoming-Events-1024x562.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EpQ5xZ-1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2020/02/18-Upcoming-Events-1024x562.png" alt="Upcoming Events" width="880" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can access the final version of the project from &lt;a href="https://github.com/ahmetkucukoglu/aspnetcore-couchbase-geosearch"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Good luck.&lt;/p&gt;

</description>
      <category>couchbase</category>
      <category>geosearch</category>
      <category>aspnetcore</category>
    </item>
    <item>
      <title>What is Event Sourcing?</title>
      <dc:creator>Ahmet Küçükoğlu</dc:creator>
      <pubDate>Sun, 12 Apr 2020 09:17:08 +0000</pubDate>
      <link>https://dev.to/ahmetkucukoglu/what-is-event-sourcing-29cd</link>
      <guid>https://dev.to/ahmetkucukoglu/what-is-event-sourcing-29cd</guid>
      <description>&lt;p&gt;This article was originally published at:  &lt;a href="https://www.ahmetkucukoglu.com/en/what-is-event-sourcing/" rel="noopener noreferrer"&gt;https://www.ahmetkucukoglu.com/en/what-is-event-sourcing/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Previously, our services would be as follows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.ahmetkucukoglu.com%2Fwp-content%2Fuploads%2F2019%2F12%2F01-1024x535.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.ahmetkucukoglu.com%2Fwp-content%2Fuploads%2F2019%2F12%2F01-1024x535.png" alt="Application Services 01"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This service consisted of hundreds of lines of code. To get rid of this confusion, we split our services into two parts as "Command" and "Query" with CQRS. We performed our CRUD operations with "Command" services and our query operations with "Query" services. Two separate services appeared as follows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.ahmetkucukoglu.com%2Fwp-content%2Fuploads%2F2019%2F12%2F02-1024x536.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.ahmetkucukoglu.com%2Fwp-content%2Fuploads%2F2019%2F12%2F02-1024x536.png" alt="Application Services 02"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this way, we achieved a little readability, but god classes were still emerging. "UseCase" s have entered our lives with Mediator. This time we started creating separate handlers for each "UseCase". 13 separate handlers appeared as follows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.ahmetkucukoglu.com%2Fwp-content%2Fuploads%2F2019%2F12%2F03-1024x536.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.ahmetkucukoglu.com%2Fwp-content%2Fuploads%2F2019%2F12%2F03-1024x536.png" alt="Application Services 03"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this approach, each handler just did its own job. The lines of code decreased further, readability increased even more. This gave us easy maintainability.&lt;/p&gt;

&lt;p&gt;This time we worked on performance. Each emerging database technology offered different features. Some of them was very good for fast writing and some of them was good for fast reading. Since we have seperated everything… We chose database technologies with good writing speed for “Command” operations and database technologies with good reading speed for “Query” operations. There was a problem. We had to synchronize data in two different database technologies.&lt;/p&gt;

&lt;p&gt;At this point, "Messaging" technologies came to our rescue. After writing the data to the database in the command handler, we sent the same data to the queues as a message. We wrote a consumer application that listens to messages in the queue. We transferred the messages that came with the consumers to the database which we had selected for “Query” operations. In this way, we achieved synchronization between two different database technologies.&lt;/p&gt;

&lt;p&gt;Then we realized that not everything was CRUD. It wasn't all about adding, updating and deleting data. What were we updating?&lt;/p&gt;

&lt;p&gt;Let's consider the Meetup application.&lt;/p&gt;

&lt;p&gt;For example, we define an event. This is an insert.&lt;/p&gt;

&lt;p&gt;After defining the event, we can update the content of the event. This is an update.&lt;/p&gt;

&lt;p&gt;Those who plan to attend the event state that they will go to the event. Is this an update for the event? If it is not update, what is it?&lt;/p&gt;

&lt;p&gt;We mark the status of the event as "Stopped" an hour before the event has started.&lt;/p&gt;

&lt;p&gt;After the event has been finished, we mark the status of the event as "Completed". So is this an update?&lt;/p&gt;

&lt;p&gt;As the owner of the event, we upload photos to the event. Is this also an update?&lt;/p&gt;

&lt;p&gt;Participants enter comments on the event. Do you think that it is an Update?&lt;/p&gt;

&lt;p&gt;As you can see, everything could not be thought of as Insert, Update and Delete. In fact, everything was an event as the following.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  MeetupRegistered&lt;/li&gt;
&lt;li&gt;  MeetupJoined&lt;/li&gt;
&lt;li&gt;  MeetupStopped&lt;/li&gt;
&lt;li&gt;  MeetupCompleted&lt;/li&gt;
&lt;li&gt;  MeetupAddedPhoto&lt;/li&gt;
&lt;li&gt;  MeetupAddedComment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If everything was an event, there was no need to keep our data in rows in related tables as we do in the classical method. Then we created a table as in the image below and added each event to this table as a line.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.ahmetkucukoglu.com%2Fwp-content%2Fuploads%2F2020%2F01%2F04-994x1024.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.ahmetkucukoglu.com%2Fwp-content%2Fuploads%2F2020%2F01%2F04-994x1024.png" alt="Events Table"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we look, we see that the event we have defined is just a join of these rows. Each event has its version number. When we join it from bottom to top, the result is as follows.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The event that we have defined represents "Aggregate" as a whole with its information, photos and comments. That's why AggregateId information is available.&lt;/p&gt;

&lt;p&gt;We said that in the "Command" operations we save our data as an event in a database as above. But since we cannot query these rows, we also need to write these events to the database we choose for "Query". For example when we want to show "incomplete events" in the meetup application, we cannot make an query in the events above.&lt;/p&gt;

&lt;p&gt;As I have mentioned in the previous paragraphs, after writing the event information to the database as an event in "Command" operations, we should send this information to a "messaging" queue. We should write a consumer listening to this queue. Through this consumer, we should listen to the "MeetupRegistered" events and write the necessary information and the event information to the "Query" database. In the same way, we should also listen to the "MeetupCompleted" events and delete the event information from the "Query" database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.ahmetkucukoglu.com%2Fwp-content%2Fuploads%2F2020%2F01%2F05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.ahmetkucukoglu.com%2Fwp-content%2Fuploads%2F2020%2F01%2F05.png" alt="Event Sourcing Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see above, events from the API in the "Command" area are written to the event store. These events are also sent to the queue. In the "Projection" area, the messages in the queue is written by being processed to the query store. Queries are made in the "Query" area, and results are returned from the API.&lt;/p&gt;

&lt;p&gt;This is Event Sourcing. It has unique terms like Aggregate, Projection, Snapshot etc. So, what technologies can we choose for "Command", "Messaging" and "Query"?&lt;/p&gt;

&lt;p&gt;"MSSQL" can be used for events. "RabbitMQ" can be used for "Messaging". Technologies such as "RavenDB, ElasticSearch, Couchbase" can be used for "Query". But for Event Sourcing, there is a technology called "Event Store" in the .NET world. This technology offers solutions for "Aggregate" and "Projection". In other words, in addition to providing the store where we can record the events, it also provides the "Messaging" and "Projection" services, which are necessary for us to record in “Query” databases.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eventstore.org/" rel="noopener noreferrer"&gt;Event Store&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have been adding practical informations to my blog rather than theoretical one. So I have prefered to write Tutorial style articles. But this time, I wanted to give first some theoretical informations for Event Sourcing. I intend to come up with a video that we will put the theory into practice soon. In that video, I will develop a sample application without going into definitions too much. For this reason, I wanted to establish the basis for that video with this theoretical article.&lt;/p&gt;

&lt;p&gt;Good luck.&lt;/p&gt;

</description>
      <category>cqrs</category>
      <category>eventsourcing</category>
      <category>eventstore</category>
      <category>messaging</category>
    </item>
    <item>
      <title>Publishing Docker Image as Serverless on GCP</title>
      <dc:creator>Ahmet Küçükoğlu</dc:creator>
      <pubDate>Wed, 26 Feb 2020 06:57:01 +0000</pubDate>
      <link>https://dev.to/ahmetkucukoglu/publishing-docker-image-as-serverless-on-gcp-4ic2</link>
      <guid>https://dev.to/ahmetkucukoglu/publishing-docker-image-as-serverless-on-gcp-4ic2</guid>
      <description>&lt;p&gt;This article was originally published at:  &lt;a href="https://www.ahmetkucukoglu.com/en/publishing-docker-image-as-serverless-on-gcp/"&gt;https://www.ahmetkucukoglu.com/en/publishing-docker-image-as-serverless-on-gcp/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;With the serverless approach, the problem about the server that the software developer confronts with has disappeared. Now we write our code and call the provider to run it. We are not dealing with server configurations, scalings etc. And pay as you go. This is a great opportunity.&lt;/p&gt;

&lt;p&gt;AWS's Lambda, GCP's Cloud Function, Azure's Azure Function etc., these services provide us this service. But this time, different kind of problem appears. These services do not support all languages. Even if it supports the language we want, it may not support the version we want. For example, AWS Lambda does not support the upper versions of .NET Core 2.1 yet. This is a problem. Nobody can restrict us :)&lt;/p&gt;

&lt;p&gt;The Cloud Run service that Google built on Knative completely solves this problem. We give Cloud Run a docker image and Cloud Run runs our serverless service from this image. So whether we develop in PHP or .NET Core, it doesn't matter. There is no limit as long as we can make dockerize. This is awesome.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Preparing the Development Environment
&lt;/h2&gt;

&lt;p&gt;In this part we will arrange our development environment. You can apply exactly the second part of my previous article, &lt;a href="https://www.ahmetkucukoglu.com/en/publishing-the-asp-net-core-application-in-gcp-kubernetes/"&gt;Publishing the ASP.NET Core Application in GCP Kubernetes&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Preparing GCP
&lt;/h2&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;3.1. Creating the Project&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Before we can use Google Cloud services, we need to create a project. You need to run the following command from the terminal. You can update PROJECT_ID and PROJECT_NAME fields according to your.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud projects create [PROJECT_ID] --name=[PROJECT_NAME]
gcloud projects create my-cloud-run-api-project-1 --name="My Cloud Run API Project"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AZgpMNMA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/01-Project-Create-1024x596.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AZgpMNMA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/01-Project-Create-1024x596.png" alt="gcloud project create" width="880" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can run the command below to see the project created.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud projects list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;3.2. Choosing the Project&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;We need to define the project that we have created on google cloud config on our local machine. You need to run the following command from the terminal. Remember to update the PROJECT_ID field according to you.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud config set project [PROJECT_ID]
gcloud config set project my-cloud-run-api-project-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hPBrO9rZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/03-Set-Project-1024x598.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hPBrO9rZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/03-Set-Project-1024x598.png" alt="gcloud config set project" width="880" height="514"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h5&gt;
  
  
  &lt;strong&gt;3.3. Activating the Billing&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Before we publish the application, we need to link an billing account to the project that we have created. To learn your Account Id, you need to run the following command from the terminal.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud beta billing accounts list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You need to run the following command to install the alpha commands of the Google SDK.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud components install alpha
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NopPdI_W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Account-Link-02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NopPdI_W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Account-Link-02.png" alt="gcloud components install alpha" width="880" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the process is complete, you need to run the following command to link the Account Id to your project. Remember to update the PROJECT_ID and ACCOUNT_ID fields according to you.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud alpha billing projects link [PROJECT_ID] --billing-account [ACCOUNT_ID]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can run the command below to see that the bill has been successfully linked to your project. Remember to update the ACCOUNT_ID field according to you.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud beta billing projects list --billing-account=[ACCOUNT_ID]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;3.4. Activating the Cloud Run API&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;It is required to activate Cloud Run API from Google Cloud APIs. You need to run the following command from the terminal.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud services enable run.googleapis.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;3.5. Activating the Container Registry API&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Container Registry API needs to be activated from Google Cloud APIs. You need to run the following command from the terminal.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud services enable containerregistry.googleapis.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  4. Publishing the Application
&lt;/h2&gt;

&lt;p&gt;I created a simple API. You can pull this API from Github with the command below.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/ahmetkucukoglu/aspnetcore-gcloud-run-sample.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;There is one thing we need to pay attention. It is that when Cloud Run running a service from the docker image, it set the port on its own. It writes this port to environment variable. It wants us to run the application that we have written in a way for this port to listen. If we don't, Cloud Run stops service if it doesn't receive a response when it does health check.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;You can see how it is set in lines 11 and 12.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;4.1. Creating the Image and Sending the Image to GCR&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;The project includes Dockerfile. We should create an image in the docker with the following command. You can set the IMAGE_ID field according to you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t [IMAGE_ID] -f CloudRunSampleAPI/Dockerfile .
docker build -t my-cloud-run-api-image:1.0 -f CloudRunSampleAPI/Dockerfile .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's first create a tag to send this image we have created to GCR. Remember to update the LOCAL_IMAGE_ID, PROJECT_ID and IMAGE_ID fields according to you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker tag [LOCAL_IMAGE_ID] gcr.io/[PROJECT_ID]/[IMAGE_ID]
docker tag my-cloud-run-api-image:1.0 gcr.io/my-cloud-run-api-project-1/my-cloud-run-api-image:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's send the image to GCR using this tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker push gcr.io/[PROJECT_ID]/[IMAGE_ID]
docker push gcr.io/my-cloud-run-api-project-1/my-cloud-run-api-image:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MV8TrUEy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/09-Docker-Push-1024x586.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MV8TrUEy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/09-Docker-Push-1024x586.png" alt="docker push gcr.io" width="880" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To see the image sent to GCR, you can run the command below from the terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud container images list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;strong&gt;4.2. Deploying the Application&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;We have to deploy our application using the image we created above. You need to run the following command from the terminal. Remember to update the SERVICE_NAME and IMAGE_ID fields according to your own information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud beta run deploy [SERVICE_NAME] --image [IMAGE_ID] --platform managed --region europe-west1 --update-env-vars APIKey=Key123,APISecret=Secret456
gcloud beta run deploy my-cloud-run-api --image gcr.io/my-cloud-run-api-project-1/my-cloud-run-api-image:1.0 --platform managed --region europe-west1 --update-env-vars APIKey=Key123,APISecret=Secret456
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eZfmYngt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/11-Run-Deploy-1024x585.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eZfmYngt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/11-Run-Deploy-1024x585.png" alt="gcloud beta run deploy" width="880" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We saw the endpoint at the terminal. You can test it now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uj3diSDv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/12-GET-1-1024x565.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uj3diSDv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/12-GET-1-1024x565.png" alt="GET" width="880" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can access the final version of the project from &lt;a href="https://github.com/ahmetkucukoglu/aspnetcore-gcloud-run-sample"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Good luck.&lt;/p&gt;

</description>
      <category>gcloud</category>
      <category>serverless</category>
      <category>dotnet</category>
      <category>aspnetcore</category>
    </item>
    <item>
      <title>Developing AWS Serverless Messaging System</title>
      <dc:creator>Ahmet Küçükoğlu</dc:creator>
      <pubDate>Tue, 18 Feb 2020 06:03:21 +0000</pubDate>
      <link>https://dev.to/ahmetkucukoglu/developing-aws-serverless-messaging-system-107p</link>
      <guid>https://dev.to/ahmetkucukoglu/developing-aws-serverless-messaging-system-107p</guid>
      <description>&lt;p&gt;This article was originally published at:  &lt;a href="https://www.ahmetkucukoglu.com/en/developing-aws-serverless-messaging-system/"&gt;https://www.ahmetkucukoglu.com/en/developing-aws-serverless-messaging-system/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;This article will be about how to develop the messaging system with the serverless approach. We will use AWS as a cloud provider. We will prefer .NET Core as the language.&lt;/p&gt;

&lt;p&gt;In this part, I will set up the scenario and give preliminary information about what will be the result.&lt;/p&gt;

&lt;p&gt;Our RESTful API endpoints will be as follows.&lt;/p&gt;

&lt;p&gt;[POST] api/comments&lt;br&gt;&lt;br&gt;
[GET] api/comments&lt;/p&gt;

&lt;p&gt;We will use the AWS services below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API Gateway :&lt;/strong&gt; It will provide the endpoints we need for the RESTful API.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Lambda :&lt;/strong&gt; It will provide us to write function for the GET and POST requests.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;SQS :&lt;/strong&gt; It will provide a messaging system. In POST request, we will send the comment texts to the queue for later processing.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Comprehend :&lt;/strong&gt; It will provide machine learning system. We will use it to detect the languages of the comment texts entered.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;DynamoDB :&lt;/strong&gt; It will provide NoSQL solution. In the POST request, we will write the data to the DynamoDB.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;S3 :&lt;/strong&gt; It will provide our code to be versioned and stored after each deployment.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;CloudFormation :&lt;/strong&gt; It will provide us to create and manage automatically all services mentioned above.&lt;/p&gt;

&lt;p&gt;When the project is completed, the architecture on AWS will be as follows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L-KwPesV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/Serverless-Messaging-System-on-AWS-1024x607.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L-KwPesV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/Serverless-Messaging-System-on-AWS-1024x607.png" alt="Serverless Messaging Architecture" width="880" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will get the comment text from the API with the POST method. We will save this comment to DynamoDB and return result. Since it will take a long time to automatically detect the language of the comment text, we will send the comment text to the queue. The lambda function, which listens to the messages in the queue will use the Comprehend service to detect the language. After getting the result, the record in DynamoDB will be updated. We will return the final version of the comment texts with the GET method from the API.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Preparing Development Environment
&lt;/h2&gt;

&lt;p&gt;In this part, we will arrange the development environment. We can apply the second part of the article, &lt;a href="https://www.ahmetkucukoglu.com/en/developing-aws-serverless-restful-api/"&gt;Developing AWS Serverless RESTful API&lt;/a&gt;. We need to include the following policies in the permission section.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  AmazonSQSFullAccess&lt;/li&gt;
&lt;li&gt;  ComprehendFullAccess&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  3. Preparing API Project
&lt;/h2&gt;

&lt;p&gt;In this part, we will create the project in its simplest form and make deployment. We will not send data to DynamoDB and SQS yet. We will send request to endpoints and get response.&lt;/p&gt;

&lt;p&gt;Create the project folder with the command line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir serverless-sqs
cd serverless-sqs
code .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We will create two separate projects. One is the API project and the other is the Consumer project, which listens to the messages in the queue. Create an api folder with the following command line from the terminal from VS Code and enter the folder.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir api
cd api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create the serverless project with the command line below.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless create --template aws-csharp --name comments-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We will see a file named "Handler.cs". This is the entry point of the application. We will need two functions, GET and POST. While this is possible in Nodejs, it is troublesome in .NET Core. Because we will need to edit the output manually and it is something you would not like :). Therefore, we will make arrangements for the ASP.NET Core API to run when a request comes to lambda. In this way, we will direct the requests to actions on the controller with the help of proxy.&lt;/p&gt;

&lt;p&gt;Start with cleaning first. Delete the file "Handler.cs". Delete the installed packages with the following command lines.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet remove package Amazon.Lambda.Core
dotnet remove package Amazon.Lambda.Serialization.Json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Change the "hello.zip" in the build.cmd and build.sh files in the project as "api-handler.zip". When we build the project, an artifact named properly shall be created. :) Shortly after, I will show how to use this artifact in serverless.yml.&lt;/p&gt;

&lt;p&gt;We need to install some packages because we will run ASP.NET Core API. Install the packages with the following command lines.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Microsoft.AspNetCore.App -v 2.1.4
dotnet add package Amazon.Lambda.AspNetCoreServer
dotnet add package AWSSDK.Extensions.NETCore.Setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create a file named "Startup.cs" and paste the following code.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Now, set the entry point of the lambda. Create a file named "LambdaEntryPoint.cs" and paste the code below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Update the serverless.yml file with the code below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;On the 16th line, specify the entry point of the application as a LambdaEntryPoint file.&lt;br&gt;&lt;br&gt;
On the 19th line, create a proxy endpoint in the API Gateway. In this way, we transfer the requests coming to API Gateway directly to the Controllers matching in the project.&lt;br&gt;&lt;br&gt;
On the 23th line, specify the path of the artifact we need when deploying the application.&lt;/p&gt;

&lt;p&gt;Now we can create Controller. Create a folder named "Controllers" and create a file named "CommentsController.cs" in it. Paste the code below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Create a folder named "Models" and create a file named "CommentsPostRequest.cs" in it. Paste the code below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Build the code with the command line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SSlOL7Bg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/01-Build-1024x504.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SSlOL7Bg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/01-Build-1024x504.png" alt="Serverless API build output" width="880" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make our first deployment to AWS with the command line below.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After the deployment process, it will write 1 endpoint and 1 API Key on the console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P7wXn28g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/Step-1-1024x406.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P7wXn28g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/Step-1-1024x406.png" alt="Serverless deployment output" width="880" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's look at what changed in AWS after the process.&lt;/p&gt;

&lt;p&gt;A Stack has been created in the &lt;a href="https://eu-central-1.console.aws.amazon.com/cloudformation/home?region=eu-central-1"&gt;Cloud Formation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oOI8Gl11--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/003-CloudFormation-1024x532.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oOI8Gl11--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/003-CloudFormation-1024x532.png" alt="Serverless API CloudFormation" width="880" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our code has been sent to &lt;a href="https://s3.console.aws.amazon.com/s3/home?region=eu-central-1"&gt;S3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bFtAc_H_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/004-S3-1024x531.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bFtAc_H_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/004-S3-1024x531.png" alt="Serverless API S3" width="880" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eu-central-1.console.aws.amazon.com/apigateway/home?region=eu-central-1"&gt;API Gateway&lt;/a&gt; has been created for the endpoints.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YWAZ_P46--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/005-API-Gateway-1024x532.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YWAZ_P46--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/005-API-Gateway-1024x532.png" alt="Serverless API Gateway" width="880" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eu-central-1.console.aws.amazon.com/lambda/home?region=eu-central-1#/functions"&gt;Lambda&lt;/a&gt; function has been created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ndpjZdOt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/006-Lambda-1024x532.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ndpjZdOt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/006-Lambda-1024x532.png" alt="Serverless API Lambda" width="880" height="457"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Integrating DynamoDB and SQS into API Project
&lt;/h2&gt;

&lt;p&gt;In this part, we will write the comment text to DynamoDB in the POST request coming from the API and send a message the queue in SQS. In the GET request, we will return the comment texts from DynamoDB.&lt;/p&gt;

&lt;p&gt;Install the packages we need with the following command lines.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package AWSSDK.DynamoDBv2
dotnet add package AWSSDK.SQS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Update the serverless.yml file as follows.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;On the 43th line, define the resource that will be created for DynamoDB.&lt;br&gt;&lt;br&gt;
On the 46th line, name the table.&lt;br&gt;&lt;br&gt;
On the 66th line, export the ARN of DynamoDB that we have created. On the 72th line, export the name of the table. We will use DynamoDB by importing this ARN and the table name we have exported to the consumer project.&lt;br&gt;&lt;br&gt;
On the 11th line, assign the name of the table we have created as environment variable.&lt;br&gt;&lt;br&gt;
On the 23th line, give full access to DynamoDB, which we have created on lambda.&lt;/p&gt;

&lt;p&gt;On the 40th line, define the resource that will create the SQS.&lt;br&gt;&lt;br&gt;
On the 43th line, name the queue.&lt;br&gt;&lt;br&gt;
On the 78th line, export the ARN of the SQS we have created. We will use SQS by importing this ARN we have exported to the consumer project.&lt;br&gt;&lt;br&gt;
On the 13th line, assign the name of the table we have created as environment variable.&lt;br&gt;&lt;br&gt;
On the 18th line, give full access to lambda that it to SQS.&lt;/p&gt;

&lt;p&gt;Update the Startup.cs file as follows.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;On the 12th and 1t3th lines, register DynamoDB and SQS clients to IOC Container.&lt;/p&gt;

&lt;p&gt;Create a file named "CommentsGetResponse.cs" under the Models folder and paste the code below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Create a file named "CommentsQueueRequest.cs" under the Models folder and paste the code below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Update the CommentsController.cs file with the code below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;On the 39th line, return the comment texts from DynamoDB.&lt;br&gt;&lt;br&gt;
On the 61th line, save the comment text to DynamoDB.&lt;br&gt;&lt;br&gt;
On the 76th line, send a message to the queue we have created in SQS to be processed.&lt;/p&gt;

&lt;p&gt;Build the code with the command line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zDEe6siG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/07-Build-1024x513.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zDEe6siG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/07-Build-1024x513.png" alt="Serverless consumer build output" width="880" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make our deployment to AWS with the command line below.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MBYlTLvR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/08-Deploy-1024x424.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MBYlTLvR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/08-Deploy-1024x424.png" alt="Serverless consumer deployment output" width="880" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make a POST request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XDbgSk4F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/11-POST-1024x563.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XDbgSk4F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/11-POST-1024x563.png" alt="Serverless POSTMAN POST" width="880" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make a GET request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R6_K2G5R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/12-GET-1024x564.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R6_K2G5R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/12-GET-1024x564.png" alt="Serverless POSTMAN GET" width="880" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's look at what changed in AWS after the process.&lt;/p&gt;

&lt;p&gt;A table has been created in &lt;a href="https://eu-central-1.console.aws.amazon.com/dynamodb/home?region=eu-central-1#tables:selected=Comments;tab=items"&gt;DynamoDB&lt;/a&gt; and the record has been sent to the table with the POST request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o5o2lepm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/009-DynamoDB-1024x532.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o5o2lepm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/009-DynamoDB-1024x532.png" alt="Serverless API DynamoDB" width="880" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A queue has been created in &lt;a href="https://eu-central-1.console.aws.amazon.com/sqs/home?region=eu-central-1"&gt;SQS&lt;/a&gt; and a message has been sent to the queue with the POST request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ILyGtahm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/010-SQS-1024x532.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ILyGtahm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/010-SQS-1024x532.png" alt="Serverless API SQS" width="880" height="457"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Preparing the Consumer Project
&lt;/h2&gt;

&lt;p&gt;In this part, we will create the consumer project, which will process the messages we have sent to the queue in SQS. Create the consumer folder by running the following command line in the terminal from VS Code and enter it.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir consumer
cd consumer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create our serverless project with the command line below.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless create --template aws-csharp --name comments-consumer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Start with cleaning first again. Delete the file named Handler.cs.&lt;/p&gt;

&lt;p&gt;Change the "hello.zip" in the build.cmd and build.sh files in the project as "consumer-handler.zip". When we build the project, an artifact named properly shall be created. Shortly after, I will show how to use this artifact in serverless.yml.&lt;/p&gt;

&lt;p&gt;It is necessary to install SQSEvents package to listen to messages in the queue in SQS, and Comprehend package to find the language of the comment text, and DynamoDB package for NoSQL. Install the packages with the following command lines.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Amazon.Lambda.SQSEvents
dotnet add package AWSSDK.Comprehend
dotnet add package AWSSDK.DynamoDBv2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create a folder named "Models" and create a file named "CommentsQueueRequest.cs" in it and paste the code below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Create a file named "ConsumerHandler.cs" and paste the code below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;On the 21th line, take the message in SQS. Since we will take the messages one by one in our example, it is enough to take the value in the zero index. For example, if we were going to take the messages ten by ten, we would have to loop them.&lt;br&gt;&lt;br&gt;
On the 32th line, make the language querying of the comment text from the Comprehend service.&lt;br&gt;&lt;br&gt;
On the 48th line, update the line in DynamoDB.&lt;/p&gt;

&lt;p&gt;Update the serverless.yml file with the code below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;On the 9th line, import the name of the DynamoDB table that we have exported in api project.&lt;br&gt;&lt;br&gt;
On the 13th line, give full access to the SQS we have created.&lt;br&gt;&lt;br&gt;
On the 18th line, give access to the language querying function in the Comprehend service.&lt;br&gt;&lt;br&gt;
On the 23th and 24th lines, give access to DynamoDB.&lt;br&gt;&lt;br&gt;
On the 35th line, connect the trigger to the queue in SQS.&lt;br&gt;&lt;br&gt;
On the 38th line, define that the messages should be transmitted to lambda one by one.&lt;/p&gt;

&lt;p&gt;Build our code with the command line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K2hOeFQc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/13-Build-1024x518.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K2hOeFQc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/13-Build-1024x518.png" alt="Serverless consumer build output" width="880" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make our deployment with the command line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_9CpF86v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/14-Deploy-1024x497.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_9CpF86v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/14-Deploy-1024x497.png" alt="Serverless consumer deployment output" width="880" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's look at what changed in AWS after the process.&lt;/p&gt;

&lt;p&gt;A stack has ben created in &lt;a href="https://eu-central-1.console.aws.amazon.com/cloudformation/home?region=eu-central-1"&gt;Cloud Formation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SapiEQGo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/015-CloudFormation-1024x532.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SapiEQGo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/015-CloudFormation-1024x532.png" alt="Serverless Consumer CloudFormation" width="880" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our code has been sent to &lt;a href="https://s3.console.aws.amazon.com/s3/home?region=eu-central-1"&gt;S3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--66w_Aea2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/016-S3-1024x532.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--66w_Aea2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/016-S3-1024x532.png" alt="Serverless Consumer S3" width="880" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our &lt;a href="https://eu-central-1.console.aws.amazon.com/lambda/home?region=eu-central-1#/functions"&gt;Lambda&lt;/a&gt; function has been created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ByUEeOhX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/017-Lambda-1024x532.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ByUEeOhX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/017-Lambda-1024x532.png" alt="Serverless Consumer Lambda" width="880" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the previous part, we have made a POST request and send a message on the queue in SQS. Now, that message has been processed. When you make a GET request, you will see that the language of the comment text is updated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fXdHquhG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/18-GET-1024x565.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fXdHquhG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/18-GET-1024x565.png" alt="Serverless POSTMAN GET" width="880" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can continue trying by making POST requests.&lt;/p&gt;

&lt;p&gt;You can access the final version of the project from &lt;a href="https://github.com/ahmetkucukoglu/serverless-queuing"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Good luck.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>sqs</category>
      <category>aws</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Publishing the ASP.NET Core Application in GCP Kubernetes</title>
      <dc:creator>Ahmet Küçükoğlu</dc:creator>
      <pubDate>Tue, 04 Feb 2020 13:30:17 +0000</pubDate>
      <link>https://dev.to/ahmetkucukoglu/publishing-the-asp-net-core-application-in-gcp-kubernetes-3jdd</link>
      <guid>https://dev.to/ahmetkucukoglu/publishing-the-asp-net-core-application-in-gcp-kubernetes-3jdd</guid>
      <description>&lt;p&gt;This article was originally published at:  &lt;a href="https://www.ahmetkucukoglu.com/en/publishing-the-asp-net-core-application-in-gcp-kubernetes/"&gt;https://www.ahmetkucukoglu.com/en/publishing-the-asp-net-core-application-in-gcp-kubernetes/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;The subject of this article series is about how to publish API, which we developed with ASP:NET Core, in Kubernetes. We will use GCP(Google Cloud Platform) as a cloud provider.&lt;/p&gt;

&lt;p&gt;In this part, i will show the scenario and give preliminary information about what will be the result. Also i will mention briefly some concepts in Kubernetes.&lt;/p&gt;

&lt;p&gt;We will develop an API containing single endpoint.&lt;br&gt;&lt;br&gt;
We will dockerize that API. For this, we will create a dockerfile.&lt;br&gt;&lt;br&gt;
We will send the image we have created with the dockerfile to GCR(Google Cloud Container Registry).&lt;br&gt;&lt;br&gt;
We will start three containers from this image.&lt;br&gt;&lt;br&gt;
We will create "Load Balancer" service, which will distribute the requests coming to the application to the containers.&lt;/p&gt;

&lt;p&gt;I want to mention five concepts in Kubernetes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cluster&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Cluster is a kubernetes server. In the process of creating Cluster, same introductions are applied like how many "master" and " node" will be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pod&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Pod represents the application. It means that the application runs on pods. It corresponds to the container in Docker.  &lt;/p&gt;

&lt;p&gt;For more information, you can visit the address below.&lt;br&gt;&lt;br&gt;
&lt;a href="https://cloud.google.com/kubernetes-engine/docs/concepts/pod"&gt;https://cloud.google.com/kubernetes-engine/docs/concepts/pod&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Deployment allows pods to be managed. We define by using the deployment how many pods to be started, which images the pods will use, which environment variables to be assigned with these pods.  &lt;/p&gt;

&lt;p&gt;For more information, you can visit the address below.&lt;br&gt;&lt;br&gt;
&lt;a href="https://cloud.google.com/kubernetes-engine/docs/concepts/deployment"&gt;https://cloud.google.com/kubernetes-engine/docs/concepts/deployment&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Service allows to make the applications running with pods accessible from outside. We will configure our service as "Load Balancer".  &lt;/p&gt;

&lt;p&gt;For more information, you can visit the address below.&lt;br&gt;&lt;br&gt;
&lt;a href="https://cloud.google.com/kubernetes-engine/docs/concepts/service"&gt;https://cloud.google.com/kubernetes-engine/docs/concepts/service&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Namespace&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It provides isolation in the cluster. It allows pods, deployments and services to come together under a "namespace". It allows the applications to be isolated from each other in case of more than one application is in the cluster. It means that each application runs under a namespace which belongs itself.  &lt;/p&gt;

&lt;p&gt;For more information, you can visit the address below.&lt;br&gt;&lt;br&gt;
&lt;a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/"&gt;https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Preparing the Development Environment
&lt;/h2&gt;

&lt;p&gt;In this part, we will arrange the development environment.&lt;/p&gt;

&lt;p&gt;Requirements&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Visual Studio Code&lt;/li&gt;
&lt;li&gt;  Docker Desktop&lt;/li&gt;
&lt;li&gt;  Google Cloud Account&lt;/li&gt;
&lt;li&gt;  Google Cloud SDK&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;
  
  
  &lt;strong&gt;2.1. Installing the Docker Desktop&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;The Docker Desktop is needed to be installed in the machine. You can download the application from the address below and install the application just by clicking next. :)  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.docker.com/products/docker-desktop"&gt;https://www.docker.com/products/docker-desktop&lt;/a&gt;&lt;/p&gt;
&lt;h5&gt;
  
  
  &lt;strong&gt;2.2. Opening a Google Cloud Account&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;You need to open a Google Cloud account with your Google account. When you open a cloud account, a promotion is defined to allow us to use the application within a year. You can do tryings by using the promotion.  &lt;/p&gt;

&lt;p&gt;You can open a Google Cloud account from the link below. After opening the account, a band will appear above the page. You can activate the promotion from the activate button.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://console.cloud.google.com/?hl=tr"&gt;https://console.cloud.google.com/?hl=tr&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xs6vXR9F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Register-02-1024x392.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xs6vXR9F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Register-02-1024x392.png" alt="Billing Google Cloud Platform" width="880" height="337"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h5&gt;
  
  
  &lt;strong&gt;2.3. Installing the Google Cloud SDK&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Since you will run the commands on your local machine, the Google Cloud SDK needs to be installed. You can download the application from the address below and install the application just by clicking next. :)  &lt;/p&gt;

&lt;p&gt;Note: In the fifth step, when you are asked for the components to be installed, you need to activate "The Beta Commands" option.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://cloud.google.com/sdk/docs/quickstart-windows"&gt;https://cloud.google.com/sdk/docs/quickstart-windows&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;The "gcloud init" commad will run automatically when the Google Cloud SDK has been installed. Authorization will be made for you to access Google Cloud from your local machine. For this reason, you will need to enter your google account information.  &lt;/p&gt;

&lt;p&gt;You can say no when you are asked if you want to create a project. We will create the project ourselves.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aFLB7Tmk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/SDK-Init-03-1024x602.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aFLB7Tmk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/SDK-Init-03-1024x602.png" alt="gcloud init" width="880" height="517"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h5&gt;
  
  
  &lt;strong&gt;2.4. Introducing the GCR&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;In order for the images to be sent to the GCR instead of the DockerHub, we need to make configuration. You must run the following command from the terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud auth configure-docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nH8POf1N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/SDK-Init-05-1024x601.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nH8POf1N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/SDK-Init-05-1024x601.png" alt="gcloud auth configure-docker" width="880" height="516"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Preparing the GCP
&lt;/h2&gt;
&lt;h5&gt;
  
  
  &lt;strong&gt;3.1. Activating the Kubernetes API&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Activating the Kubernetes Engine API, which is one of the Google Cloud APIs, is required. You must run the following command from the terminal.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud services enable container.googleapis.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;3.2. Creating the Project&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;You need to create a project to be able to use Google Cloud services. You need to run the following command from the terminal. You can update PROJECT_ID and PROJECT_NAME fields by yourself.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud projects create [PROJECT_ID] --name=[PROJECT_NAME]
gcloud projects create my-k8s-api-project-1 --name="My K8S API Project"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0UVgN_Yb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Project-Creation-03-1024x601.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0UVgN_Yb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Project-Creation-03-1024x601.png" alt="gcloud project create" width="880" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can run the command below to see the project created.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud projects list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;3.3. Choosing the Project&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;You need to define the project you have created on google cloud config in your local machine. You need to run the command below from the terminal. Remember to update the PROJECT_ID field according to your information.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud config set project [PROJECT_ID]
gcloud config set project my-k8s-api-project-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--29sHUP4e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Config-Set-02-1024x603.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--29sHUP4e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Config-Set-02-1024x603.png" alt="gcloud config set project" width="880" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can run the command below to see whether the project has been added to the configuration.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud config get-value core/project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;3.4. Activating the Billing&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Before creating a cluster, you must link a billing account to the project you have created. To learn your Account Id, you need to run the following command from the terminal.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud beta billing accounts list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You need to run the following command to install the alpha commands of the Google SDK.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud components install alpha
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NopPdI_W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Account-Link-02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NopPdI_W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Account-Link-02.png" alt="gcloud components install alpha" width="880" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the prcoess is complete, you need to run the following command to link the Account Id to your project. Remember to update the PROJECT_ID and ACCOUNT_ID fields according to your information.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud alpha billing projects link [PROJECT_ID] --billing-account [ACCOUNT_ID]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can run the command below from the terminal to see that the invoice has been successfully linked to your project. Remember to update the ACCOUNT_ID field according to your information.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud beta billing projects list --billing-account=[ACCOUNT_ID]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;3.5. Creating the Cluster&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;You need to run the command below to create cluster. Remember to update CLUSTER_ID and PROJECT_ID fields according to your information.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud beta container clusters create [CLUSTER_ID] --project=[PROJECT_ID] --addons=Istio --istio-config=auth=MTLS_STRICT --cluster-version=latest --machine-type=n1-standard-2 --num-nodes=1 --region europe-west1

gcloud beta container clusters create my-k8s-api-cluster-1 --project=my-k8s-api-project-1 --addons=Istio --istio-config=auth=MTLS_STRICT --cluster-version=latest --machine-type=n1-standard-2 --num-nodes=1 --region europe-west1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Wyu07koI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Cluster-Creation-03-1024x602.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Wyu07koI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Cluster-Creation-03-1024x602.png" alt="gcloud beta container clusters create" width="880" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can run the comand below to see the cluster created.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud container clusters list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;All preparations have been done. Now you can publish the project in the Kubernetes.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Publishing the application
&lt;/h2&gt;

&lt;p&gt;I have created a simple API. You can clone this API from Github with the command below.&lt;/p&gt;

&lt;p&gt;git clone &lt;a href="https://github.com/ahmetkucukoglu/aspnetcore-k8s-sample.git"&gt;https://github.com/ahmetkucukoglu/aspnetcore-k8s-sample.git&lt;/a&gt;&lt;br&gt;
cd aspnetcore-k8s-sample&lt;/p&gt;
&lt;h5&gt;
  
  
  &lt;strong&gt;4.1. Creating the Dockerfile and Sending the Image to GCR&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Create a .Dockerfile file in the project.&lt;/p&gt;

&lt;p&gt;You need to create an image in the docker with the following command. You can determine the IMAGE_ID field by yourself.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t [IMAGE_ID] -f K8SSampleAPI/Dockerfile .
docker build -t my-k8s-api-image:1.0 -f K8SSampleAPI/Dockerfile .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create a tag firstly to send this image we have created to GCR. Don't forget to update the LOCAL_IMAGE_ID, PROJECT_ID and IMAGE_ID fields according to your own information.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker tag [LOCAL_IMAGE_ID] gcr.io/[PROJECT_ID]/[IMAGE_ID]
docker tag my-k8s-api-image:1.0 gcr.io/my-k8s-api-project-1/my-k8s-api-image:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Send the image to GCR using this tag.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker push gcr.io/[PROJECT_ID]/[IMAGE_ID]
docker push gcr.io/my-k8s-api-project-1/my-k8s-api-image:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tOd-b6kB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Image-Creation-06-1024x602.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tOd-b6kB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Image-Creation-06-1024x602.png" alt="docker push gcr.io" width="880" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can run the command below from the terminal to see the image sent to GCR.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud container images list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;4.2. Creating the Namespace&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;I mentioned the namespace in the first part. Create a namespace.yaml file in the project.&lt;/p&gt;

&lt;p&gt;On the 4th line, define a name for the namespaces.&lt;br&gt;&lt;br&gt;
On the 6th line, define the label. We use the labels as tags. You can define a label as a key/value as you want.&lt;/p&gt;

&lt;p&gt;Now, define this namespace in the Kubernetes cluster.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create -f K8SSampleAPI/namespace.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yotzyYyn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Kubectl-Namespace-1024x603.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yotzyYyn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Kubectl-Namespace-1024x603.png" alt="kubectl create namespace" width="880" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can run the command below from the terminal to see the namespace created.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get namespaces --show-labels
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;4.3. Creating the Deployment&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;In the first part, I mentioned deployment. Create a deployment.yaml file in the project.&lt;/p&gt;

&lt;p&gt;On the 7th line, determine how many pods will be removed.&lt;br&gt;&lt;br&gt;
On the 11th line, define the label again. Determine the name of the application with the app key. You will need that while defining service to the defined value.&lt;br&gt;&lt;br&gt;
Give the image you have sent to the GCR to the image field on the 15th line.&lt;/p&gt;

&lt;p&gt;Now, define the deployment in the Kubernetes cluster.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create -f K8SSampleAPI/deployment.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4EcBqmMi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Kubectl-Deployment-1024x602.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4EcBqmMi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Kubectl-Deployment-1024x602.png" alt=" kubectl create deployment" width="880" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can run the command below from the terminal to see the deployment created.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get deployments --show-labels --namespace development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When deployment is done, three pods will run. You can run the command below to see.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods --show-labels --namespace development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;4.4. Creating the Service&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;In the first part, I mentioned the service. Create a service.yaml file in the project.&lt;/p&gt;

&lt;p&gt;On the 9th line, write the value in the app key that we defined when defining deployment. In this way, the requests coming to service are directed to the pods in the defined deployment. We have mentioned above that three pods will be started in deployment.&lt;br&gt;&lt;br&gt;
On the 12t line, define that the application will be published from the port 1453.&lt;/p&gt;

&lt;p&gt;Now, define the service in the Kubernetes cluster.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create -f K8SSampleAPI/service.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---CajN--l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Kubectl-Service-1024x601.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---CajN--l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Kubectl-Service-1024x601.png" alt="kubectl create service" width="880" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can run the command below from the terminal to see the created service.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get services --show-labels --namespace development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When you run the command, you can see that the External-IP section is in the pending state. It may take up to a minute to assignment IP for the application. When the IP assignment is completed, it means that the application is ready to be published on the port 1453.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZuXaahZd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Kubectl-Service-02-1024x601.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZuXaahZd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Kubectl-Service-02-1024x601.png" alt="kubectl get services" width="880" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8VqFyPTw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Soon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8VqFyPTw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Soon.png" alt="K8SSampleAPI" width="816" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;K8SSampleAPI&lt;/p&gt;

&lt;p&gt;We have specified ApiKey and ApiSecret information in the deployment.yaml. We defined the values as environment variable. We have seen that these variables are successfully accessed within the application.&lt;/p&gt;

&lt;p&gt;I determined the application Id information in the Startup file while the application was starting. Since three applications are started in Deployment, each application has Application Id information according to itself. If you make a request from different browsers, you will see that these three different ApplicationId are returning. In this way, we have seen that the requests are directed to three different pods.&lt;/p&gt;

&lt;p&gt;You can run the following command to delete the cluster. When the cluster is deleted, namespace, deployment, service and pods will be deleted. Remember to update the CLUSTER_ID field according to your information.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud container clusters delete [CLUSTER_ID] --region europe-west1
gcloud container clusters delete my-k8s-api-cluster-1 --region europe-west
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rQUsVsm3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Cluster-Delete-03-1024x600.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rQUsVsm3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/Cluster-Delete-03-1024x600.png" alt="gcloud container clusters delete" width="880" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can access the last version of the project from &lt;a href="https://github.com/ahmetkucukoglu/aspnetcore-k8s-sample"&gt;Github&lt;/a&gt;.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ahmetkucukoglu"&gt;
        ahmetkucukoglu
      &lt;/a&gt; / &lt;a href="https://github.com/ahmetkucukoglu/aspnetcore-k8s-sample"&gt;
        aspnetcore-k8s-sample
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
k8s-sample&lt;/h1&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ahmetkucukoglu/aspnetcore-k8s-sample"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Good luck.&lt;/p&gt;

</description>
      <category>aspnetcore</category>
      <category>dotnet</category>
      <category>gcloud</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Developing AWS Serverless RESTful API</title>
      <dc:creator>Ahmet Küçükoğlu</dc:creator>
      <pubDate>Mon, 27 Jan 2020 06:51:02 +0000</pubDate>
      <link>https://dev.to/ahmetkucukoglu/developing-aws-serverless-restful-api-3ngm</link>
      <guid>https://dev.to/ahmetkucukoglu/developing-aws-serverless-restful-api-3ngm</guid>
      <description>&lt;p&gt;This article was originally published at:  &lt;a href="https://www.ahmetkucukoglu.com/en/developing-aws-serverless-restful-api/"&gt;https://www.ahmetkucukoglu.com/en/developing-aws-serverless-restful-api/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;This article series is about how to develop RestfulAPI with a serverless approach. We will use AWS as a cloud provider.&lt;/p&gt;

&lt;p&gt;In this part, i will show the scenario and give information about what will be the result.&lt;/p&gt;

&lt;p&gt;Our RESTful API endpoints will be like below.&lt;/p&gt;

&lt;p&gt;[POST] api/ads&lt;br&gt;&lt;br&gt;
[PUT] api/ads/{id}&lt;br&gt;&lt;br&gt;
[DELETE] api/ads/{id}&lt;br&gt;&lt;br&gt;
[GET] api/ads&lt;br&gt;&lt;br&gt;
[GET] api/ads/{id}&lt;/p&gt;

&lt;p&gt;We will use the following AWS services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API Gateway :&lt;/strong&gt; It will provide the endpoints we need for the RESTful API.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Lambda :&lt;/strong&gt; It will provide to write function for the GET, POST, PUT and DELETE requests.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;DynamoDB :&lt;/strong&gt; It will provide NoSQL solution. In the POST, PUT and DELETE requests, we will write the data to the DynamoDB.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;ElasticCache :&lt;/strong&gt; It will provide the distributed cache solution. In the GET request, we will read the data from Redis.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;S3 :&lt;/strong&gt; It will provide our code to be versioned and stored after each deployment.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;CloudFormation :&lt;/strong&gt; It will provide us to create and manage automatically all services mentioned above.&lt;/p&gt;

&lt;p&gt;When the project is done, the architecture on AWS will be like below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1GaEhoq3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/06-1024x607.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1GaEhoq3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/06-1024x607.png" alt="Serverless" width="880" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a result, the record will be sent to the DynamoDB which is NoSQL solution of AWS in the POST request. Record changes in our DynamoDB table will be sended on the ElasticCache which is the solution service of the distributed cache of AWS. The data in the GET request will be read from ElasticCache instead of the DynamoDB.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Preparing the Development Environment
&lt;/h2&gt;

&lt;p&gt;In this part, we will arrange our development environment.&lt;/p&gt;

&lt;p&gt;Requirements&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Visual Studio Code&lt;/li&gt;
&lt;li&gt;  AWS Account&lt;/li&gt;
&lt;li&gt;  AWS CLI&lt;/li&gt;
&lt;li&gt;  Serverless Application Framework&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;
  
  
  &lt;strong&gt;2.1. Creating a User in AWS Console&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Creating an authorized user in AWS is required to make deployment with serverless.&lt;/p&gt;

&lt;p&gt;Go to IAM from AWS Console. Choose "User" on the left menu. Click the "Add user" button.&lt;/p&gt;

&lt;p&gt;Write "serverless" in the username fied. Choose "Programmatic Access" from the Access type section. Go to the second step(Permissions).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2cFSMN3_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/07-1024x550.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2cFSMN3_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/07-1024x550.png" alt="Step 1 — User Informations" width="880" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose "Attach existing policies directly" from the Permissions section. Give the following policies. Go to the third step(Tags).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  AWSLambdaFullAccess&lt;/li&gt;
&lt;li&gt;  IAMFullAccess&lt;/li&gt;
&lt;li&gt;  AmazonS3FullAccess&lt;/li&gt;
&lt;li&gt;  CloudWatchLogsFullAccess&lt;/li&gt;
&lt;li&gt;  AmazonAPIGatewayAdministrator&lt;/li&gt;
&lt;li&gt;  AWSCloudFormationFullAccess&lt;/li&gt;
&lt;li&gt;  AmazonDynamoDBFullAccess&lt;/li&gt;
&lt;li&gt;  AmazonElastiCacheFullAccess&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cXAES9BB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/08-1024x550.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cXAES9BB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/08-1024x550.png" alt="Step 2 — User Permissions" width="880" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Write "Application" in the Tag Key field and "Serverless RESTful API" in the Tag Value field. Go to the fourth step(Review).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3a-0daFn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/09-1024x550.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3a-0daFn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/09-1024x550.png" alt="Step 3 — Tagging the User" width="880" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the "Create User" button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aoG3GE1y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/10-1024x576.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aoG3GE1y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/10-1024x576.png" alt="Step 4 — User Review" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the screen, you will see the information about Access Key Id and Secret Access Key. Keep them in a side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1fEtZKFw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/11-1024x550.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1fEtZKFw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/11-1024x550.png" alt="Step 5 — Access Informations of the User" width="880" height="473"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h5&gt;
  
  
  &lt;strong&gt;2.2. The Installation of AWS CLI&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Open Command Prompt and run command line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws configure --profile serverlessuser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;AWS Access Key ID :&lt;/strong&gt; The Access Key Id you will copy&lt;br&gt;&lt;br&gt;
&lt;strong&gt;AWS Secret Access Key :&lt;/strong&gt; The Secret Access Key you will copy&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Default region name :&lt;/strong&gt; eu-central-1&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Default output format :&lt;/strong&gt; json&lt;/p&gt;
&lt;h5&gt;
  
  
  &lt;strong&gt;2.3. The Installation of the Serverless Framework&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;We will use the Serverless Application Framework to develop this application. You can visit the address below for the installation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://s3-us-west-2.amazonaws.com/assets.site.serverless.com/logos/Serverless_mark_black_400x400_v3%402x.jpg"&gt;Serverless Framework - AWS Lambda Guide - Installing The Serverless Framework&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Preparing the Endpoints
&lt;/h2&gt;

&lt;p&gt;In this part, we will create the project and make deployment in a simplest way. We will not send a record to the DynamoDB yet. We will GET response after sending request to the endpoints.&lt;/p&gt;

&lt;p&gt;Create the project folder with the command line below.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir serverless-api &amp;amp;&amp;amp; cd serverless-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create the serverless project with the command line below.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless create --template aws-nodejs --name ads-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Open the project with the command line below via Visual Studio Code.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;code .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Update the serverless.yml file like below.&lt;/p&gt;

&lt;p&gt;serverless.yml v1&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Delete the handler.js file. Create 4 files to be named as "create.js", "update.js", " delete.js" and "getByld.js".&lt;/p&gt;

&lt;p&gt;create.js v1&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;update.js v1&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;delete.js v1&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;getAll.js v1&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;getById.js v1&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Create a file named "create_request.json" in the project folder and paste the json in it. Defines the POST request model. Sets required fields.&lt;/p&gt;

&lt;p&gt;create_request.json&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Create a file named "update_request.json" in the project folder and paste json in it. Defines the PUT request model. Sets required fields.&lt;/p&gt;

&lt;p&gt;update_request.json&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Make deployment to AWS by using the commad line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After the deployment, in a simplest way, lambda functions and the API endpoints to make request functions is created.&lt;/p&gt;

&lt;p&gt;After the deployment process, will write 5 API endpoints and 1 API Key on the console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ccMDcSrv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/12-1024x306.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ccMDcSrv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/12-1024x306.png" alt="Deployment output" width="880" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can see the result by sending request to the endpoints. You need to add "x-api-key" to the Headers and for the value, write API Key showed in the console.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's look at what changed in AWS after the process.&lt;/p&gt;

&lt;p&gt;Stack is created in the &lt;a href="https://eu-central-1.console.aws.amazon.com/cloudformation/home?region=eu-central-1"&gt;Cloud Formation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6DMHijEz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/13-1024x550.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6DMHijEz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/13-1024x550.png" alt="CloudFormation" width="880" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our code is sent to &lt;a href="https://s3.console.aws.amazon.com/s3/home?region=eu-central-1"&gt;S3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--12joDCKh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/14-1024x550.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--12joDCKh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/14-1024x550.png" alt="S3" width="880" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eu-central-1.console.aws.amazon.com/apigateway/home?region=eu-central-1"&gt;API Gateway&lt;/a&gt; is created for the endpoints.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LruRaAOk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/15-1024x550.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LruRaAOk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/15-1024x550.png" alt="API Gateway" width="880" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eu-central-1.console.aws.amazon.com/lambda/home?region=eu-central-1#/functions"&gt;Lambda&lt;/a&gt; functions are created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8L6MQ5----/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/16-1024x549.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8L6MQ5----/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/16-1024x549.png" alt="Lambda" width="880" height="472"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  4. DynamoDB Integration
&lt;/h2&gt;

&lt;p&gt;In this part, we will write the data coming over the API to DynamoDB. We will read the data from DynamoDB.&lt;/p&gt;

&lt;p&gt;Install the required packages by using the command lines below.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i aws-sdk
npm i uuid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Update the serverless.yml file like below.&lt;/p&gt;

&lt;p&gt;serverless.yml v2&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Update the files of create.js, update. js, delete.js, getAll.js and getByld.js like below.&lt;/p&gt;

&lt;p&gt;create.js v2&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;update.js v2&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;delete.js v2&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;getAll.js v2&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;getById.js v2&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Make the second deployment to AWS with the command line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;You can see the result by sending request to the endpoints. You need to add "x-api-key" to the Headers and for the value, write API Key showed in the console.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's look at what changed in AWS after the process.&lt;/p&gt;

&lt;p&gt;A table is created in the &lt;a href="https://eu-central-1.console.aws.amazon.com/dynamodb/home?region=eu-central-1#tables:"&gt;DynamoDB&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vi_W_J6G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/17-1024x550.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vi_W_J6G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/17-1024x550.png" alt="DynamoDB" width="880" height="473"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Redis Integration
&lt;/h2&gt;

&lt;p&gt;In this last chapter, we will transfer the streams in the DynamoDB(adding, udating and deleting) to ElastiCache Redis and do reading from Redis in the GetAll request.&lt;/p&gt;

&lt;p&gt;Install the required packages with the command lines below.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Before starting to make update in the files, you need to learn the subnetlds by entering AWS console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UZJQI5Db--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/18-1024x576.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UZJQI5Db--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/18-1024x576.png" alt="Subnets" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Update the serverless.yml file like below. You need to update the subnetlds parts with your own information.&lt;/p&gt;

&lt;p&gt;serverless.yml v3&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Update the getAll.js file like below.&lt;/p&gt;

&lt;p&gt;getAll.js v3&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Create a new file named trigger.js.&lt;/p&gt;

&lt;p&gt;trigger.js&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Make the third and last deployment to AWS with the command line below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;You can see the result by sending request to the endpoints. You need to add "x-api-key" to the Headers and for the value, write API Key showed in the console.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's look at what changed in AWS after the process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eu-central-1.console.aws.amazon.com/elasticache/home?region=eu-central-1#redis:"&gt;ElasticCache&lt;/a&gt; is created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Oh0uZh3B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/19-1024x576.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Oh0uZh3B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/19-1024x576.png" alt="ElasticCache Redis" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Trigger is assigned to the &lt;a href="https://eu-central-1.console.aws.amazon.com/dynamodb/home?region=eu-central-1#tables:selected=AdsTable;tab=triggers"&gt;DynamoDB&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JNoOzowb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/20-1024x550.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JNoOzowb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ahmetkucukoglu.com/wp-content/uploads/2019/10/20-1024x550.png" alt="DynamoDB Trigger" width="880" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can access the final version of the project from &lt;a href="https://github.com/ahmetkucukoglu/serverless-restful"&gt;Github&lt;/a&gt;.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ahmetkucukoglu"&gt;
        ahmetkucukoglu
      &lt;/a&gt; / &lt;a href="https://github.com/ahmetkucukoglu/serverless-restful"&gt;
        serverless-restful
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Serverless RESTful on AWS
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
serverless-restful&lt;/h1&gt;
&lt;p&gt;Serverless RESTful on AWS&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ahmetkucukoglu/serverless-restful"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Good luck.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>node</category>
      <category>dynamodb</category>
    </item>
  </channel>
</rss>
