<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Firat Tonak]]></title><description><![CDATA[Exploring technology with focus on application security and cloud computing! Real-world solutions, tutorials, and insights across development, security, and clo]]></description><link>https://firattonak.com</link><generator>RSS for Node</generator><lastBuildDate>Tue, 14 Apr 2026 08:41:48 GMT</lastBuildDate><atom:link href="https://firattonak.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Enhancing API Security with Middleware: Filtering and Masking Requests in .NET Core]]></title><description><![CDATA[Middleware is a key part of how modern web apps are built, working as a middle layer that handles requests and responses. In API systems, middleware helps make things safer, work better, and follow rules about protecting data.
One big problem develop...]]></description><link>https://firattonak.com/enhancing-api-security-with-middleware-filtering-and-masking-requests-in-net-core</link><guid isPermaLink="true">https://firattonak.com/enhancing-api-security-with-middleware-filtering-and-masking-requests-in-net-core</guid><category><![CDATA[Request Filtering]]></category><category><![CDATA[Sensitive Data Protection]]></category><category><![CDATA[.net core]]></category><category><![CDATA[Middleware]]></category><category><![CDATA[api security]]></category><category><![CDATA[data masking]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[c programming]]></category><category><![CDATA[RESTful APIs]]></category><category><![CDATA[asp.net core]]></category><dc:creator><![CDATA[Fırat TONAK]]></dc:creator><pubDate>Wed, 15 Jan 2025 15:24:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1736822196864/b46e818e-7145-4c28-8fb0-9c3e6129b681.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Middleware is a key part of how modern web apps are built, working as a middle layer that handles requests and responses. In API systems, middleware helps make things safer, work better, and follow rules about protecting data.</p>
<p>One big problem developers often face is dealing with private information that moves through API requests. Requests not appropriately checked can create weak spots that let bad people see or take private information. To fix this, teams can use middleware to check, clean, and hide private information before it gets to the main program.</p>
<p>This article will show you how to build middleware in .NET Core that makes APIs safer by cleaning and hiding private data. You will learn how to catch and change incoming requests, work with settings that can change, and make things run fast while letting your program grow bigger. After reading this guide, you will know how to make a strong, safe middleware layer for your APIs.</p>
<h3 id="heading-middleware-in-net-core-and-how-it-handles-api-requests"><strong>Middleware in .NET Core and How It Handles API Requests</strong></h3>
<p>Middleware is a key part of the <code>Asp.Net Core</code> system, working as the main piece of how requests and responses flow. In a web app, middleware parts handle HTTP requests as they move through this flow, letting developers add special tasks at different steps. These parts can change requests, add safety checks, save records of what happens, or fix errors, making them very important for building strong APIs.</p>
<p>Middleware works between when a client asks for something and when an API gives an answer. In <code>Asp.Net Core</code>, middleware is a small, separate part that can either work with requests and send them to the next part in the line or stop and make an answer. Middleware is set up in the <code>Program.cs</code> or <code>Startup.cs</code> file, letting developers make a custom and growing request line.</p>
<blockquote>
<p>You need to use <code>Startup.cs</code> if your project is targeting</p>
<ol>
<li><p>Asp.Net Core 1.x</p>
</li>
<li><p>Asp.Net Core 2.x</p>
</li>
<li><p>Asp.Net Core 3.x</p>
</li>
<li><p>.Net 5</p>
</li>
</ol>
<p>You need to use <code>Program.cs</code> if your project is targeting</p>
<ol>
<li><p>.Net 6</p>
</li>
<li><p>.Net 7</p>
</li>
<li><p>.Net 8</p>
</li>
</ol>
</blockquote>
<p>The <code>Asp.Net Core</code> middleware line works with requests one after another, ensuring each middleware part runs in the order it was put in. This setup lets developers make middleware for many uses, including:</p>
<ul>
<li><p>Checking who someone is and what they can do.</p>
</li>
<li><p>Writing down what happens and watching how things work.</p>
</li>
<li><p>Dealing with problems when they happen.</p>
</li>
<li><p>Changing and checking data.</p>
</li>
</ul>
<p>APIs often handle private data, like personal, money, and login details. Showing this information without protection can cause safety problems, like data theft and people getting in who should not. Middleware helps fix this by letting developers filter and hide private data before it gets to the main Program.</p>
<p>Filtering requests means looking at what is in them to find and remove harmful or unwanted parts. Hiding data means replacing private information with fake values so it is not shown during work or record-keeping. Together, these make API work safer and more trustworthy.</p>
<p><strong>Main Things About Middleware for Filtering and Hiding</strong></p>
<p>Using middleware for filtering and hiding requests in .NET Core gives several good things:</p>
<ol>
<li><p><strong>Better Safety</strong>: Middleware can stop private data from being shown in records, answers, or other systems, making data theft less likely.</p>
</li>
<li><p><strong>Following Rules</strong>: Middleware can help APIs follow data protection laws like GDPR or HIPAA by keeping private information safe.</p>
</li>
<li><p><strong>Working Better</strong>: By filtering out wrong or bad requests, middleware makes program errors less likely and makes the whole system work better.</p>
</li>
<li><p><strong>Easy to Change and Grow</strong>: Middleware parts are easy to make, test, and update, letting developers fix new safety needs without significant program changes.</p>
</li>
<li><p><strong>Exact Data Handling</strong>: Middleware ensures private data is handled the same way across all API endpoints, making fewer mistakes and differences.</p>
</li>
</ol>
<p>Before we start making middleware in .NET Core to check and hide parts of API requests, you need to have the right tools and basic understanding. Here's what you need:</p>
<ol>
<li><p>You will need the Visual Studio code</p>
</li>
<li><p>You will need a .NET framework</p>
</li>
<li><p>You will need the postman for testing</p>
</li>
</ol>
<blockquote>
<h4 id="heading-important-note">!! Important Note !!</h4>
<p>If you have all the tools and setup ready, you can skip the installation steps. Go straight to the <strong>Middleware Design and Workflow</strong> section to learn how to make it work and how middleware handles requests and responses.</p>
</blockquote>
<h3 id="heading-setting-up-visual-studio-code">Setting up Visual Studio Code</h3>
<p><code>Visual Studio Code</code> (VS Code) is a small, free code-writing tool made by Microsoft. Many developers use it because it is flexible, fast, and works with many coding languages. VS Code runs well on <code>Windows</code>, <code>macOS</code>, and <code>Linux</code>.</p>
<p>Key features of Visual Studio Code include:</p>
<p><strong>Extensibility:</strong> A considerable store of add-ons for languages, frameworks, and tools.</p>
<p><strong>Built-in Git Integration:</strong> This makes working together and tracking changes easier.</p>
<p><strong>Intelligent Code Editing:</strong> Gives IntelliSense for competent code help, color-coded text, and problem-finding.</p>
<p><strong>Customizability:</strong> This lets you change looks, keyboard shortcuts, and workspace settings to match what you like.</p>
<p>Visual Studio Code is a small editor with strong abilities and has become popular with developers who make different things, from websites to cloud programs.</p>
<p>Type <code>Visual Studio code download</code> into Google and click the first link.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736824930530/1bbb80f8-948e-46e6-adc5-87c43312064c.png" alt class="image--center mx-auto" /></p>
<p>On the next page, you must pick which matches your computer type. I will pick Mac and get it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736825118055/065f2411-4609-4171-96d3-021fd096f1b6.png" alt class="image--center mx-auto" /></p>
<p>You will find the file in your downloads folder when it finishes downloading. You need to open it by clicking on the zip file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736825193308/6342c63a-b0f0-400a-b285-225a5bcd7980.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-setting-up-net-framework">Setting up .Net Framework</h3>
<p>Microsoft's <strong>.NET Framework</strong> is a strong and complete software building system, mainly for creating and running Windows programs. It gives a controlled setting with many valuable tools and libraries, letting developers make different programs, including desktop, web, and server programs.</p>
<p><strong>Key components of the .NET Framework include:</strong></p>
<ol>
<li><p><strong>Common Language Runtime (CLR):</strong> The main engine that controls program running, memory, cleaning unused data, and safety.</p>
</li>
<li><p><strong>Base Class Library (BCL):</strong> A set of ready-to-use tools and libraries for everyday tasks like working with files, databases, and <code>XML</code>.</p>
</li>
<li><p><strong>Language Support:</strong> Works with many coding languages, like <code>C#</code>, <code>VB.NET</code>, and <code>F#</code>, making developers' choices easier.</p>
</li>
</ol>
<p>In 2002, the .NET Framework changed Windows program building by making things like memory control and safety setup easier. Over time, newer systems like <strong>.NET Core</strong> and <strong>.NET 5/6/7/8/9</strong> have come after it, focusing on better speed, growth ability, and support for Windows, macOS, and Linux. Even with these changes, the .NET Framework remains important for keeping old Windows programs working and ensuring older software runs well and stays stable.</p>
<p>Go to <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/core/install/macos"><code>Install .NET on macOS</code></a> Microsoft page and click on <code>Download .Net</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736825664315/2f3c3288-87bd-4a65-be58-37f2508d6a05.png" alt class="image--center mx-auto" /></p>
<p>On the next page, let’s download <code>.NET 8.0 (Long Term Support)</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736825744870/3a6044c3-db63-4796-a380-6545bc8b4e71.png" alt class="image--center mx-auto" /></p>
<p>After selecting <code>.NET 8.0</code>, you must choose an option that matches your computer type. I will pick <code>Arm64</code> because I have an <code>M chip</code>.</p>
<blockquote>
<p>If you have an <code>M chip</code> computer, you should download <code>Arm64</code>; if not, download x64 instead.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736826438884/b83a11b9-b5e5-433c-9503-ab08b719d8ad.png" alt class="image--center mx-auto" /></p>
<p>When the download finishes correctly, you will find the package in your download folder</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736826489760/8dff3d28-cfde-44b8-a25d-ccf20b9c7fcf.png" alt class="image--center mx-auto" /></p>
<p>Now install the .NET framework. Open the package to begin installing and select <code>Continue</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736826565655/2851858c-6aa6-4374-9ebd-af48d361c269.png" alt class="image--center mx-auto" /></p>
<p>On the next screen, you need to select <code>Install</code></p>
<blockquote>
<p>If you want to put it somewhere else, you can select <code>Change Install Location</code>.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736826616481/6ffdaf48-7f7e-4259-b4f0-1310b9a87e2d.png" alt class="image--center mx-auto" /></p>
<p>When the installation finishes appropriately, you will see a screen and can end it by selecting <code>Close</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736826739870/04be4a90-578d-4238-8c38-f955a30166d9.png" alt class="image--center mx-auto" /></p>
<p>If everything works right, we can check the version in the terminal. Open a terminal and type <code>dotnet --version</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736826843015/a12a6f51-5223-4c51-a361-793f5966d63c.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-setting-up-postman">Setting up Postman</h3>
<p><code>Postman</code> is a well-liked API-making and testing tool that makes building, testing, and handling APIs easier. It gives developers a simple way to work with APIs without writing complex code. You can get it as a computer program or use it in a web browser, which works on <code>Windows</code>, <code>macOS</code>, and <code>Linux</code>.</p>
<p>Key features of Postman include:</p>
<p><strong>API Testing</strong> lets users send requests and look at answers in different forms like <code>JSON</code> and <code>XML</code>.</p>
<p><strong>Automation:</strong> Works with JavaScript to write scripts and run tests by itself.</p>
<p><strong>Collaboration:</strong> Let teams share their work, settings, and written guides.</p>
<p><strong>Mock Servers:</strong> Creates fake API endpoints for building and testing.</p>
<p>With its many useful features and simple design, Postman has become an essential tool for making, fixing, and connecting APIs in many different types of work.</p>
<p>When we finish coding, we need to check our work, so we must download Postman. Pick the download option that matches your computer's chip.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736828105133/04e54cc4-a12e-4ece-afc2-308d44be7995.png" alt class="image--center mx-auto" /></p>
<p>Once the download finishes, you will find the zip file in your downloads folder</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736828180315/7c8efd9b-e202-448a-b7b2-28b631ffe174.png" alt class="image--center mx-auto" /></p>
<p>Click the zip file to start <code>Postman</code></p>
<blockquote>
<p>If you get asked <code>Move to Application Folder</code>, go ahead and move it</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736828262685/94de1c8b-b1b8-4a1b-9d8e-4cd07ecba8d6.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>If everything works right, you will see this screen. We will not make an account now, so choose <code>Continue without an account</code> and keep going</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736828377934/26efe9f2-b4b4-4563-84f6-b9f733b4fc21.png" alt class="image--center mx-auto" /></p>
<p>On the next screen, select <code>Open Lightweight API Client</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736828441919/72600637-574d-466a-a8da-560076b837cc.png" alt class="image--center mx-auto" /></p>
<p>If you did each step right, you should now see this form</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736828501040/dbbc2fb3-a93b-455f-ba36-4b3cc85bf3cb.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-middleware-design-and-workflow">Middleware Design and Workflow</h3>
<p>Middleware in .NET Core helps manage API requests, letting developers check and change requests and responses at different points. When making middleware to filter and hide sensitive data, you need to plan what it will do, how it fits in, and how it handles requests.</p>
<p>In <code>ASP.NET Core</code>, middleware pieces work one after another to handle web requests coming in and going out. Middleware does two main things:</p>
<p><strong><em>Intercepting Requests:</em></strong> Middleware grabs and works on requests as they come in. It can change the request, pass it on, or stop it.</p>
<p><strong><em>Processing Responses</em>:</strong> Middleware can also handle responses, letting developers change them before sending them back. Middleware that filters and hides sensitive data mainly focuses on catching and changing requests before they reach the main program. This keeps sensitive info safe as early as possible.</p>
<p>The middleware follows clear steps to handle requests well:</p>
<h4 id="heading-intercepting-requests">Intercepting Requests</h4>
<p>The middleware catches every web request that comes in. At this point:</p>
<ol>
<li><p>The HttpContext object lets you see request details, like headers, query strings, and what is in the request.</p>
</li>
<li><p>The middleware checks if the request has content that needs looking at (like <code>POST</code> or <code>PUT</code> requests with <code>JSON</code> data)</p>
</li>
</ol>
<h4 id="heading-filtering-requests">Filtering Requests</h4>
<p>The middleware looks at the request content for sensitive data. This means:</p>
<ol>
<li><p>Breaking down the request content (like <code>JSON</code>) into a format it can check.</p>
</li>
<li><p>Looking for sensitive info by comparing what is there with a list of words, patterns, or data types.</p>
</li>
</ol>
<h4 id="heading-masking-or-deleting-data"><strong>Masking or Deleting Data</strong></h4>
<p>If it finds sensitive data, the middleware hides it by putting placeholder text (like *****) instead. Alternatively, the middleware can remove the sensitive parts altogether.</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"username"</span>: <span class="hljs-string">"firat"</span>,
  <span class="hljs-attr">"password"</span>: <span class="hljs-string">"verysecret"</span>,
  <span class="hljs-attr">"ssn"</span>: <span class="hljs-string">"123456789"</span>
}
</code></pre>
<p>The above JSON would be modified to</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"username"</span>: <span class="hljs-string">"firat"</span>,
  <span class="hljs-attr">"password"</span>: <span class="hljs-string">"*****"</span>,
  <span class="hljs-attr">"ssn"</span>: <span class="hljs-string">"*****"</span>
}
</code></pre>
<p>After filtering and hiding, the middleware makes a new changed request:</p>
<ol>
<li><p>The updated content is turned back into <code>JSON</code>.</p>
</li>
<li><p>The old request content has been replaced with new content.</p>
</li>
<li><p>The request moves on to the next middleware or handler. This ensures everything downstream gets a clean request, stopping any chance of showing sensitive data by accident.</p>
</li>
</ol>
<h3 id="heading-creating-a-new-aspnet-core-web-api-project">Creating a New ASP.NET Core Web API Project</h3>
<p>We are making an API project with middleware to change <code>requests</code> and <code>responses</code>.</p>
<p>Start by opening a terminal and run <code>dotnet new webapi -n MiddlewareProcess</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736832120441/368cc412-51a6-49bb-af6f-dab383addc49.png" alt class="image--center mx-auto" /></p>
<blockquote>
<ul>
<li><p><code>dotnet new webapi</code> is used to create a <code>Web API</code> project template</p>
<p>  <code>-n &lt;ProjectName&gt;</code> is used to give a name for the project</p>
</li>
</ul>
</blockquote>
<p>Execute <code>code .</code> to open the project in Visual Studio Code</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736832277173/b5d8f5bd-5517-4aa5-835f-1f40650e8870.png" alt class="image--center mx-auto" /></p>
<p>When it is done correctly, you will see several project files</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736832381884/cc1c8186-6e5a-49e2-bcf0-963bad5b0497.png" alt class="image--center mx-auto" /></p>
<p>To test if it works, execute <code>dotnet run</code> and look for the port number your computer shows</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736832670535/bba4d29f-5d67-45df-9fdb-9ee2de5e13bf.png" alt class="image--center mx-auto" /></p>
<p>You can visit <a target="_blank" href="http://localhost:5256/swagger/index.html"><code>http://localhost:5256/swagger/index.html</code></a> in your browser</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736832757670/c342ede6-d010-4c48-9519-6d25830f9ae1.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>In <code>Program.cs</code>, you will find code for a <code>Minimal API</code>. This is something different we might learn later. You can delete it since we will not use <code>Minimal API</code></p>
<pre><code class="lang-csharp">app.MapGet(<span class="hljs-string">"/weatherforecast"</span>, () =&gt;
{
    <span class="hljs-keyword">var</span> forecast =  Enumerable.Range(<span class="hljs-number">1</span>, <span class="hljs-number">5</span>).Select(index =&gt;
        <span class="hljs-keyword">new</span> WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(<span class="hljs-number">-20</span>, <span class="hljs-number">55</span>),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    <span class="hljs-keyword">return</span> forecast;
})
</code></pre>
</blockquote>
<p>First, install the <code>C#</code> extension</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736833259979/f095200f-eebf-4139-89f2-36c1cecbe0ee.png" alt class="image--center mx-auto" /></p>
<p>After installing <code>C#</code>, make a new folder called Controller, then make a new C# file with any name you choose</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736833382222/56c5040b-9c54-40b8-aa7d-717af42240f8.png" alt class="image--center mx-auto" /></p>
<p>Now, implement the <code>API</code> code in your new file</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Microsoft.AspNetCore.Mvc;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">MiddlewareExample.Controllers</span>
{
    [<span class="hljs-meta">ApiController</span>]
    [<span class="hljs-meta">Route(<span class="hljs-meta-string">"api/[controller]"</span>)</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MiddlewareController</span> : <span class="hljs-title">ControllerBase</span>
    {
        [<span class="hljs-meta">HttpGet</span>]
        <span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">GetText</span>(<span class="hljs-params"></span>)</span>
        {
            <span class="hljs-keyword">return</span> Ok(<span class="hljs-string">"test"</span>);
        }
    }
}
</code></pre>
<p><code>[ApiController]</code> indicates that the class is a controller and enables automatic binding and validation.</p>
<p><code>[Route("api/[controller]")]</code> sets the web address to <code>api/middleware</code> (using the controller's name).</p>
<p><code>[HttpGet]</code> specifies that this action method responds to HTTP GET requests.</p>
<p><code>GetText()</code> is what we call this piece of code, which is not part of the web address itself, and it sends back the word <code>test</code> with a message <code>200 OK</code> saying everything worked.</p>
<p><code>return Ok("test");</code> returns the string <code>"test"</code> in an <code>OkObjectResult</code> to indicate a successful response.</p>
<p>You also need to change <code>Program.cs</code> to make your controller work. Go to <code>Program.cs</code> and write <code>builder.Services.AddControllers();</code> and <code>app.MapControllers();</code></p>
<p><code>Program.cs</code> should match what is shown below</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> builder = WebApplication.CreateBuilder(args);

<span class="hljs-comment">// Add services to the container.</span>
<span class="hljs-comment">// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle</span>
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddControllers(); <span class="hljs-comment">// Add this line </span>

<span class="hljs-keyword">var</span> app = builder.Build();

<span class="hljs-comment">// Configure the HTTP request pipeline.</span>
<span class="hljs-keyword">if</span> (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.MapControllers(); <span class="hljs-comment">// add this line</span>

app.Run();
</code></pre>
<p>Execute <code>dotnet run</code> after setting everything up and using <code>Postman</code> to send a request to <a target="_blank" href="http://localhost:%7Byour"><code>http://localhost:{your</code></a> <code>port}/api/middleware</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736915916822/7a9880a1-0260-4e00-bd54-403911b7a9b2.png" alt class="image--center mx-auto" /></p>
<p>Now we know our controller and API work correctly. We need to make a list of words that we want to hide or remove. This list will help us filter content.</p>
<p>Make a new folder called <code>Model</code>, and inside it, make a new C# file called <code>SensitiveData.cs.</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736834438578/74675305-3002-4c74-9b81-15cceb295bb1.png" alt class="image--center mx-auto" /></p>
<p>Write your code precisely like what's shown below</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title">SensitiveData</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> List&lt;<span class="hljs-keyword">string</span>&gt; Keywords = <span class="hljs-keyword">new</span>()
    { 
        <span class="hljs-string">"password"</span>, 
        <span class="hljs-string">"ssn"</span>, 
        <span class="hljs-string">"creditCard"</span>, 
        <span class="hljs-string">"accountnumber"</span>
    };
}
</code></pre>
<p>We use a <code>static</code> class because it holds information everyone shares, and we will not need to start the class.</p>
<p><code>Readonly</code> makes sure the list cannot be changed.</p>
<p>Now, let us make our middleware class. Create a folder called <code>Middleware</code> and put a new C# file called <code>FilteringMiddleware.cs</code> in it</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736834797704/76e47ef0-d42c-433d-89c5-dd63cb922c6a.png" alt class="image--center mx-auto" /></p>
<p>Let us begin writing our middleware class. We will start by adding the namespaces we need</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System.Text.Json;
<span class="hljs-keyword">using</span> System.Text;
</code></pre>
<p><code>System.Text.Json</code> has classes and tools for JSON data. It helps turn JSON data into C# objects we can use.</p>
<p><code>System.Text</code> lets us read and write data streams. We need this to handle data coming into our program.</p>
<p>The next function will be <code>RequestDelegate</code>.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> RequestDelegate _next;
</code></pre>
<p>The line <code>private readonly RequestDelegate _next;</code> is very important because it helps pass web requests to the next part of your <code>ASP.NET Core</code> program.</p>
<blockquote>
<p>In <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core, middleware uses a pattern called <strong>chain of responsibility</strong>. This means each request goes through a line of helpers, and each helper can either work on it or pass it along.</p>
<p><code>RequestDelegate</code> is like a pointer showing which middleware is next in the request line.</p>
</blockquote>
<p>We need two settings to help us hide or remove private information.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">bool</span> _maskSensitiveData;  
<span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">bool</span> _removeSensitiveFields;
</code></pre>
<p>We'll make a starter (constructor) function for our middleware.</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">RequestFilteringMiddleware</span>(<span class="hljs-params">RequestDelegate next, <span class="hljs-keyword">bool</span> maskSensitiveData = <span class="hljs-literal">true</span>, <span class="hljs-keyword">bool</span> removeSensitiveFields = <span class="hljs-literal">false</span></span>)</span>
{
   _next = next;
   _maskSensitiveData = maskSensitiveData;
   _removeSensitiveFields = removeSensitiveFields;
}
</code></pre>
<p>By default, <code>maskSensitiveData</code> will be set to <code>true</code> and <code>removeSensitiveFields</code> will be set to <code>false</code>.</p>
<p><code>RequestFilteringMiddleware</code> starts up (constructor) when we make new middleware. <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core calls it when we add <code>app.UseMiddleware&lt;RequestFilteringMiddleware&gt;()</code> to our program.</p>
<p><code>RequestDelegate next</code> shows what comes next in line. <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core gives us this information when it makes the middleware.</p>
<p><code>_next = next;</code> saves the next step so we can use it later with <code>_next(context)</code>.</p>
<p>Finally, we will make the core part that does the work. This runs every time a web request comes in.</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">InvokeAsync</span>(<span class="hljs-params">HttpContext context</span>)</span>
</code></pre>
<p><code>HttpContext context</code> represents all HTTP-specific information about the current request and response.</p>
<p>We will put our logic work into the <code>InvokeAsync</code> method to clean up or hide data. Here's how it works.</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">InvokeAsync</span>(<span class="hljs-params">HttpContext context</span>)</span>
{
    <span class="hljs-keyword">if</span> (context.Request.Method == HttpMethods.Post)
    {
        context.Request.EnableBuffering(); 

        <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> reader = <span class="hljs-keyword">new</span> StreamReader(context.Request.Body, Encoding.UTF8, leaveOpen: <span class="hljs-literal">true</span>))
        {
            <span class="hljs-keyword">var</span> body = <span class="hljs-keyword">await</span> reader.ReadToEndAsync();
            context.Request.Body.Position = <span class="hljs-number">0</span>; 

            <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">string</span>.IsNullOrWhiteSpace(body))
            {
                <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> jsonDocument = JsonDocument.Parse(body))
                {
                    <span class="hljs-keyword">var</span> rootElement = jsonDocument.RootElement.Clone();
                    <span class="hljs-keyword">var</span> filteredJson = ProcessJsonElement(rootElement);

                    <span class="hljs-keyword">var</span> modifiedBody = JsonSerializer.Serialize(filteredJson);
                    <span class="hljs-keyword">var</span> memoryStream = <span class="hljs-keyword">new</span> MemoryStream(Encoding.UTF8.GetBytes(modifiedBody));
                    context.Request.Body = memoryStream;
                    context.Request.Body.Position = <span class="hljs-number">0</span>; 
                }
            }
        }
    }

    <span class="hljs-keyword">await</span> _next(context);
}
</code></pre>
<p>Let’s look at each step</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">if</span> (context.Request.Method == HttpMethods.Post)
</code></pre>
<p>This part makes sure we only work on <code>POST</code> requests.</p>
<pre><code class="lang-csharp">context.Request.EnableBuffering();
</code></pre>
<p>This step is important because, normally, you can only read a request once in <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core. <code>EnableBuffering()</code> let’s read it many times.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> reader = <span class="hljs-keyword">new</span> StreamReader(context.Request.Body, Encoding.UTF8, leaveOpen: <span class="hljs-literal">true</span>))
{
    <span class="hljs-keyword">var</span> body = <span class="hljs-keyword">await</span> reader.ReadToEndAsync();
    context.Request.Body.Position = <span class="hljs-number">0</span>;
}
</code></pre>
<p><code>StreamReader</code> helps us read the requested data as text.</p>
<p><code>await reader.ReadToEndAsync()</code> gets all the data at once (asynchronously).</p>
<p><code>leaveOpen: true</code> keeps the data available for others to use later.</p>
<p><code>context.Request.Body.Position = 0;</code> goes back to the start so others can read the data, too.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> jsonDocument = JsonDocument.Parse(body))
{
    <span class="hljs-keyword">var</span> rootElement = jsonDocument.RootElement.Clone();
}
</code></pre>
<p><code>JsonDocument.Parse(body)</code> turns the text into a format we can work with.</p>
<p><code>RootElement.Clone()</code> makes a copy we can change.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> filteredJson = ProcessJsonElement(rootElement);
</code></pre>
<p><code>ProcessJsonElement</code> looks through the data and changes sensitive fields based on our rules.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> modifiedBody = JsonSerializer.Serialize(filteredJson);
</code></pre>
<p>It turns our changed data back into text using <code>JsonSerializer.Serialize</code>.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> memoryStream = <span class="hljs-keyword">new</span> MemoryStream(Encoding.UTF8.GetBytes(modifiedBody));
context.Request.Body = memoryStream;
context.Request.Body.Position = <span class="hljs-number">0</span>;
</code></pre>
<p><code>MemoryStream</code> puts our changed data in place of the original.</p>
<p><code>context.Request.Body.Position = 0</code> resets the stream position so endpoints or downstream middleware can read the processed body.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">await</span> _next(context);
</code></pre>
<p>It ensures the request continues to be processed after the middleware has completed its logic.</p>
<p>Now, we will make the <code>ProcessJsonElement</code> function. Here is how it looks.</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">object</span> <span class="hljs-title">ProcessJsonElement</span>(<span class="hljs-params">JsonElement element</span>)</span>
{
    <span class="hljs-keyword">switch</span> (element.ValueKind)
    {
        <span class="hljs-keyword">case</span> JsonValueKind.Object:
            <span class="hljs-keyword">var</span> processedObject = <span class="hljs-keyword">new</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">object</span>&gt;();
            <span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> property <span class="hljs-keyword">in</span> element.EnumerateObject())
            {
                <span class="hljs-keyword">if</span> (SensitiveData.Keywords.Contains(property.Name))
                {
                    <span class="hljs-keyword">if</span> (_maskSensitiveData)
                    {
                        processedObject[property.Name] = <span class="hljs-string">"*****"</span>; <span class="hljs-comment">// Mask the sensitive value</span>
                    }
                    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!_removeSensitiveFields)
                    {
                        processedObject[property.Name] = <span class="hljs-literal">null</span>; <span class="hljs-comment">// Set sensitive value to null</span>
                    }
                }
                <span class="hljs-keyword">else</span>
                {
                    processedObject[property.Name] = ProcessJsonElement(property.Value);
                }
            }
            <span class="hljs-keyword">return</span> processedObject;

        <span class="hljs-keyword">case</span> JsonValueKind.Array:
            <span class="hljs-keyword">var</span> processedArray = <span class="hljs-keyword">new</span> List&lt;<span class="hljs-keyword">object</span>&gt;();
            <span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> item <span class="hljs-keyword">in</span> element.EnumerateArray())
            {
                processedArray.Add(ProcessJsonElement(item));
            }
            <span class="hljs-keyword">return</span> processedArray;

        <span class="hljs-keyword">case</span> JsonValueKind.String:
            <span class="hljs-keyword">return</span> element.GetString();

        <span class="hljs-keyword">case</span> JsonValueKind.Number:
            <span class="hljs-keyword">return</span> element.GetDouble();

        <span class="hljs-keyword">case</span> JsonValueKind.True:
        <span class="hljs-keyword">case</span> JsonValueKind.False:
            <span class="hljs-keyword">return</span> element.GetBoolean();

        <span class="hljs-keyword">case</span> JsonValueKind.Null:
        <span class="hljs-keyword">default</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    }
}
</code></pre>
<p>Let’s investigate our code and understand the steps</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">case</span> JsonValueKind.Object:
    <span class="hljs-keyword">var</span> processedObject = <span class="hljs-keyword">new</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">object</span>&gt;();
    <span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> property <span class="hljs-keyword">in</span> element.EnumerateObject())
    {
        <span class="hljs-keyword">if</span> (SensitiveData.Keywords.Contains(property.Name))
        {
            <span class="hljs-keyword">if</span> (_maskSensitiveData)
            {
                processedObject[property.Name] = <span class="hljs-string">"*****"</span>; 
            }
            <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!_removeSensitiveFields)
            {
                processedObject[property.Name] = <span class="hljs-literal">null</span>; 
            }
        }
        <span class="hljs-keyword">else</span>
        {
            processedObject[property.Name] = ProcessJsonElement(property.Value);
        }
    }
<span class="hljs-keyword">return</span> processedObject;
</code></pre>
<p>JSON can have layers inside layers, so we check every level for sensitive information.</p>
<p><code>Dictionary&lt;string,object&gt;</code> is used to store the processed object.</p>
<p><code>EnumerateObject</code> helps us look at <code>property.Name</code> and <code>property.Value</code></p>
<p><code>SensitiveData.Keywords.Contains(property.Name)</code> checks for sensitive</p>
<ul>
<li><p>Changes values to <code>"*****"</code> if <code>_maskSensitiveData</code> is <code>true</code></p>
</li>
<li><p>Makes values <code>null</code> if <code>_maskSensitiveData</code> is <code>false</code> and <code>_removeSensitiveFields</code> is <code>false</code></p>
</li>
<li><p>Takes out the whole piece if <code>_removeSensitiveFields</code> is <code>true</code></p>
</li>
</ul>
<p><code>return processedObject;</code> gives back the processed data.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">case</span> JsonValueKind.Array:
 <span class="hljs-keyword">var</span> processedArray = <span class="hljs-keyword">new</span> List&lt;<span class="hljs-keyword">object</span>&gt;();
 <span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> item <span class="hljs-keyword">in</span> element.EnumerateArray())
 {
   processedArray.Add(ProcessJsonElement(item));
 }
<span class="hljs-keyword">return</span> processedArray;
</code></pre>
<p>JSON arrays can have nested objects inside, so we check everything.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">case</span> JsonValueKind.String:
<span class="hljs-keyword">return</span> element.GetString();
</code></pre>
<p><code>JsonValueKind.String</code> keeps primitive string values correctly included in the modified JSON without modification.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">case</span> JsonValueKind.Number:
<span class="hljs-keyword">return</span> element.GetDouble();
</code></pre>
<p><code>JsonValueKind.Number</code> keeps numerical values preserved in the modified JSON.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">case</span> JsonValueKind.True:
<span class="hljs-keyword">case</span> JsonValueKind.False:
<span class="hljs-keyword">return</span> element.GetBoolean();
</code></pre>
<p><code>JsonValueKind.True</code> and <code>JsonValueKind.False</code> keep boolean values preserved in the modified JSON.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">case</span> JsonValueKind.Null:
<span class="hljs-keyword">default</span>:
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
</code></pre>
<p><code>JsonValueKind.Null</code> handles empty values correctly.</p>
<p>We're done implementing our middleware. Now add <code>app.UseMiddleware&lt;RequestFilteringMiddleware&gt;(false, true);</code> to <code>Program.cs</code>. Your <code>Program.cs</code> should look like this.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> builder = WebApplication.CreateBuilder(args);

<span class="hljs-comment">// Add services to the container.</span>
<span class="hljs-comment">// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle</span>
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddControllers();

<span class="hljs-keyword">var</span> app = builder.Build();

<span class="hljs-comment">// Configure the HTTP request pipeline.</span>
<span class="hljs-keyword">if</span> (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseMiddleware&lt;RequestFilteringMiddleware&gt;(<span class="hljs-literal">false</span>, <span class="hljs-literal">true</span>);

app.MapControllers();

app.Run();
</code></pre>
<p>One more thing - we need to update our controller to send back what it gets. It should look like this.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Microsoft.AspNetCore.Mvc;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">MiddlewareExample.Controllers</span>
{
    [<span class="hljs-meta">ApiController</span>]
    [<span class="hljs-meta">Route(<span class="hljs-meta-string">"api/[controller]"</span>)</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">RequestController</span> : <span class="hljs-title">ControllerBase</span>
    {
        [<span class="hljs-meta">HttpPost</span>]
        <span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">ReturnResponse</span>(<span class="hljs-params">[FromBody] Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">object</span>&gt; requestData</span>)</span>
        {
            <span class="hljs-keyword">return</span> Ok(<span class="hljs-keyword">new</span>
            {
                Data = requestData
            });
        }
    }
}
</code></pre>
<p>We use <code>Dictionary&lt;string,object&gt;</code> because JSON data is structured as <code>key-value pairs</code></p>
<p>Time to test our work. Here's what to do:</p>
<ol>
<li><p>Run <code>dotnet run</code></p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736915657835/f351e0d4-3217-4fc8-805c-39b70b56797a.png" alt class="image--center mx-auto" /></p>
<p> Use <code>Postman</code> to make a request to <a target="_blank" href="http://localhost:%7Byour">http://localhost:{your</a> port}/api/middleware</p>
</li>
</ol>
<blockquote>
<p>You can set your port in <code>launchSettings.json</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736916835587/95e61751-8b89-465f-94e4-66060df2c295.png" alt class="image--center mx-auto" /></p>
</blockquote>
<ol start="3">
<li>Click <code>Body</code>, pick <code>raw</code> then <code>JSON</code>. Use this test data.</li>
</ol>
<pre><code class="lang-json">{
    <span class="hljs-attr">"data"</span>: {
        <span class="hljs-attr">"user"</span>: {
            <span class="hljs-attr">"name"</span>: {
                <span class="hljs-attr">"first"</span>: <span class="hljs-string">"Firat"</span>,
                <span class="hljs-attr">"last"</span>: <span class="hljs-string">"Tonak"</span>
            },
            <span class="hljs-attr">"email"</span>: <span class="hljs-string">"firattonak.com@firattonak.com"</span>,
            <span class="hljs-attr">"ssn"</span>: <span class="hljs-string">"123-45-6789"</span>
        },
        <span class="hljs-attr">"order"</span>: {
            <span class="hljs-attr">"paymentMethod"</span>: {
                <span class="hljs-attr">"card"</span>: {
                    <span class="hljs-attr">"accountnumber"</span>: <span class="hljs-string">"1111 222 3333 1111"</span>
                }
            }
        }
    }
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736917037454/47871107-93a5-4c5b-8c87-32eaa64f3a0f.png" alt class="image--center mx-auto" /></p>
<p>Let's start testing. First, set <code>maskSensitiveData</code> to true and <code>removeSensitiveData</code> to false in <code>Program.cs</code></p>
<pre><code class="lang-csharp">app.UseMiddleware&lt;RequestFilteringMiddleware&gt;(<span class="hljs-literal">true</span>, <span class="hljs-literal">false</span>);
</code></pre>
<p>After updating <code>Program.cs</code>, run <code>dotnet run</code> and try it. You should see this.</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"data"</span>: {
        <span class="hljs-attr">"data"</span>: {
            <span class="hljs-attr">"user"</span>: {
                <span class="hljs-attr">"name"</span>: {
                    <span class="hljs-attr">"first"</span>: <span class="hljs-string">"Firat"</span>,
                    <span class="hljs-attr">"last"</span>: <span class="hljs-string">"Tonak"</span>
                },
                <span class="hljs-attr">"email"</span>: <span class="hljs-string">"firattonak.com@firattonak.com"</span>,
                <span class="hljs-attr">"ssn"</span>: <span class="hljs-string">"*****"</span>
            },
            <span class="hljs-attr">"order"</span>: {
                <span class="hljs-attr">"paymentMethod"</span>: {
                    <span class="hljs-attr">"card"</span>: {
                        <span class="hljs-attr">"accountnumber"</span>: <span class="hljs-string">"*****"</span>
                    }
                }
            }
        }
    }
}
</code></pre>
<p>See how sensitive information is now masked.</p>
<p>Next, let's try removing sensitive information. Change <code>Program.cs</code> to this.</p>
<pre><code class="lang-csharp">app.UseMiddleware&lt;RequestFilteringMiddleware&gt;(<span class="hljs-literal">false</span>, <span class="hljs-literal">true</span>);
</code></pre>
<p>Send another request, and you should see this.</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"data"</span>: {
        <span class="hljs-attr">"data"</span>: {
            <span class="hljs-attr">"user"</span>: {
                <span class="hljs-attr">"name"</span>: {
                    <span class="hljs-attr">"first"</span>: <span class="hljs-string">"Firat"</span>,
                    <span class="hljs-attr">"last"</span>: <span class="hljs-string">"Tonak"</span>
                },
                <span class="hljs-attr">"email"</span>: <span class="hljs-string">"firattonak.com@firattonak.com"</span>
            },
            <span class="hljs-attr">"order"</span>: {
                <span class="hljs-attr">"paymentMethod"</span>: {
                    <span class="hljs-attr">"card"</span>: {}
                }
            }
        }
    }
}
</code></pre>
<p>Notice how sensitive information is now gone from the response.</p>
<blockquote>
<p>The logic will work no matter how complex your response is.</p>
</blockquote>
<p>Middleware is critical in today's API development, working as the primary system for handling and changing requests before they get to the main app code. When we use middleware to check and hide parts of requests, we fix two big problems in API safety: protecting private information and following data privacy rules like GDPR, HIPAA, and PCI-DSS. This helps developers reduce risks early, making people trust the systems they create.</p>
<p>Middleware for checking and hiding requests is a tool and a foundation for safe and strong API systems. Using this method creates a base for protecting data, following rules, and being reliable. However, it can do even more than that. By making innovative additions like recording hidden request data, adding tools to understand usage, or limiting how many requests can come in to stop misuse, this middleware can grow into a complete answer for what modern APIs need.</p>
<p>APIs are not fixed things; they get bigger, change, and face new problems in our always-changing digital world. Middleware becomes the quiet helper in this process, letting APIs change easily for new needs while staying safe and fast.</p>
<p>In the end, middleware is more than just computer code; it's a way of thinking about change, a promise to keep things safe, and a path to new ideas in API development.</p>
<p>You can access the code <a target="_blank" href="https://github.com/frttnk/Middleware-Request-Filter-Mask">here</a></p>
]]></content:encoded></item><item><title><![CDATA[Easy Steps to Set Up Terraform on Mac]]></title><description><![CDATA[This article will teach you about Terraform and how to install it on macOS. You can start using Terraform once you are done with all the steps.

This guide is created to serve as a reference for future articles, and it focuses on the installation and...]]></description><link>https://firattonak.com/easy-steps-to-set-up-terraform-on-mac</link><guid isPermaLink="true">https://firattonak.com/easy-steps-to-set-up-terraform-on-mac</guid><category><![CDATA[Terraform]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Infrastructure as code]]></category><category><![CDATA[#IaC]]></category><category><![CDATA[aws cli]]></category><category><![CDATA[macOS]]></category><category><![CDATA[Cloud infrastructure]]></category><category><![CDATA[terraform installation]]></category><category><![CDATA[cloudautomation]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Fırat TONAK]]></dc:creator><pubDate>Sat, 04 Jan 2025 14:25:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735873413258/a16dab3d-dbb1-498b-ae4d-6167f058ac29.avif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This article will teach you about Terraform and how to install it on macOS. You can start using Terraform once you are done with all the steps.</p>
<blockquote>
<p>This guide is created to serve as a reference for future articles, and it focuses on the installation and setup.</p>
</blockquote>
<h2 id="heading-what-is-terraform">What is Terraform?</h2>
<p>Terraform is an infrastructure as code (IaC) tool that allows you to manage your resources through code. With Terraform, you can create and modify your infrastructure easily and efficiently.</p>
<p>Terraform provides:</p>
<ol>
<li><p>An infrastructure-as-code approach that helps you create, modify, and delete your resources through code.</p>
</li>
<li><p>Automation of resource creation, modification, and destruction, which reduces direct human interaction with resources and minimizes the risk of human error.</p>
</li>
<li><p>Support for multiple cloud providers.</p>
</li>
<li><p>The ability to collaborate with your team by sharing Terraform files.</p>
</li>
<li><p>State management features that allow you to make and revert changes to your resources easily.</p>
</li>
<li><p>The capability to handle complex and large infrastructures.</p>
</li>
</ol>
<h2 id="heading-installing-terraform">Installing Terraform</h2>
<p>Installing Terraform is a straightforward process that requires you to visit their <a target="_blank" href="https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli">website</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735874356231/eb9feb39-7ba5-470a-8918-a6d778dc4dbc.png" alt class="image--center mx-auto" /></p>
<p>Follow the steps based on your operating system.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735874448332/b81dc401-f7a9-4ab6-bc62-af0f83b3fc5e.png" alt class="image--center mx-auto" /></p>
<p>Since I use macOS, I selected <code>Homebrew on macOS</code>. Open a terminal and execute the command <code>brew tap hashicorp/tap</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735874557201/613d7aa0-8010-4fbb-9f63-df2a626dafba.png" alt class="image--center mx-auto" /></p>
<p>Then execute the command <code>brew install hashicorp/tap/terraform</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735874603488/60b16975-7b99-48e8-b129-53b569a745f9.png" alt class="image--center mx-auto" /></p>
<p>After the installation is complete, run the command <code>brew update</code>, and then finally, execute <code>brew upgrade hashicorp/tap/terraform</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735874970687/aca7fbec-9b74-4a1a-a050-582a62afe9bb.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-testing-terraform">Testing Terraform</h2>
<p>After following all the steps, we should test Terraform to verify it’s working correctly. To do this, execute the command <code>terraform -help</code>. You should see the following output if Terraform is installed on your machine.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735874811944/09bbd18a-4147-4225-b191-9a9e32409e8e.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-configuring-aws-for-terraform">Configuring AWS for Terraform</h2>
<p>We need to make sure that <code>aws cli</code> is installed on our computer before we start managing AWS resources. Let's install the <code>aws cli</code> by executing the command <code>brew install awscli</code>. You should see a similar output at the end of the process.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735875299816/5a4f1ae5-ec86-47f3-8845-6ba7955b2c06.png" alt class="image--center mx-auto" /></p>
<p>Then, let's verify the installation by executing the command <code>aws --version</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735875355845/fa1c97ba-484c-4143-9afe-4253c04de41b.png" alt class="image--center mx-auto" /></p>
<p>Since we can see the version of the <code>aws cli</code>, we can run <code>aws configure</code> to configure AWS credentials. First, go to the AWS Management Console and create an <code>Access Key</code> and <code>Secret Access Key</code>. Search for <code>IAM</code> and select the first result.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735953694208/71808ac6-8047-4d33-a0b5-7b63e092cbad.png" alt class="image--center mx-auto" /></p>
<p>Click on <code>Users</code> and then click on <code>Create User</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735953784507/0c29e0a1-3548-4136-9a1c-3f4a7ac5aeab.png" alt class="image--center mx-auto" /></p>
<p>Enter a <code>User name</code> then click on <code>Next</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735953846662/0c96cd20-dd45-4b70-8504-55fa0761063f.png" alt class="image--center mx-auto" /></p>
<p>On the Set Permissions page, select <code>Attach policies directly</code> and search for <code>AdministratorAccess</code>. Assign it to the user, as we will need admin access to test our Terraform configuration. Then click on <code>Next</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735954070878/176f0ecd-136e-45ee-babf-5f70affcf792.png" alt class="image--center mx-auto" /></p>
<p>Review all the details and click on <code>Create User</code> if everything looks good.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735954167085/baf027ad-25bd-41a8-9339-0278737eccb9.png" alt class="image--center mx-auto" /></p>
<p>If the process is successful, you should see the user in the list.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735954268525/94e82135-922d-495a-9d37-b03fb4a18964.png" alt class="image--center mx-auto" /></p>
<p>Now, we need to create an <code>Access Key</code>. To do this, click on the <code>User Name</code>, select <code>Security Credentials</code>, and then click on <code>Create Access Key</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735954431979/5e68eb2f-da2d-4c55-9595-1c73b77e1122.png" alt class="image--center mx-auto" /></p>
<p>On the next page, select <code>Command Line Interface (CLI)</code> because we want to use the <code>AWS CLI</code>. Check the <code>Confirmation</code> box, then click on <code>Next</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735954621889/634f9330-8905-4904-9d0d-caf60bbdec46.png" alt class="image--center mx-auto" /></p>
<p>You can enter a description if you want, as it is optional, and then click on <code>Create Access Key</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735954671014/227e9661-b5d3-483e-b497-4e17531c60aa.png" alt class="image--center mx-auto" /></p>
<p>On the next page, you will see your <code>Access Key</code> and <code>Secret Access Key</code>. You must save these details because you will not see <code>Secret Access Key</code> again after clicking on <code>Done</code>. You can either download them or save them to a notepad.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735954815498/50b8d0dc-1b47-42a3-92b5-8642fca7d836.png" alt class="image--center mx-auto" /></p>
<p>Now, go back to the terminal and create a folder by executing the command <code>mkdir &lt;folder_name&gt;</code>. Navigate to the folder you just created and run <code>code .</code> to open it in VS Code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735956406538/545964d0-1b65-42ed-81e6-29f9560ea0ed.png" alt class="image--center mx-auto" /></p>
<p>Open a Terminal and execute the command <code>aws configure</code>, then enter your AWS credentials.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735956597361/8906bc8b-e0f8-495d-8f26-ca2fb860358b.png" alt class="image--center mx-auto" /></p>
<p>Let's go to <code>Extensions</code> in VS Code and install the <code>HashiCorp Terraform</code> extension.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735956724980/0401f15c-edf6-4c0f-8467-c07f2fb61ab0.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-testing-terraform-configuration">Testing Terraform Configuration</h2>
<p>Now, we can create a Terraform file and test our configuration to verify it's working. Create a file named <a target="_blank" href="http://main.tf"><code>main.tf</code></a> and copy the following configuration code.</p>
<pre><code class="lang-bash">data <span class="hljs-string">"aws_ami"</span> <span class="hljs-string">"linux"</span>{
    most_recent = <span class="hljs-literal">true</span>

    filter{
        name = <span class="hljs-string">"name"</span>
        values = [<span class="hljs-string">"amzn2-ami-hvm-*-x86_64-gp2"</span>]
    }

    filter{
        name = <span class="hljs-string">"owner-id"</span>
        values = [<span class="hljs-string">"137112412989"</span>] <span class="hljs-comment"># Amazon's official AMI owner ID</span>
    }
}

resource <span class="hljs-string">"aws_instance"</span> <span class="hljs-string">"ecommerce_server"</span> {
  ami           = data.aws_ami.linux.id
  instance_type = <span class="hljs-string">"t2.micro"</span>

    tags = {
    Name = <span class="hljs-string">"Terraform Test"</span>
  }
}
</code></pre>
<p>Next, we need to execute these commands in sequence:</p>
<ol>
<li><p><code>terraform init</code> to initialize the configuration requirements</p>
</li>
<li><p><code>terraform plan</code> to preview what will be created</p>
</li>
<li><p><code>terraform apply -auto-approve</code> to create the EC2 instances</p>
</li>
</ol>
<blockquote>
<p>The <code>-auto-approve</code> flag allows us to skip the approval step after executing <code>terraform apply</code>. Without this flag, you would need to type <code>yes</code> when Terraform asks for approval.</p>
</blockquote>
<p>Go to the AWS Management Console and check the EC2 instance list to verify the deployment.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735957525080/ccf9d27c-b0ac-4e92-9848-dd38ce556f45.png" alt class="image--center mx-auto" /></p>
<p>If you can see <code>Terraform Test</code> in the instance list, it means our configuration is working, and we can use Terraform from now on to create our infrastructure on AWS.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735957607768/572a83b9-7ec3-40e8-b079-3bc05f309ee1.png" alt class="image--center mx-auto" /></p>
<p>We need to run the command <code>terraform destroy -auto-approve</code> to avoid additional costs.</p>
<p>In this article, we covered how to install and configure Terraform on macOS to manage AWS infrastructure. As a result, following these simple steps will help you set up Terraform and start managing AWS resources.</p>
<p>You can access the code <a target="_blank" href="https://github.com/frttnk/Easy-Steps-to-Set-Up-Terraform-on-Mac/tree/main">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Terraform Provisioner: A Beginner's Tutorial]]></title><description><![CDATA[We will examine the provisioner in this article, and you will learn about some common details, such as the file, local-exec, and remote-exec commands and how to use them.
What is a Provisioner?
A provisioner is a mechanism that is used to execute com...]]></description><link>https://firattonak.com/understanding-terraform-provisioner-a-beginners-tutorial</link><guid isPermaLink="true">https://firattonak.com/understanding-terraform-provisioner-a-beginners-tutorial</guid><category><![CDATA[Terraform]]></category><category><![CDATA[provisioner]]></category><category><![CDATA[#Terraform #AWS #InfrastructureAsCode #Provisioning #Automation #CloudComputing]]></category><category><![CDATA[Devops]]></category><category><![CDATA[terraform basics]]></category><category><![CDATA[cloudautomation]]></category><category><![CDATA[#IaC]]></category><category><![CDATA[#HashiCorp #TerraformTips #TerraformTutorial #TerraformBestPractices#DevOpsCommunity#CloudInfrastructure#TerraformModules#TerraformProvider#Automation#InfrastructureAutomation#DevOpsEngineer#TerraformByExample]]></category><category><![CDATA[Infrastructure as code]]></category><category><![CDATA[Infrastructure management]]></category><dc:creator><![CDATA[Fırat TONAK]]></dc:creator><pubDate>Tue, 31 Dec 2024 03:36:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735443171615/ed5ff23d-9c4f-4433-8f00-c42a00021019.avif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We will examine the provisioner in this article, and you will learn about some common details, such as the <code>file</code>, <code>local-exec</code>, and <code>remote-exec</code> commands and how to use them.</p>
<h2 id="heading-what-is-a-provisioner">What is a Provisioner?</h2>
<p>A provisioner is a mechanism that is used to execute commands or scripts on a resource after the resource has been created. It is part of the infrastructure deployment process, allowing you to install the necessary software or apply the required configurations.</p>
<p>There are three types of provisioners:</p>
<ol>
<li><p><strong>File Provisioner</strong>: Used to transfer files or directories from the local machine to a remote resource.</p>
</li>
<li><p><strong>Remote-Exec Provisioner</strong>: Used to execute commands on the remote resource using SSH or WinRM, which is why the remote resource must support SSH or WinRM.</p>
</li>
<li><p><strong>Local-Exec Provisioner</strong>: Used to execute commands on the local machine (the machine running Terraform).</p>
</li>
</ol>
<h3 id="heading-file-provisioner">File Provisioner</h3>
<p>As we mentioned earlier, it is used to transfer files or directories from a local machine to remote resources.</p>
<p>Let's imagine we will create an e-commerce platform and want to host our backend on EC2 in AWS. We will need to define critical details such as database connections, payment gateway configurations, and so on for the backend server.</p>
<p>In this case, we need to use the <code>File Provisioner</code> to upload the configuration file from the local machine to the EC2 server.</p>
<p>We need to create a configuration file named <code>ecommerce.conf</code> and add some details to it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735097952634/373f63ec-0040-4c2f-806b-8eada24edae5.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-plaintext">[database]
host = "database info"
port = 1234
username = firat
password = firat1234
</code></pre>
<p>Our database configuration file is ready, and we can start writing the Terraform configuration code to create EC2 in AWS.</p>
<blockquote>
<p>You can check how to configure <code>AWS CLI</code> if you have not.</p>
</blockquote>
<p>Create a folder and move your configuration file under the folder because we want to keep the configuration file where our <code>main.tf</code> file is.</p>
<p>Now we need to write our EC2 configuration code and get started with fetching the latest Linux AMI. I will use Linux because it will not be charged for the operating system additionally.</p>
<blockquote>
<p>We need a key pair for EC2 creation and connection. Please follow the steps <a target="_blank" href="https://firattonak.com/understanding-and-using-ec2-key-pairs">here</a> before moving forward.</p>
</blockquote>
<p>Here is the <code>data</code> block configuration code.</p>
<pre><code class="lang-json"># Get the latest Amazon Linux <span class="hljs-number">2</span> AMI
data <span class="hljs-string">"aws_ami"</span> <span class="hljs-string">"linux"</span>{
    most_recent = true

    filter{
        name = <span class="hljs-attr">"name"</span>
        values = [<span class="hljs-attr">"amzn2-ami-hvm-*-x86_64-gp2"</span>]
    }

    filter{
        name = <span class="hljs-attr">"owner-id"</span>
        values = [<span class="hljs-attr">"137112412989"</span>] # Amazon's official AMI owner ID
    }
}
</code></pre>
<p>The <code>filter</code> is used to narrow down the results that come from the provider. You do not have to use it. It is optional.</p>
<p><code>name</code> is a key that is used by the filter. For example, the result will be filtered by name. If you want to filter the result by <code>architecture</code>, then you need to create code like that below.</p>
<pre><code class="lang-json">filter{
    name = <span class="hljs-attr">"architecture"</span>
    values = [<span class="hljs-attr">"x86_64"</span>]
}
</code></pre>
<blockquote>
<p>If you want to learn more details about filters, you can visit <a target="_blank" href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami">here</a></p>
</blockquote>
<p>Now, we are able to fetch the latest <code>AMI</code> , and it's time to create our EC2 instance. In this case, we will use the default security group that AWS provides us.</p>
<blockquote>
<p>We need to make sure that our default security group allows SSH (port 22) from our IP address. If it allows <code>All traffic</code>, then you do not have to configure anything. However, keeping your security group as <code>All traffic</code> is not recommended.</p>
</blockquote>
<p>Let's check our security group details first. Go to the EC2 page and hit the <code>Security Groups</code> on the left side.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735310712105/151de873-86ea-4530-b772-60898cbf9649.png" alt class="image--center mx-auto" /></p>
<p>Go to Inbound rules and hit <code>Edit Inbound rules</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735412384909/b5b7f45c-3693-4f63-8db5-00c3f4724318.png" alt class="image--center mx-auto" /></p>
<p>Hit <code>Add rule</code> and add the line like the one below, and then hit <code>Save rules</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735412473313/f3027c8d-d2a2-406b-9aef-829cf73fe448.png" alt class="image--center mx-auto" /></p>
<p>As I mentioned before, if your security group allows all traffic, you do not have to set up SSH. Let’s create an EC2 instance code.</p>
<pre><code class="lang-json">resource <span class="hljs-string">"aws_instance"</span> <span class="hljs-string">"ecommerce_server"</span> {
  ami           = data.aws_ami.linux.id
  instance_type = <span class="hljs-attr">"t2.micro"</span>
  key_name      = <span class="hljs-attr">"ProvisionerKeyPair"</span>

  vpc_security_group_ids = [<span class="hljs-attr">"sg-00138b47ec51588d2"</span>] # the security group that we just created
  associate_public_ip_address = true # SSH does not work without public IP. this line ensures that EC2 gets a public IP.

  provisioner <span class="hljs-attr">"file"</span> {
    source      = <span class="hljs-attr">"ecommerce.conf"</span>
    destination = <span class="hljs-attr">"/home/ec2-user/ecommerce.conf"</span>

    connection {
      type        = <span class="hljs-attr">"ssh"</span>
      user        = <span class="hljs-attr">"ec2-user"</span>
      private_key = file(<span class="hljs-attr">"./ProvisionerKeyPair.pem"</span>)
      host        = self.public_ip
    }
  }

  tags = {
    Name = <span class="hljs-attr">"EcommerceServer"</span>
  }
}
</code></pre>
<p>We need to test our code after creation; that is why we need a public IP. We will use the <code>out</code> keyword to output the public IP.</p>
<pre><code class="lang-json">output <span class="hljs-string">"ec2_instance_public_ip"</span>{
    value = aws_instance.ecommerce_server.public_ip
}
</code></pre>
<p>Our configuration is ready now. We will execute <code>terraform init</code>, <code>terraform plan</code>, and <code>terraform apply</code> commands respectively and create an EC2 instance.</p>
<p>The entire code should be like the one below.</p>
<pre><code class="lang-json">data <span class="hljs-string">"aws_ami"</span> <span class="hljs-string">"linux"</span>{
    most_recent = true

    filter{
        name = <span class="hljs-attr">"name"</span>
        values = [<span class="hljs-attr">"amzn2-ami-hvm-*-x86_64-gp2"</span>]
    }

    filter{
        name = <span class="hljs-attr">"owner-id"</span>
        values = [<span class="hljs-attr">"137112412989"</span>] # Amazon's official AMI owner ID
    }
}

resource <span class="hljs-string">"aws_instance"</span> <span class="hljs-string">"ecommerce_server"</span> {
  ami           = data.aws_ami.linux.id
  instance_type = <span class="hljs-attr">"t2.micro"</span>
  key_name      = <span class="hljs-attr">"ProvisionerKeyPair"</span>

  vpc_security_group_ids = [<span class="hljs-attr">"sg-00138b47ec51588d2"</span>] # the security group that we just created
  associate_public_ip_address = true # SSH does not work without public IP. this line ensures that EC2 gets a public IP.

  provisioner <span class="hljs-attr">"file"</span> {
    source      = <span class="hljs-attr">"ecommerce.conf"</span>
    destination = <span class="hljs-attr">"/home/ec2-user/ecommerce.conf"</span>

    connection {
      type        = <span class="hljs-attr">"ssh"</span>
      user        = <span class="hljs-attr">"ec2-user"</span>
      private_key = file(<span class="hljs-attr">"./ProvisionerKeyPair.pem"</span>)
      host        = self.public_ip
    }
  }

  tags = {
    Name = <span class="hljs-attr">"EcommerceServer"</span>
  }
}

output <span class="hljs-string">"ec2_instance_public_ip"</span>{
    value = aws_instance.ecommerce_server.public_ip
}
</code></pre>
<p>Let's start with the <code>terraform init</code> command. You should see a similar following result when you execute the command.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735414660412/a9c92cd9-8e90-48b3-98c7-46cd6271b9e2.png" alt class="image--center mx-auto" /></p>
<p>Time to execute <code>terraform plan</code> and see what Terraform will create.</p>
<p>If you encounter an error like the one below, you need to give your user proper permissions. I will give <code>AmazonEC2FullAccess</code> in this article for now.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735415442775/c56b44f1-ddf4-46e7-982b-b08aaaa43041.png" alt class="image--center mx-auto" /></p>
<p>After configuring the permission issue, you should see the plan after you execute the <code>terraform plan</code> command. The plan shows all the details about what Terraform will do once you execute <code>terraform apply</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735415523376/d8526b81-7853-434b-aca4-611e113c62b6.png" alt class="image--center mx-auto" /></p>
<p>Let's execute <code>terraform apply</code> and create our EC2 instance and upload the <code>ecommerce.conf</code> file. It will ask you a question like 'Do you want to perform these actions?' when you execute the code, and you need to type <code>yes</code> if you want to move forward.</p>
<blockquote>
<p>Keep in mind that if you want to run <code>terraform apply</code> without any confirmation, you should use the <code>-auto-approve</code> flag.. <a target="_blank" href="https://developer.hashicorp.com/terraform/cli/commands/apply">More details</a></p>
</blockquote>
<p>You should see a similar result once you have finished executing the <code>terraform apply</code> command.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735519926565/413051e5-b77e-4ca8-b440-a47373ad04de.png" alt class="image--center mx-auto" /></p>
<p>We created our server and uploaded the configuration file. However, we should test our infrastructure and see the configuration file on the server.</p>
<p>First, let's check to see if the EC2 instance is created or not. You should see a server named <code>EcommerceServer</code> in the instances list.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735520037383/e3c640cc-310f-4a31-a442-d8a6516b900e.png" alt class="image--center mx-auto" /></p>
<p>If we are good with creating EC2 instances, let's go and check our configuration file. Now, we will try to connect to our EC2 instance. You need to give proper permissions again to your key pair file if you might run into the following error.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735520494553/40efa8b2-3fe4-47cc-bede-4d1a62a9a9c6.png" alt class="image--center mx-auto" /></p>
<p>You need to execute <code>chmod 400</code> and <code>ssh -i ./ProvisionerKeyPair.pem ec2-user@&lt;Your EC2 Public IP&gt;</code> respectively, and then you should see the result below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735520465526/ccafd64e-2b5b-45db-94b7-edc747405b7a.png" alt class="image--center mx-auto" /></p>
<p>You can access your EC2 server and you should check your configuration file by typing the <code>dir</code> command. It will list all files in the directory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735520654712/6bbf7935-f7f5-426b-8834-462794adc9c2.png" alt class="image--center mx-auto" /></p>
<p>Now, let's check if the file is correct or not by checking what is inside. You need to execute the <code>cat</code> command to see the content of the file.</p>
<pre><code class="lang-bash">[ec2-user@ip-172-31-80-65 ~]$ cat ecommerce.conf
[database]
host = <span class="hljs-string">"database info"</span>
port = 1234
username = firat
password = firat1234
</code></pre>
<p>If you are done with checking the details, you can execute the <code>exit</code> command to return to the local machine.</p>
<pre><code class="lang-bash">[ec2-user@ip-172-31-80-65 ~]$ <span class="hljs-built_in">exit</span>
<span class="hljs-built_in">logout</span>
Connection to 3.84.8.181 closed.
</code></pre>
<h3 id="heading-local-exec-provisioner">Local-Exec Provisioner</h3>
<p><code>Local-exec</code> command is used to run commands on the local machine where Terraform is working. It is useful for informing users, running scripts, logging information, and so on during the processes.</p>
<blockquote>
<p>The important point is that you need to write <code>local-exec</code> in the resource definition block.</p>
</blockquote>
<p>The scenario will be the same, and we want to create an EC2 instance on AWS. We will store the public IP of the EC2 instance in a text file after creation is done.</p>
<p>Let's create the resource code and execute <code>terraform plan</code> and <code>terraform apply</code> respectively.</p>
<pre><code class="lang-json">resource <span class="hljs-string">"aws_instance"</span> <span class="hljs-string">"ecommerce_server"</span> {
  ami           = data.aws_ami.linux.id
  instance_type = <span class="hljs-attr">"t2.micro"</span>
  key_name      = <span class="hljs-attr">"ProvisionerKeyPair"</span>

  vpc_security_group_ids = [<span class="hljs-attr">"sg-00138b47ec51588d2"</span>] # the security group that we just created
  associate_public_ip_address = true # SSH does not work without public IP. this line ensures that EC2 gets a public IP.

  provisioner <span class="hljs-attr">"local-exec"</span>{
    command = <span class="hljs-attr">"echo ${self.public_ip} &gt; instance_public_ip.txt"</span>
  }

  tags = {
    Name = <span class="hljs-attr">"EcommerceServer"</span>
  }
}
</code></pre>
<p>As you can see above, the resource code is almost the same. The only differences are that we removed the <code>file</code> provisioner implementation and wrote the local-exec implementation. However, you can implement both <code>file</code> and <code>local-exec</code> provisioners.</p>
<p>The final code should be like the one below.</p>
<pre><code class="lang-json">data <span class="hljs-string">"aws_ami"</span> <span class="hljs-string">"linux"</span>{
    most_recent = true

    filter{
        name = <span class="hljs-attr">"name"</span>
        values = [<span class="hljs-attr">"amzn2-ami-hvm-*-x86_64-gp2"</span>]
    }

    filter{
        name = <span class="hljs-attr">"owner-id"</span>
        values = [<span class="hljs-attr">"137112412989"</span>] # Amazon's official AMI owner ID
    }
}

resource <span class="hljs-string">"aws_instance"</span> <span class="hljs-string">"ecommerce_server"</span> {
  ami           = data.aws_ami.linux.id
  instance_type = <span class="hljs-attr">"t2.micro"</span>
  key_name      = <span class="hljs-attr">"ProvisionerKeyPair"</span>

  vpc_security_group_ids = [<span class="hljs-attr">"sg-00138b47ec51588d2"</span>] # the security group that we just created
  associate_public_ip_address = true # SSH does not work without public IP. this line ensures that EC2 gets a public IP.

  provisioner <span class="hljs-attr">"local-exec"</span>{
    command = <span class="hljs-attr">"echo ${self.public_ip} &gt; instance_public_ip.txt"</span>
  }

  tags = {
    Name = <span class="hljs-attr">"EcommerceServer"</span>
  }
}
</code></pre>
<p>You should see your EC2 instance after you execute the commands. If you see the EC2 instance, you should see the <code>instance_public_ip.txt</code> file in the directory where <a target="_blank" href="http://main.tf">main.tf</a> is located in the <code>local-exec provisioner</code>. You will see the IP address when you check the details of the txt file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735526610815/5b50e89e-1afa-4325-9612-e50eb37dc5e9.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-remote-exec-provisioner">Remote-Exec Provisioner</h3>
<p><code>Remote-exec</code> provisioner is used to execute commands on a remote machine after your infrastructure has been created.</p>
<p>It is used to install software packages, configure services, run setup scripts, and so on.</p>
<blockquote>
<p>You have to specify the connection details such as WinRM for Windows or SSH for Linux instances. Terraform needs connection details to make communication with the remote resource.</p>
</blockquote>
<p>The scenario will be the same, and we want to create an EC2 instance. We will write "Hello from Terraform" into a text file after creation is done.</p>
<p>You can install the Apache server by following the codes, but you may face some additional costs.</p>
<pre><code class="lang-json">sudo yum update -y # it updates the system packages
sudo yum install -y httpd # it installs Apache HTTP Server
sudo systemctl start httpd # it starts the Apache service
sudo systemctl enable httpd # it configures Apache to start on boot
</code></pre>
<p>Let's create a resource code for the <code>EC2</code> instance and execute <code>terraform plan</code> and <code>terraform apply</code> respectively.</p>
<pre><code class="lang-json">resource <span class="hljs-string">"aws_instance"</span> <span class="hljs-string">"ecommerce_server"</span> {
  ami           = data.aws_ami.linux.id
  instance_type = <span class="hljs-attr">"t2.micro"</span>
  key_name      = <span class="hljs-attr">"ProvisionerKeyPair"</span>

  connection {
        type = <span class="hljs-attr">"ssh"</span>
        user = <span class="hljs-attr">"ec2-user"</span>
        private_key = file(<span class="hljs-attr">"./ProvisionerKeyPair.pem"</span>)
        host = self.public_ip
    }

  provisioner <span class="hljs-string">"remote-exec"</span>{
    inline = [ 
        <span class="hljs-attr">"echo 'Hello from Terraform!' &gt; /home/ec2-user/testfile.txt"</span>
     ]
  }

  tags = {
    Name = <span class="hljs-attr">"EcommerceServer"</span>
  }
}
</code></pre>
<p>As you can see, we specify connection details like what we did for the <code>file</code> provisioner earlier and create a text file to store our message.</p>
<p>The final code should be like the one below.</p>
<pre><code class="lang-json">data <span class="hljs-string">"aws_ami"</span> <span class="hljs-string">"linux"</span>{
    most_recent = true

    filter{
        name = <span class="hljs-attr">"name"</span>
        values = [<span class="hljs-attr">"amzn2-ami-hvm-*-x86_64-gp2"</span>]
    }

    filter{
        name = <span class="hljs-attr">"owner-id"</span>
        values = [<span class="hljs-attr">"137112412989"</span>] # Amazon's official AMI owner ID
    }
}

resource <span class="hljs-string">"aws_instance"</span> <span class="hljs-string">"ecommerce_server"</span> {
  ami           = data.aws_ami.linux.id
  instance_type = <span class="hljs-attr">"t2.micro"</span>
  key_name      = <span class="hljs-attr">"ProvisionerKeyPair"</span>

    connection {
        type = <span class="hljs-attr">"ssh"</span>
        user = <span class="hljs-attr">"ec2-user"</span>
        private_key = file(<span class="hljs-attr">"./ProvisionerKeyPair.pem"</span>)
        host = self.public_ip
    }

  provisioner <span class="hljs-string">"remote-exec"</span>{
    inline = [ 
        <span class="hljs-attr">"echo 'Hello from Terraform!' &gt; /home/ec2-user/testfile.txt"</span>
     ]
  }

  tags = {
    Name = <span class="hljs-attr">"EcommerceServer"</span>
  }
}

output <span class="hljs-string">"server_public_IP"</span> {
  value = aws_instance.ecommerce_server.public_ip
}
</code></pre>
<p>You should see the EC2 instance in the list on the AWS management console.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735529896253/b6b2cc4a-f788-4f26-8d23-34700f76fa1c.png" alt class="image--center mx-auto" /></p>
<p>If you execute the following command, you will connect to your EC2 instance that you just created.</p>
<pre><code class="lang-bash">ssh -i ProvisionerKeyPair.pem ec2-user@&lt;Your EC2 Public IP&gt;
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735529993425/f5e8a63c-9a89-4077-9821-cd4a8915631d.png" alt class="image--center mx-auto" /></p>
<p>Let's check to see if our message is stored on the server or not. We need to use the <code>cat</code> command to see the details.</p>
<pre><code class="lang-bash">cat /home/ec2-user/testfile.txt
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735530069531/3333b229-6caf-475d-a19c-1782f95d7d70.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-when-keyword">When Keyword</h3>
<p>The <code>When</code> keyword is used to tell the provisioner when it should run. The keyword is for the <code>local-exec</code> provisioner and <code>remote-exec</code> provisioner. You cannot use it for the <code>file</code> provisioner.</p>
<p>Let's use the keyword and learn how to use it. <code>local-exec</code> will be used for it. You need to add the <code>when</code> keyword in the provisioner and decide when the provisioner should run. I will define <code>when = "destroy"</code> and execute the <code>terraform apply</code> command.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735531655312/a43ac7cc-9d89-4413-b8cf-7542c91e52fe.png" alt class="image--center mx-auto" /></p>
<p>As you can see, the EC2 has been created but there is no text file in the directory. Let's destroy the EC2 using <code>terraform destroy</code> and see if the text file has been created or not.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735531817701/c0594ddd-5f40-4e0c-8b68-5cb2fa436905.png" alt class="image--center mx-auto" /></p>
<p>As you can see above, the text file has been created after the destroy process.</p>
<p>We checked on how to use Provider in Terraform with examples. You can use the details according to your needs or projects. If we summarize what we did:</p>
<ol>
<li><p>If you want to upload a file, you need to use the <code>file</code> provisioner</p>
</li>
<li><p>If you want to execute a command on the local machine where Terraform is working, you need to use the <code>local-exec</code> provisioner</p>
</li>
<li><p>If you want to execute a command on a remote resource after the infrastructure has been created, you need to use the <code>remote-exec</code> provisioner</p>
</li>
</ol>
<p>Since the article is for educational purposes, we should execute the <code>terraform destroy</code> command before we leave to avoid additional costs.</p>
<p>You can access the entire code <a target="_blank" href="https://github.com/frttnk/Understanding-Terraform-Provisioner-A-Beginner-s-Tutorial">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding and Using EC2 Key Pairs]]></title><description><![CDATA[Let's imagine you want to create a virtual server on AWS called an EC2 instance and need a secure way to connect to it. This is where key pairs come in. A key pair acts as a lock and key that ensures you can access only your EC2 instances.
This artic...]]></description><link>https://firattonak.com/understanding-and-using-ec2-key-pairs</link><guid isPermaLink="true">https://firattonak.com/understanding-and-using-ec2-key-pairs</guid><category><![CDATA[AWS Secure Access ]]></category><category><![CDATA[aws ec2]]></category><category><![CDATA[keypair]]></category><category><![CDATA[Cloud Computing]]></category><category><![CDATA[AWS Tutorials ]]></category><category><![CDATA[EC2 Instances]]></category><category><![CDATA[how to create a new keypair on aws]]></category><category><![CDATA[SSH connection to AWS cloud server]]></category><dc:creator><![CDATA[Fırat TONAK]]></dc:creator><pubDate>Tue, 24 Dec 2024 05:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735232410818/47664ee4-a9bd-43d9-8ad0-aaaf311a6763.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let's imagine you want to create a virtual server on AWS called an EC2 instance and need a secure way to connect to it. This is where key pairs come in. A key pair acts as a lock and key that ensures you can access only your EC2 instances.</p>
<p>This article will set up a key pair using the AWS Management Console. Setting up a key pair does not require any coding skills. By the end of this article, you will learn how to create a key pair and how to connect to your EC2 instance.</p>
<blockquote>
<p>Please ensure that you have a valid AWS account before proceeding with this article.</p>
</blockquote>
<p>Go to the AWS Management Console, search for <code>EC2</code>, and select the first option in the results list.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735233548080/5dbb9b9a-a4c4-4b2c-ad36-19a10e24b2d6.png" alt class="image--center mx-auto" /></p>
<p>On this page, select <code>Key Pairs</code> under <code>Network &amp; Security</code>, then click <code>Create key pair</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735233748417/c1948d6c-fcb6-4a13-95e0-0120bd3379fe.png" alt class="image--center mx-auto" /></p>
<p>Now, we will enter details for setting up a key pair.</p>
<p>The <code>Name</code> field is where you enter your key pair name.</p>
<p>There are two different types of key pairs:</p>
<ol>
<li><p>RSA: A cryptographic system that uses public and private keys for secure communication and authentication in systems.</p>
</li>
<li><p>ED25519: A modern public-key cryptography algorithm that offers high performance and security. Its key size is smaller than RSA.</p>
</li>
</ol>
<p>There are two different types of file formats:</p>
<ol>
<li><p>.pem is for <a target="_blank" href="https://en.wikipedia.org/wiki/Secure_Shell">SSH</a></p>
</li>
<li><p>.ppk is for <a target="_blank" href="https://en.wikipedia.org/wiki/PuTTY">PuTTY</a></p>
</li>
</ol>
<p>Enter your details as shown below and click <code>Create key pair.</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735238121427/d2455664-b97d-4bab-a6ed-49b63569a910.png" alt class="image--center mx-auto" /></p>
<p>You should see the key pair in the list, and it will be downloaded automatically.</p>
<blockquote>
<p>Note that you must keep it safe.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735265158262/958bc902-827b-4519-b1e2-4917d879998f.png" alt class="image--center mx-auto" /></p>
<p>Let's create an EC2 instance and verify that our key pair is working.</p>
<p>Go to EC2 on the AWS Management Console, click <code>Instances</code>, and then click <code>Launch instances</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735266248836/b660b86d-492b-4084-8245-7f8cb9429cc0.png" alt class="image--center mx-auto" /></p>
<p>Since we'll use the Free tier in this article, select the <code>t2.micro</code> instance type. Then, select the key pair you just created and click <code>Launch instance</code>.</p>
<blockquote>
<p>We will not cover all EC2 details in this article.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735266894098/f2d6a70f-11e9-40ad-b311-32e5990ab0b6.png" alt class="image--center mx-auto" /></p>
<p>After the process is complete, you should see your EC2 instance on the list.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735266963947/547709a9-b93c-49ce-b2f2-4c5a20847dc1.png" alt class="image--center mx-auto" /></p>
<p>Now, we'll learn how to connect to our EC2 instance using the key pair. Let's open a <code>Terminal</code>.</p>
<p>We must set the correct permissions for our key pair file <code>AWSKeyPair.pem</code> by executing the <code>chmod 400</code> command.</p>
<pre><code class="lang-bash">chmod 400 ~/Downloads/AWSKeyPair.pem
</code></pre>
<p>After setting permissions, we need to get our EC2's public IP. Go to the AWS Management Console and find the <code>Public IPv4 address</code> on the Instances page under Details.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735267818913/c50d3875-e93b-4f7b-9d4e-0100198d2b59.png" alt class="image--center mx-auto" /></p>
<p>Execute the following command using the Public IP.</p>
<pre><code class="lang-bash">ssh -i ~/Downloads/AWSKeyPair.pem ec2-user@54.196.249.211
</code></pre>
<p>After executing the command, you'll receive a connection verification prompt. Type <code>yes</code>, and if successful, you'll see the EC2 console.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735268000898/bd02d841-9f03-432b-950e-be44ba158d7d.png" alt class="image--center mx-auto" /></p>
<p>Following these steps, you can create a key pair and connect to your EC2 instance. A key pair ensures that only you can access the instance, so keep your .pem file secure and never share it. You can now use this knowledge for key pair management and EC2 creation in your projects.</p>
]]></content:encoded></item><item><title><![CDATA[How to Easily Configure AWS CLI with Your Access Key and Secret Key]]></title><description><![CDATA[This article will investigate how to create an Access Key and Secret and how to use aws configure command.

Please ensure that you have a valid AWS account before proceeding with this article.

Go to your AWS Management Console and search for IAM.

C...]]></description><link>https://firattonak.com/step-by-step-guide-to-setting-up-aws-cli-for-terraform-access-and-secret-keys</link><guid isPermaLink="true">https://firattonak.com/step-by-step-guide-to-setting-up-aws-cli-for-terraform-access-and-secret-keys</guid><category><![CDATA[AWS]]></category><category><![CDATA[aws cli]]></category><category><![CDATA[AWS_ACCESS_KEY]]></category><category><![CDATA[Generate AWS Access Key and Secret Key]]></category><category><![CDATA[aws access and secret access key]]></category><dc:creator><![CDATA[Fırat TONAK]]></dc:creator><pubDate>Wed, 11 Dec 2024 05:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735145046215/ed3d6196-4763-417e-ac37-51f37285f31b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This article will investigate how to create an Access Key and Secret and how to use <code>aws configure</code> command.</p>
<blockquote>
<p>Please ensure that you have a valid AWS account before proceeding with this article.</p>
</blockquote>
<p>Go to your AWS Management Console and search for IAM.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735098699310/b8817e31-af25-4580-835d-8b22c45492f9.png" alt class="image--center mx-auto" /></p>
<p>Click on <code>Users</code> in the menu on the left side, then click the <code>Create user</code> button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735098979994/725aa98e-3673-40f4-a364-642be0ea0d0a.png" alt class="image--center mx-auto" /></p>
<p>Enter a <code>user name</code> and click the <code>Next</code> button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735145564245/09e343a5-58b9-42fc-976b-00b78f26c462.png" alt class="image--center mx-auto" /></p>
<p>Click the <code>Next</code> button again</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735100039916/2936a3dc-4574-4c30-abbd-2a24e9cb3a21.png" alt class="image--center mx-auto" /></p>
<p>Create the user by clicking the <code>Create user</code> button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735145700803/2097a6c8-8a76-4e56-87c7-34132dfa6023.png" alt class="image--center mx-auto" /></p>
<p>Then go to the user you just created, select <code>Security credentials</code> from the menu, and click <code>Create access key</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735100445256/3d0580ba-23cc-4ede-94cf-baa69cb85d29.png" alt class="image--center mx-auto" /></p>
<p>Select the following options and click the <code>Next</code> button</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735100548260/3ab0c2b5-ea31-49dc-8831-34bdfe6e9514.png" alt class="image--center mx-auto" /></p>
<p>Enter a description if you want (it's optional), then click <code>Create access key</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735145834318/8bf53c13-2570-4391-a158-f4085ad6777e.png" alt class="image--center mx-auto" /></p>
<p>You now have an Access Key and a Secret Access Key. If you want, you can download them by clicking <code>Download .csv file</code> to save it to your machine.</p>
<blockquote>
<p>Make sure to save the Access Key details somewhere because you will never be able to see the Secret Access Key again after you click the <code>Done</code> button.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735101228165/20167fc0-92f0-412c-b432-a55c2ceca729.png" alt class="image--center mx-auto" /></p>
<p>Now, it's time to configure the AWS CLI in the terminal. Execute the <code>aws configure</code> command and enter the following details.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735101689552/9e7b0e91-609a-43f0-ad40-0482ed945873.png" alt class="image--center mx-auto" /></p>
<p>Now, you're ready to run your Terraform configuration codes for AWS. If you have properly configured the AWS CLI with access keys and secrets, you can integrate your Terraform code with AWS efficiently and securely.</p>
]]></content:encoded></item><item><title><![CDATA[C# Specifiers Explained: What You Need to Know]]></title><description><![CDATA[In this article, we will learn about specifiers and how to use them. They are important for managing your code securely and maintaining a strong structure in terms of architecture and code quality. Additionally, this topic is fundamental for Object-O...]]></description><link>https://firattonak.com/c-specifiers-explained-what-you-need-to-know</link><guid isPermaLink="true">https://firattonak.com/c-specifiers-explained-what-you-need-to-know</guid><category><![CDATA[# csharp  # beginners  # dotnet  # programming]]></category><category><![CDATA[c sharp]]></category><category><![CDATA[coding tips]]></category><category><![CDATA[code security]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[learn c sharp]]></category><category><![CDATA[Coding Best Practices]]></category><dc:creator><![CDATA[Fırat TONAK]]></dc:creator><pubDate>Wed, 04 Dec 2024 17:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735146537406/feea5d72-2e1b-4377-bf75-9b3fa1889784.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, we will learn about specifiers and how to use them. They are important for managing your code securely and maintaining a strong structure in terms of architecture and code quality. Additionally, this topic is fundamental for Object-Oriented Programming (OOP).</p>
<p>We use specifiers to manage the accessibility of our classes and methods. There are four different types of specifiers: <strong><em>public, private, protected, internal,</em></strong> and <strong><em>protected internal.</em></strong></p>
<h2 id="heading-public-specifier">Public Specifier</h2>
<p>The public specifier is accessible at all levels of the project.</p>
<blockquote>
<p>An important point is that the public specifier can also be accessed by other assemblies when your DLL is referenced.</p>
</blockquote>
<p><strong>Product.cs</strong></p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">Specifiers</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Product</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span>? _productName;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span>? ProductName
    {
        <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _productName; }
        <span class="hljs-keyword">set</span> { _productName = <span class="hljs-keyword">value</span>; }
    }
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> <span class="hljs-title">GetProductName</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> ProductName ?? <span class="hljs-string">""</span>;
    }
}
</code></pre>
<p><strong>Program.cs</strong></p>
<pre><code class="lang-csharp">Product newProduct = <span class="hljs-keyword">new</span> Product();
newProduct.ProductName = <span class="hljs-string">"Test Product"</span>;
newProduct.GetProductName();
</code></pre>
<p>As you can see, we can access the public methods and fields anywhere in the project.</p>
<h2 id="heading-private-specifier">Private Specifier</h2>
<p>The private specifier is accessible only within the class where it is defined.</p>
<blockquote>
<p>The private specifier cannot be accessed by other assemblies, even when your DLL is referenced.</p>
</blockquote>
<p><strong>Product.cs</strong></p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">Specifiers</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Product</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span>? _productName;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span>? ProductName
    {
        <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _productName; }
        <span class="hljs-keyword">set</span> { _productName = <span class="hljs-keyword">value</span>; }
    }
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> <span class="hljs-title">GetProductName</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">if</span> (!IsProductAvailable())
        {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Product is not available"</span>;
        }
        <span class="hljs-keyword">return</span> ProductName ?? <span class="hljs-string">""</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">IsProductAvailable</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    }
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735130381356/7daab0ea-bc00-41a1-a77f-141de783a2e0.png" alt /></p>
<p>As you can see, we cannot access the private method in <code>Program.cs</code>. However, we can access the private method in <code>Product.cs</code></p>
<h3 id="heading-protected-specifier">Protected Specifier</h3>
<p>The protected specifier can be accessed within the same class and in derived classes.</p>
<blockquote>
<p>If your derived class is in another assembly, your protected methods are still accessible.</p>
</blockquote>
<p><strong>Product.cs</strong></p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">Specifiers</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Product</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span>? _productName;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span>? ProductName
    {
        <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _productName; }
        <span class="hljs-keyword">set</span> { _productName = <span class="hljs-keyword">value</span>; }
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">decimal</span>? _productPrice;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">decimal</span>? ProductPrice
    {
        <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _productPrice; }
        <span class="hljs-keyword">set</span> { _productPrice = <span class="hljs-keyword">value</span>; }
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">bool</span>? _productStatus;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span>? ProductStatus
    {
        <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _productStatus; }
        <span class="hljs-keyword">set</span> { _productStatus = <span class="hljs-keyword">value</span>; }
    }
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> <span class="hljs-title">GetProductName</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">if</span> (!CheckProductIsAvailable())
        {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Product is not available"</span>;
        }
        <span class="hljs-keyword">return</span> ProductName ?? <span class="hljs-string">""</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">IsProductAvailable</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    }

    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">bool</span>? GetProductStatus()
    {
        <span class="hljs-keyword">return</span> _productStatus;
    }
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735130382965/ad679dba-188c-4a97-bad1-f754c63a1c0b.png" alt /></p>
<p>As you can see, we cannot access the <code>GetProductStatus</code> method in the <code>Program.cs</code> file.</p>
<p>However, when I make the <code>Product.cs</code> class abstract, we can access the protected methods in the derived class.</p>
<p><strong>Product.cs</strong></p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">Specifiers</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Product</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span>? _productName;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span>? ProductName
    {
        <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _productName; }
        <span class="hljs-keyword">set</span> { _productName = <span class="hljs-keyword">value</span>; }
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">decimal</span>? _productPrice;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">decimal</span>? ProductPrice
    {
        <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _productPrice; }
        <span class="hljs-keyword">set</span> { _productPrice = <span class="hljs-keyword">value</span>; }
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">bool</span>? _productStatus;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span>? ProductStatus
    {
        <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _productStatus; }
        <span class="hljs-keyword">set</span> { _productStatus = <span class="hljs-keyword">value</span>; }
    }
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> <span class="hljs-title">GetProductName</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">if</span> (!IsProductAvailable())
        {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Product is not available"</span>;
        }
        <span class="hljs-keyword">return</span> ProductName ?? <span class="hljs-string">""</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">IsProductAvailable</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    }

    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">virtual</span> <span class="hljs-keyword">bool</span>? GetProductStatus()
    {
        <span class="hljs-keyword">return</span> _productStatus;
    }
}
</code></pre>
<p><strong>Computer.cs</strong></p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">Specifiers</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Computer</span> : <span class="hljs-title">Product</span>
{
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">bool</span>? GetProductStatus()
    {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">base</span>.GetProductStatus();
    }
}
</code></pre>
<h3 id="heading-internal-specifier">Internal Specifier</h3>
<p>The internal specifier can be accessed anywhere within the project.</p>
<blockquote>
<p>The internal specifier cannot be accessed by other assemblies, even when your DLL is referenced.</p>
</blockquote>
<p><strong>Product.cs</strong></p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">Specifiers</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Product</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span>? _productName;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span>? ProductName
    {
        <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _productName; }
        <span class="hljs-keyword">set</span> { _productName = <span class="hljs-keyword">value</span>; }
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">decimal</span>? _productPrice;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">decimal</span>? ProductPrice
    {
        <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _productPrice; }
        <span class="hljs-keyword">set</span> { _productPrice = <span class="hljs-keyword">value</span>; }
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">bool</span>? _productStatus;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span>? ProductStatus
    {
        <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _productStatus; }
        <span class="hljs-keyword">set</span> { _productStatus = <span class="hljs-keyword">value</span>; }
    }
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> <span class="hljs-title">GetProductName</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">if</span> (!IsProductAvailable())
        {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Product is not available"</span>;
        }
        <span class="hljs-keyword">return</span> ProductName ?? <span class="hljs-string">""</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">IsProductAvailable</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    }

    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">virtual</span> <span class="hljs-keyword">bool</span>? GetProductStatus()
    {
        <span class="hljs-keyword">return</span> _productStatus;
    }

    <span class="hljs-keyword">internal</span> <span class="hljs-keyword">decimal</span>? GetProductPrice()
    {
        <span class="hljs-keyword">return</span> ProductPrice ?? <span class="hljs-number">0</span>;
    }

}
</code></pre>
<p><strong>Program.cs</strong></p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Specifiers;

Product computer = <span class="hljs-keyword">new</span> Computer();
computer.ProductPrice = <span class="hljs-number">150</span>;
computer.GetProductPrice();
</code></pre>
<h3 id="heading-protectedinternal-specifier">ProtectedInternal Specifier</h3>
<p>The protectedInternal specifier is accessible at all levels within the project, as well as by other assemblies when your DLL is referenced.</p>
<blockquote>
<p>If your derived class is in another assembly, your <code>protectedInternal</code> methods are accessible.</p>
</blockquote>
<p>I have tried to explain the different types of specifiers in C# and why they are needed.</p>
<blockquote>
<p>I did not include an example of the <code>protectedInternal</code> specifier because it is very similar to the <code>public</code> specifier. The only difference is that while the <code>public</code> specifier is accessible everywhere, including in other assemblies and external code, the <code>protectedInternal</code> specifier cannot be accessed by external code in other assemblies."</p>
</blockquote>
<p>You can reach the code <a target="_blank" href="https://github.com/frttnk/C-Specifiers-Explained-What-You-Need-to-Know">here</a></p>
]]></content:encoded></item><item><title><![CDATA[How to Implement Global Exception Handling in ASP.NET Core Middleware]]></title><description><![CDATA[In this article, we will delve into the process of implementing global exception handling in ASP.NET Core middleware. By handling exceptions globally, we can streamline error management and enhance the robustness of our applications. We will explore ...]]></description><link>https://firattonak.com/how-to-implement-global-exception-handling-in-aspnet-core-middleware</link><guid isPermaLink="true">https://firattonak.com/how-to-implement-global-exception-handling-in-aspnet-core-middleware</guid><category><![CDATA[C# Application Stability]]></category><category><![CDATA[C# Best Practices]]></category><category><![CDATA[Aspnetcore]]></category><category><![CDATA[exceptionhandling]]></category><category><![CDATA[Middleware]]></category><category><![CDATA[error handling]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[networking]]></category><category><![CDATA[API development ]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[C#]]></category><dc:creator><![CDATA[Fırat TONAK]]></dc:creator><pubDate>Tue, 03 Dec 2024 17:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735134884956/c9ed6fd6-448a-4e92-a3c6-be4c864bcb6d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, we will delve into the process of implementing global exception handling in <strong><em>ASP.NET Core</em></strong> middleware. By handling exceptions globally, we can streamline error management and enhance the robustness of our applications. We will explore common exceptions, demonstrate how to throw them when errors occur and catch these exceptions using a try-catch block within the middleware.</p>
<blockquote>
<p>You can find more details about try-catch block <a target="_blank" href="https://firattonak.com/c-sharp-net-core-web-development-exploring-error-handling-with-try-catch-finally-blocks"><strong>here</strong></a></p>
</blockquote>
<p>I assume that you have already created a Web API project for implementation. If so, your project structure should look as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735130333915/9d1dfece-00d6-43a0-ac96-bfc20af8d123.png" alt class="image--center mx-auto" /></p>
<p>Let’s create a folder named <code>Exceptions</code> where we will develop custom exception classes. These classes will inherit from the <code>Exception</code> class.</p>
<p>The first one will be <code>BadRequestException</code>, which will inherit from the <code>Exception</code> class in the System namespace.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">ExceptionHandlingInMiddleware.Exceptions</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">BadRequestException</span> : <span class="hljs-title">Exception</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">BadRequestException</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> message</span>) : <span class="hljs-title">base</span>(<span class="hljs-params">message</span>)</span>
    {

    }
}
</code></pre>
<p>The second one will be <code>NotFoundException</code></p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">ExceptionHandlingInMiddleware.Exceptions</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">NotFoundException</span> : <span class="hljs-title">Exception</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">NotFoundException</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> message</span>):<span class="hljs-title">base</span>(<span class="hljs-params">message</span>)</span>
    {

    }
}
</code></pre>
<p>The third one will be <code>NotImplementedException</code></p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">ExceptionHandlingInMiddleware.Exceptions</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">NotImplementedException</span> : <span class="hljs-title">Exception</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">NotImplementedException</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> message</span>) : <span class="hljs-title">base</span>(<span class="hljs-params">message</span>)</span>
    {

    }
}
</code></pre>
<p>The last one will be <code>UnauthorizedException</code></p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">ExceptionHandlingInMiddleware.Exceptions</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">UnauthorizedException</span>:<span class="hljs-title">Exception</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UnauthorizedException</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> message</span>):<span class="hljs-title">base</span>(<span class="hljs-params">message</span>)</span>
    {

    }
}
</code></pre>
<p>Now that we have finished creating the custom exception classes, you can still create additional custom exception classes if needed.</p>
<p>After creating all the classes, your structure should look as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735130334953/1d4af269-89d6-4bc5-b69c-78ef58857046.png" alt /></p>
<p>Now, we need to integrate our exceptions into middleware. To do this, we will create a folder named <code>Configurations</code>, where we will implement our middleware and utilize it in the <code>Program.cs</code> file.</p>
<p>After creating the folder, we will create a middleware class named <code>ExceptionMiddlewareConfiguration</code> and begin implementing it.</p>
<p>First, we will add a request delegate to intercept the request pipeline. For more details about the request pipeline, refer to the following:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">ExceptionHandlingInMiddleware.Configurations</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ExceptionMiddlewareConfiguration</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> RequestDelegate _next;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ExceptionMiddlewareConfiguration</span>(<span class="hljs-params">RequestDelegate next</span>)</span>
    {
    _next = next;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">Invoke</span>(<span class="hljs-params">HttpContext context</span>)</span>
    {
        <span class="hljs-keyword">try</span>
        {
            <span class="hljs-keyword">await</span> _next(context);
        }
        <span class="hljs-keyword">catch</span> (Exception excp)
        {
        <span class="hljs-comment">// we will implement exceptions here</span>
        }
    }

}
</code></pre>
<p>Next, we need to check the type of exception being passed and determine the appropriate status code to return.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> ExceptionHandlingInMiddleware.Exceptions;
<span class="hljs-keyword">using</span> System.Net;
<span class="hljs-keyword">using</span> System.Text.Json;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">ExceptionHandlingInMiddleware.Configurations</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ExceptionMiddlewareConfiguration</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> RequestDelegate _next;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ExceptionMiddlewareConfiguration</span>(<span class="hljs-params">RequestDelegate next</span>)</span>
    {
        _next = next;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">Invoke</span>(<span class="hljs-params">HttpContext context</span>)</span>
    {
        <span class="hljs-keyword">try</span>
        {
            <span class="hljs-keyword">await</span> _next(context);
        }
        <span class="hljs-keyword">catch</span> (Exception excp)
        {
            <span class="hljs-keyword">await</span> ExceptionAsync(context, excp);
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Task <span class="hljs-title">ExceptionAsync</span>(<span class="hljs-params">HttpContext context, Exception ex</span>)</span>
    {
    <span class="hljs-comment">// Here, the HTTP codes will be determined based on exceptions</span>
        HttpStatusCode statusCode;
        <span class="hljs-keyword">string</span> message = <span class="hljs-string">"Unexpected error"</span>;

        <span class="hljs-comment">// We need to identify the type of the exception</span>
        <span class="hljs-keyword">var</span> excpType = ex.GetType();

        <span class="hljs-comment">// Let's check what kind of exceptions are passed</span>
        <span class="hljs-keyword">if</span> (excpType == <span class="hljs-keyword">typeof</span>(BadRequestException))
        {
            statusCode = HttpStatusCode.BadRequest;
            message = ex.Message;
        }
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (excpType == <span class="hljs-keyword">typeof</span>(NotFoundException))
        {
            statusCode = HttpStatusCode.NotFound;
            message = ex.Message;
        }
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (excpType == <span class="hljs-keyword">typeof</span>(Exceptions.NotImplementedException))
        {
            statusCode = HttpStatusCode.NotImplemented;
            message = ex.Message;
        }
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (excpType == <span class="hljs-keyword">typeof</span>(UnauthorizedException))
        {
            statusCode = HttpStatusCode.Unauthorized;
            message = ex.Message;
        }
        <span class="hljs-keyword">else</span>
        {
            statusCode = HttpStatusCode.InternalServerError;
            message = ex.Message;
        }

        <span class="hljs-keyword">var</span> result = JsonSerializer.Serialize(<span class="hljs-keyword">new</span> { message = message });
        context.Response.ContentType = <span class="hljs-string">"application/json"</span>;
        context.Response.StatusCode = (<span class="hljs-keyword">int</span>)statusCode;

        <span class="hljs-keyword">return</span> context.Response.WriteAsync(result);

    }
}
</code></pre>
<p>As shown above, we can check the type of exception and return the appropriate status code.</p>
<p>Now, we need to inject our middleware class into the <code>Program.cs</code> file.</p>
<p>To do this, let’s create a static class named <code>ApplicationBuilderConfiguration</code> under the <code>Configurations</code> folder.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">ExceptionHandlingInMiddleware.Configurations</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ApplicationBuilderConfiguration</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> IApplicationBuilder <span class="hljs-title">ErrorHandler</span>(<span class="hljs-params"><span class="hljs-keyword">this</span> IApplicationBuilder applicationBuilder</span>)</span> =&gt; applicationBuilder.UseMiddleware();
}
</code></pre>
<p>Next, we need to call the <code>ApplicationBuilderConfiguration</code> static class after <code>Add.MapController()</code> in the <code>Program.cs</code> file.using ExceptionHandlingInMiddleware.Configurations;</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> builder = WebApplication.CreateBuilder(args);

<span class="hljs-comment">// Add services to the container</span>

builder.Services.AddControllers();
<span class="hljs-comment">// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle</span>
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

<span class="hljs-keyword">var</span> app = builder.Build();

<span class="hljs-comment">// Configure the HTTP request pipeline.</span>
<span class="hljs-keyword">if</span> (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.ErrorHandler();

app.Run();
</code></pre>
<p>Now, it’s time to test our exception handling implementation. Let’s create a controller called <code>TestController</code> and implement an <code>HttpGet</code> API.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> ExceptionHandlingInMiddleware.Exceptions;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Mvc;
<span class="hljs-keyword">using</span> NotImplementedException = ExceptionHandlingInMiddleware.Exceptions.NotImplementedException;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">ExceptionHandlingInMiddleware.Controllers</span>
{
    [<span class="hljs-meta">Route(<span class="hljs-meta-string">"api/[controller]"</span>)</span>]
    [<span class="hljs-meta">ApiController</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TestController</span> : <span class="hljs-title">ControllerBase</span>
    {
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">TestController</span>(<span class="hljs-params"></span>)</span>
        {

        }
        [<span class="hljs-meta">HttpGet</span>]
        [<span class="hljs-meta">Route(<span class="hljs-meta-string">"TestExceptions"</span>)</span>]
        <span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">TestExceptions</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> number</span>)</span>
        {
            CheckTheNumber(number);
            <span class="hljs-keyword">return</span> Ok();
        }

        <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CheckTheNumber</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> number</span>)</span>
        {
            <span class="hljs-keyword">if</span> (number == <span class="hljs-number">1</span>)
            {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> BadRequestException(<span class="hljs-string">"Number = 1 is the bad request exception"</span>);
            }
            <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (number == <span class="hljs-number">2</span>)
            {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> NotFoundException(<span class="hljs-string">"Number = 2 is the Not found exception"</span>);
            }
            <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (number == <span class="hljs-number">3</span>)
            {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> NotImplementedException(<span class="hljs-string">"Number = 3 is the Not implemented exception"</span>);
            }
            <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (number == <span class="hljs-number">4</span>)
            {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnauthorizedException(<span class="hljs-string">"Number = 4 is the unauthorized exception"</span>);
            }
        }

    }
}
</code></pre>
<p>As you can see below, the exceptions are working as expected.</p>
<p>When the number is 1</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735130336065/cefdd7e4-4a7c-4404-888d-466121cb6eec.png" alt /></p>
<p>When the number is 2</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735130337250/1b0c48b8-ca31-4f55-879c-886c5dcf91b9.png" alt /></p>
<p>When the number is 3</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735130338716/f373ef85-aa8d-4b5e-a579-61e85cd38a72.png" alt /></p>
<p>When the number is 4</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735130340093/5eb73e65-11f3-4fb3-a73e-945c9b8e8627.png" alt /></p>
<p>Additionally, you can implement a default response type to inform consumers of the API.</p>
<p>Simply use <code>ProducesResponseType</code> to define the response type for a controller, as shown below:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> ExceptionHandlingInMiddleware.Exceptions;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Mvc;
<span class="hljs-keyword">using</span> NotImplementedException = ExceptionHandlingInMiddleware.Exceptions.NotImplementedException;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">ExceptionHandlingInMiddleware.Controllers</span>
{
    [<span class="hljs-meta">Route(<span class="hljs-meta-string">"api/[controller]"</span>)</span>]
    [<span class="hljs-meta">ApiController</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TestController</span> : <span class="hljs-title">ControllerBase</span>
    {
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">TestController</span>(<span class="hljs-params"></span>)</span>
        {

        }
        [<span class="hljs-meta">HttpGet</span>]
        [<span class="hljs-meta">Route(<span class="hljs-meta-string">"TestExceptions"</span>)</span>]
        [<span class="hljs-meta">ProducesResponseType(StatusCodes.Status200OK)</span>]
        [<span class="hljs-meta">ProducesResponseType(StatusCodes.Status400BadRequest)</span>]
        [<span class="hljs-meta">ProducesResponseType(StatusCodes.Status404NotFound)</span>]
        [<span class="hljs-meta">ProducesResponseType(StatusCodes.Status501NotImplemented)</span>]
        [<span class="hljs-meta">ProducesResponseType(StatusCodes.Status401Unauthorized)</span>]
        <span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">TestExceptions</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> number</span>)</span>
        {
            CheckTheNumber(number);
            <span class="hljs-keyword">return</span> Ok();
        }

        <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CheckTheNumber</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> number</span>)</span>
        {
            <span class="hljs-keyword">if</span> (number == <span class="hljs-number">1</span>)
            {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> BadRequestException(<span class="hljs-string">"Number = 1 is the bad request exception"</span>);
            }
            <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (number == <span class="hljs-number">2</span>)
            {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> NotFoundException(<span class="hljs-string">"Number = 2 is the Not found exception"</span>);
            }
            <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (number == <span class="hljs-number">3</span>)
            {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> NotImplementedException(<span class="hljs-string">"Number = 3 is the Not implemented exception"</span>);
            }
            <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (number == <span class="hljs-number">4</span>)
            {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnauthorizedException(<span class="hljs-string">"Number = 4 is the unauthorized exception"</span>);
            }
        }
    }
}
</code></pre>
<p>This way, users can understand what kind of response type they might expect from the API.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735130341384/e03f5def-0e70-4c5b-8fe0-894c8a09d3f5.png" alt /></p>
<p>Note that if you want to pass an object through a custom exception model, you need to change the parameter type from <code>string</code> to <code>object</code>. This will allow you to pass your model as the response type.</p>
<p>You can check the code below:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">ExceptionHandlingInMiddleware.Exceptions</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">BadRequestException</span> : <span class="hljs-title">Exception</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">BadRequestException</span>(<span class="hljs-params"><span class="hljs-keyword">object</span> message</span>) : <span class="hljs-title">base</span>(<span class="hljs-params">message.ToString(</span>))</span>
    {

    }
}
</code></pre>
<p>In conclusion, implementing global exception handling in <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core middleware is a crucial step in enhancing the robustness and reliability of your applications. By creating custom exception classes and integrating them into middleware, you can efficiently manage errors and provide clear, consistent responses to API consumers.</p>
<p>This approach not only simplifies error handling but also improves the overall user experience by ensuring that exceptions are handled gracefully and appropriately. As demonstrated, the process is straightforward and can be tailored to meet specific application needs, allowing for scalable and maintainable error management solutions.</p>
<p>You can refer to the code <a target="_blank" href="https://github.com/frttnk/Exception-Handling-in-Middleware">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[C# Error Handling Made Easy with Try-Catch-Finally Blocks]]></title><description><![CDATA[In this concise article, we delve into the topic of handling exceptions in C#. To effectively manage exceptions, we utilize the try-catch-finally block. Here’s a breakdown of its components:

Try block: Any errors that occur within the try block trig...]]></description><link>https://firattonak.com/c-sharp-net-core-web-development-exploring-error-handling-with-try-catch-finally-blocks</link><guid isPermaLink="true">https://firattonak.com/c-sharp-net-core-web-development-exploring-error-handling-with-try-catch-finally-blocks</guid><category><![CDATA[Error Handling in C#]]></category><category><![CDATA[exception management]]></category><category><![CDATA[Application Stability]]></category><category><![CDATA[C# Tips]]></category><category><![CDATA[C#]]></category><category><![CDATA[error handling]]></category><category><![CDATA[try-catch-finally]]></category><category><![CDATA[#ProgrammingBestPractices]]></category><category><![CDATA[software development]]></category><category><![CDATA[debugging]]></category><dc:creator><![CDATA[Fırat TONAK]]></dc:creator><pubDate>Fri, 08 Nov 2024 17:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735133154775/b322ce9e-df7b-4d0c-a786-eeffad536aa0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this concise article, we delve into the topic of handling exceptions in C#. To effectively manage exceptions, we utilize the try-catch-finally block. Here’s a breakdown of its components:</p>
<ul>
<li><p><strong>Try block</strong>: Any errors that occur within the try block trigger a transfer of control to the catch block.</p>
</li>
<li><p><strong>Catch block</strong>: In the catch block, we define the logic for handling errors, which may include returning error messages or logging.</p>
</li>
<li><p><strong>Finally block</strong>: The code in the finally block is executed regardless of whether an exception occurs, making it the ideal place to implement finalization logic.</p>
</li>
</ul>
<pre><code class="lang-csharp"><span class="hljs-keyword">try</span>
{
    <span class="hljs-keyword">int</span> first = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">int</span> second = <span class="hljs-number">0</span>;

    <span class="hljs-keyword">int</span> result = first / second;
}
<span class="hljs-keyword">catch</span> (Exception excp)
{
    Console.WriteLine(<span class="hljs-string">"Divide by zero error :\n"</span>+excp.ToString());
}
<span class="hljs-keyword">finally</span>
{
    Console.WriteLine(<span class="hljs-string">"\nWe got an error and need to change the logic here"</span>);
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735130293011/bc23c963-e4dd-4013-aafa-9c77f91fef71.png" alt /></p>
<p>Indeed, as evident from the preceding explanation, when an error occurs, the try block directs the code flow to the catch block, which in turn directs it to the finally block.</p>
<blockquote>
<p>One common source of confusion in exception handling is whether it’s possible to use multiple catch blocks. The answer is affirmative; you can have multiple catch blocks, but only one of them will be executed, depending on the type of exception that matches the error encountered.</p>
<p>Another area of confusion in exception handling revolves around whether it’s permissible to use only a try block without incorporating a catch block. The answer is affirmative; you can use a try block by itself, but it is obligatory to include a finally block as part of the structure.</p>
</blockquote>
<p>The final aspect to consider in exception handling is distinguishing between “throw ex” and “throw.” This distinction is crucial for pinpointing the exact source of the issue.</p>
<p>When you employ the <code>throw</code> keyword, it allows you to identify the precise line responsible for the problem while <code>throw ex</code> rethrows the exception, potentially losing the original stack trace.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">try</span>
{
    DivideZero(); <span class="hljs-comment">// line 25</span>
}
<span class="hljs-keyword">catch</span> (Exception excp)
{    
    Console.WriteLine(excp.StackTrace);
}

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">DivideZero</span>(<span class="hljs-params"></span>)</span>
{
    <span class="hljs-keyword">try</span>
    {
        <span class="hljs-keyword">int</span> first = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">int</span> second = <span class="hljs-number">0</span>;

        <span class="hljs-keyword">int</span> result = first / second; <span class="hljs-comment">// line 39</span>
    }
    <span class="hljs-keyword">catch</span> (Exception excp)
    {
        <span class="hljs-keyword">throw</span>;
    }
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735130294017/b4dcdeb2-a1bf-4c92-b8d1-80fe59507c3d.png" alt /></p>
<p>The line number may vary depending on your specific environment and configuration.</p>
<p>When you use <code>throw ex</code>, it will indicate the line where the <code>throw ex</code> keyword is located, potentially masking the original line number where the exception was initially thrown. This can make it harder to trace the root cause of the issue. To preserve the original stack trace, it's better to use <code>throw</code> without the <code>ex</code> keyword.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">try</span>
{
    DivideZero(); <span class="hljs-comment">// line 25</span>
}
<span class="hljs-keyword">catch</span> (Exception excp)
{
    Console.WriteLine(excp.StackTrace);
}

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">DivideZero</span>(<span class="hljs-params"></span>)</span>
{
    <span class="hljs-keyword">try</span>
    {
        <span class="hljs-keyword">int</span> first = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">int</span> second = <span class="hljs-number">0</span>;

        <span class="hljs-keyword">int</span> result = first / second;
    }
    <span class="hljs-keyword">catch</span> (Exception excp)
    {
        <span class="hljs-keyword">throw</span> excp;<span class="hljs-comment">// line 43</span>
    }
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735130295138/55208795-9f50-4d76-b4c6-ee695eb732b9.png" alt /></p>
<p>This is why <code>throw</code> should be preferred over <code>throw ex</code>.</p>
<blockquote>
<p>It’s important to emphasize that error handling should be implemented at a higher level rather than at a lower level. When error handling is implemented at the lower level, it becomes impossible to catch errors that occur at the higher level. Conversely, by implementing error handling at the higher level, errors can be captured wherever they occur in the code.</p>
</blockquote>
<p>In conclusion, understanding and implementing effective error handling in C# is essential for developing robust and reliable software applications.</p>
<p>By utilizing try-catch-finally blocks, developers can manage exceptions gracefully, ensuring that applications can handle unexpected situations without crashing.</p>
<p>The ability to use multiple catch blocks allows for specific handling of different exception types, while the distinction between <code>throw</code> and <code>throw ex</code> is crucial for maintaining accurate stack traces. Prioritizing error handling at a higher level in the code structure further enhances the application's stability. By mastering these techniques, developers can significantly improve the quality and resilience of their software solutions.</p>
<p>To access the accompanying code, please follow the provided <a target="_blank" href="https://github.com/frttnk/Exploring-Error-Handling-with-Try-Catch-Blocks-in-C-">link</a>.</p>
]]></content:encoded></item></channel></rss>