<?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" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Unit Coding]]></title><description><![CDATA[Software Development & amazing projects]]></description><link>https://unitcoding.com/</link><image><url>https://unitcoding.com/favicon.png</url><title>Unit Coding</title><link>https://unitcoding.com/</link></image><generator>Ghost 5.59</generator><lastBuildDate>Sat, 11 Apr 2026 23:01:09 GMT</lastBuildDate><atom:link href="https://unitcoding.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Build a Todo application with Blazor and C#]]></title><description><![CDATA[<p>&quot;Hi there! Today, we&#x2019;re going to build a to-do application&#x2014;but with a twist. Unlike the typical to-do apps you might find in countless tutorials, this one will feature a sleek interface, smooth animations, and one or two more additional features beyond a regular to-do application.</p>]]></description><link>https://unitcoding.com/build-a-todo-application-with-blazor/</link><guid isPermaLink="false">67cf760ffb83c504df341c84</guid><category><![CDATA[ASP NET Core]]></category><category><![CDATA[Blazor]]></category><category><![CDATA[beginner]]></category><category><![CDATA[C#]]></category><dc:creator><![CDATA[Oscar Montenegro]]></dc:creator><pubDate>Mon, 31 Mar 2025 16:27:51 GMT</pubDate><media:content url="https://unitcoding.com/content/images/2025/03/Build-a-Todo-application-with-Blazor-and-C-.png" medium="image"/><content:encoded><![CDATA[<img src="https://unitcoding.com/content/images/2025/03/Build-a-Todo-application-with-Blazor-and-C-.png" alt="Build a Todo application with Blazor and C#"><p>&quot;Hi there! Today, we&#x2019;re going to build a to-do application&#x2014;but with a twist. Unlike the typical to-do apps you might find in countless tutorials, this one will feature a sleek interface, smooth animations, and one or two more additional features beyond a regular to-do application. </p><p>Having said that I have to mention that this application does not intend to be flawless or a production ready product, but a nice looking and fun to use project for you to get started if you desire to learn blazor or maybe you already know but you like coding fun stuff, also the application design is not mine while I coded the app entirely from the markup, the styling and the C# code I got the design from Figma while looking for an amazing interface and I found it, so all credit goes to its author &#x201C;itcenter uchquduq&#x201D;. Ready to get started? Let&#x2019;s dive in and bring this project to life!&quot;</p><h3 id="give-the-project-a-start-on-github">Give the project a start on Github</h3><p>If you come across an issue, or while coding along with the article, something doesn&#x2019;t look like it should, I recommend you to take a look at the code on Github to make sure your code is similar to mine. Also please if you enjoy coding this app give the project a start on Github to know that you liked it and create more projects like this one.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Osempu/TodoApplication?ref=unitcoding.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - Osempu/TodoApplication: A beautiful looking to-do application made with Blazor and C#</div><div class="kg-bookmark-description">A beautiful looking to-do application made with Blazor and C# - Osempu/TodoApplication</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Build a Todo application with Blazor and C#"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">Osempu</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/871a68f7b1119b6a8593e27a259a3272e421416db30e68f21641d9d39477f4e5/Osempu/TodoApplication" alt="Build a Todo application with Blazor and C#"></div></a></figure><p>What You&#x2019;ll Learn</p><ul><li><strong>Build a Blazor WebAssembly App</strong>: Start from scratch and structure components like a pro.</li><li><strong>Craft Reusable UIs</strong>: Design components like <code>TodoHeader</code> and <code>TodoComponent</code> with event handling and data binding.</li><li><strong>Persist Data with local storage</strong>: Save tasks and theme preferences so nothing gets lost.</li><li><strong>Style with Flair</strong>: Implement a responsive dark/light theme using CSS variables and Line Awesome icons.</li><li><strong>Animate with CSS</strong>: Add slick transitions for adding/removing tasks (because details matter!).</li><li><strong>Filter Tasks Dynamically</strong>: Toggle between &#x201C;All,&#x201D; &#x201C;Active,&#x201D; and &#x201C;Completed&#x201D; tasks with real-time updates.</li></ul><h2 id="create-a-new-blazor-application">Create a new Blazor application</h2><p>First, let&#x2019;s start creating a new dotnet Blazor application using the dotnet cli with the following command.</p><p><code>dotnet new blazorwasm -o TodoApplication</code></p><p>This will create a new Blazor WebAssembly application with some boilerplate code that we will get rid of to start our application from scratch.</p><p>Get into your new project folder and open Visual Studio code with the following commands (you can use Visual Studio if you prefer; it will work as well)</p><p><code>cd TodoApplication</code></p><p><code>code . -r</code></p><p>Now, let&#x2019;s proceed to start removing some of the boilerplate codes so we can start working on our application. Go ahead and delete the <code>Counter</code> and <code>Weather</code> pages under the <code>Pages</code> folder. Now remove the <code>NavMenu.razor</code> component and <code>NavMenu.razor.css</code> from the <code>Layout</code> folder and in the <code>MainLayout.razor</code> component, remove the sidebar so the code looks like this.</p><pre><code class="language-html">@inherits LayoutComponentBase
&lt;div class=&quot;page&quot;&gt;
    &lt;main&gt;
        &lt;article&gt;
            @Body
        &lt;/article&gt;
    &lt;/main&gt;
&lt;/div&gt;</code></pre><pre><code class="language-css"> 
 /*remove the styling for the article element*/
  .top-row, article {
      padding-left: 2rem !important;
      padding-right: 1.5rem !important;
  }</code></pre><p>This will remove the sidebar and the top navbar with the About link so we can have a nice white canvas to start designing. Now, your application should look something like this. Nothing but the welcome text.</p><figure class="kg-card kg-image-card"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742958669651/7c0bcf0d-141e-4763-8aaf-16cfe67600d9.png" class="kg-image" alt="Build a Todo application with Blazor and C#" loading="lazy"></figure><h2 id="let%E2%80%99s-begin-with-the-simplest-implementation">Let&#x2019;s begin with the simplest implementation</h2><p>We want to start by quickly implementing the simplest solution for the todo application; for that, we will create all the code in the <code>home.razor</code> file, and once done, we will move forward to create the components and add some complexity.</p><h3 id="remove-bootstrap-and-default-styling">Remove Bootstrap and default styling</h3><p>Let&#x2019;s begin by removing the reference to the bootstrap library in the <code>index.html</code> file and in the <code>app.css</code> file, we will remove the undesired padding in the <code>.content</code> class, and we will also remove the margin and padding to the HTML and body elements.</p><pre><code class="language-html">&lt;!--index.html--&gt;

&lt;!--Remove this line from the index.html file--&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;css/bootstrap/bootstrap.min.css&quot; /&gt;</code></pre><pre><code class="language-css">/*app.css*/

/*Lets reset the styling for theese elements*/
html, body {
    ...
    margin: 0px;
    padding: 0px;
    box-sizing: border-box;
}

/*Remove this class to avoid clashing with our own content implementation*/
.content {
    padding-top: 1.1rem;
}</code></pre><h3 id="create-a-todo-model">Create a Todo model</h3><p>Now, let&#x2019;s move on to create our to-do model that will hold the to-do name and whether it is done or not, so let&#x2019;s add some default values for each of the properties.</p><pre><code class="language-csharp">namespace TodoApplication.Models;

public class Todo
{
    public string Title { get; set; } = string.Empty;
    public bool IsDone { get; set; } = false;
}</code></pre><p>This will be our main class, which will be used through our application.</p><h3 id="adding-just-the-very-basics">Adding just the very basics</h3><p>For our first version, we will not be creating any component or adding any styling to the application; we will only rely on the HTML elements and some C# code.</p><pre><code class="language-html">/*Home.razor*/
&lt;PageTitle&gt;Todo Application&lt;/PageTitle&gt;

&lt;div class=&quot;app-container&quot;&gt;
	&lt;div class=&quot;hero&quot;&gt;
		&lt;div class=&quot;container&quot;&gt;
	    &lt;div class=&quot;header&quot;&gt;
	        &lt;h1 class=&quot;app-title&quot;&gt;TODO&lt;/h1&gt;
	    &lt;/div&gt;

		&lt;div class=&quot;body-container&quot;&gt;
		    &lt;input type=&quot;text&quot; placeholder=&quot;Create a new todo...&quot;
		        @bind=&quot;todoTitle&quot; 
		        @bind:event=&quot;oninput&quot;
		        @onkeydown=&quot;AddTodo&quot;&gt;
		
		    @foreach(var todo in todos) {
		        &lt;div&gt;
		            &lt;label&gt;
		                &lt;input type=&quot;checkbox&quot; @bind=&quot;todo.IsDone&quot;&gt; 
		                @todo.Title
		            &lt;/label&gt;
		            &lt;span class=&quot;remove-icon&quot; @onclick=&quot;() =&gt; RemoveTodo(todo)&quot;&gt;x&lt;/span&gt;
		        &lt;/div&gt;
		    }
	    &lt;/div&gt;
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/div&gt;</code></pre><p>We can see that the application is divided into three sections.</p><ol><li>The header, which will contain the application name</li><li>The form by means of which we will create the tasks consists of a text input that we will bind its value to a string called <code>todoTitle</code> that will be the title for newly created tasks. Also, this input has a <code>bind:event</code> on the <code>oninput</code> event to make sure we get the latest value inserted in the input, otherwise, we will always get the last value, and the first input will always be a blank string, and we don&#x2019;t want that to happen. Lastly, the <code>onkeydown</code> event will trigger the function <code>AddTodo</code> that will check if the pressed key is the <code>Enter</code> key and then will create the new task.</li><li>Finally, the tasks list(the code within the foreach loop) will contain every task created with a checkbox bound to the <code>IsDone</code> property of the task. The label will display the <code>Todo</code> title, and finally, we have a button to remove the selected task.</li></ol><p>For the C# code, we have the following:</p><pre><code class="language-csharp">@code {
	private List&lt;Todo&gt; todos = new List&lt;Todo&gt;();
	private string todoTitle = string.Empty;
	private void AddTodo(KeyboardEventArgs e) {
	    if (e.Key == &quot;Enter&quot; &amp;&amp; !string.IsNullOrWhiteSpace(todoTitle)) {
	        var newTodo = new Todo() { Title = todoTitle };
	        todos.Add(newTodo);
	        todoTitle = string.Empty;
	    }
	}
	
	private void RemoveTodo(Todo todo) {
	    todos.Remove(todo);
	}
}</code></pre><p>We have a list of <code>Todo</code> elements being this the todo list, we have a string value for the input that will create the new task. Then we have the <code>AddTodo</code> function that, as we mentioned before, passes the <code>KeyboardEventArgs</code> as a parameter, and inside, we check if the pressed key is the <code>Enter</code> key, and if it is, it will create a new <code>Todo</code> using the value from the <code>todoTitle</code> variable and will remove the value from <code>todoTitle</code> variable to reset the input element. Lastly, the <code>RemoveTodo</code> function, as the name suggests, removes the selected task. This code can be in the same <code>Home.razor</code> file for now right below the markup.</p><p>With this, we have our application working, we can create a task, mark it as completed, and remove it from the list. Now, we will take it to the next level, adding styling and some more features.</p><figure class="kg-card kg-image-card"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743138848544/dc2c7806-fa94-4893-b0c7-9be593c23357.png" class="kg-image" alt="Build a Todo application with Blazor and C#" loading="lazy"></figure><h3 id="leveling-up-our-application">Leveling up our application</h3><p>Now, it&#x2019;s time to enhance our to-do application by creating components, adding awesome styling, and adding the necessary code.</p><p>First, let&#x2019;s create the header component containing the application title, an icon to toggle the theme, and the form to input the todo title.</p><h3 id="creating-the-header-component">Creating the Header component</h3><p>Start by abstracting the markup and code from the header into its own component, so start creating a folder named <code>Components</code> , and there you will be storing every new component that will be needed. Now, create a new component named <code>TodoHeader.razor</code> Here, you will move the corresponding markup and code to work as intended, but before adding any code, let&#x2019;s write down what will be the responsibilities of the header component.</p><p>The header component will:</p><ul><li>Display the application title</li><li>Display an icon to indicate whether the application is in dark or light mode.</li><li>Emit an event to toggle between light or dark mode</li><li>Display an image for dark mode and another one for light mode</li></ul><p>So having said that, let&#x2019;s move to the new header component, and also let&#x2019;s add the new code for the features listed above.</p><pre><code class="language-csharp">/*TodoHeader.razor*/
@using Blazored.LocalStorage
@inject ILocalStorageService localStorage

&lt;div class=&quot;header&quot;&gt;
    &lt;h1 class=&quot;app-title&quot;&gt;@AppTitle&lt;/h1&gt;
    &lt;i class=&quot;@icon&quot; 
        @onclick=&quot;Toggle&quot;&gt;&lt;/i&gt;
&lt;/div&gt;

@code {
    [Parameter]
    public string AppTitle { get; set; } = string.Empty;
    [Parameter]
    public EventCallback&lt;bool&gt; ToggleState { get; set; }
    [Parameter]
    public string LightIcon { get; set; } = string.Empty;
    [Parameter]
    public string DarkIcon { get; set; } = string.Empty;
    private bool isDarkMode = false;
    private string icon = string.Empty;

    protected override async Task OnInitializedAsync() {
        isDarkMode = await localStorage.GetItemAsync&lt;bool&gt;(&quot;IsDarkModeEnabled&quot;);
        icon = isDarkMode ? LightIcon : DarkIcon;
    }

    private async Task Toggle() {
        isDarkMode = !isDarkMode;
        await localStorage.SetItemAsync&lt;bool&gt;(&quot;IsDarkModeEnabled&quot;, isDarkMode);
        icon = isDarkMode ? LightIcon : DarkIcon;
        await ToggleState.InvokeAsync(isDarkMode);    }
}</code></pre><p>Let&#x2019;s start breaking down the code from top to bottom. First, you will see a reference to a library named <code>Blazored.LocalStorage</code> , which will help you manage the local storage in your application, allowing you to store the state of your theme application even after reloading it. We will also use it to store our tasks. Below, we are injecting the local storage service and naming it <code>localStorage</code> . This will allow you to use the service in your component.</p><p>Below is all the markup needed for the header component, there&#x2019;s a wrapper container with a class named header, and inside of it is an h1 tag that&#x2019;s holding the application title in a property, and below is the theme icon which will work as a toggle button to change between light and dark mode.</p><p>Then, at the top of the code section, we have some properties. The first one is the application title, followed by the <code>ToggleState</code> event callback that will be invoked when clicking on the toggle theme icon. The <code>DarkIcon</code> and <code>LightIcon</code> will be used to specify the icon used for the dark and light theme, as the properties before this will be passed as parameters so they can be configured when calling the header component. The <code>isDarkMode</code> variable will be used to check if the dark mode is active or not, and similarly, the icon variable will be used to get and set the current icon in the header.</p><p>We call the <code>onInitializedAsync</code> so that when the component is initialized, it checks for the IsDarkModeEnabled value in the local storage to set that in the isDarkMode variable. Based on that, it will set whether the icon displayed should be a light or dark icon. Lastly, the Toggle function will set the <code>isDarkMode</code> to the opposite value, then store that in the local storage, change the icon based on the variable, and invoke the <code>ToggleState</code> event callback, passing back the negated <code>isDarkMode</code> value.</p><h3 id="style-for-the-header-component">Style for the header component</h3><pre><code class="language-css">/*TodoHeader.razor.css*/
.header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
}

i.la-sun, i.la-moon {
    font-size: 3rem;
    color: #fff;
}

i.la-sun:hover, i.la-moon:hover {
    color: #ccc;
    cursor: pointer;
}

.app-title {
    font-size: 3rem;
    margin: 20px;
    margin-left: 0px;
    color: #FFF;
    text-align: left;
    user-select: none;
    letter-spacing: 1rem;
}</code></pre><p>Create a new file at the same level as the header component file and name it <code>TodoHeader.razor.css</code> in this file, we will define the styling for this component.</p><h3 id="adding-more-styling-to-the-appcss-file">Adding more styling to the <code>app.css</code> file</h3><p>The following styling should be added in the <code>app.css</code> file to apply some global stylings to your application, I recommend you remove what you have in the file and add the styles below to avoid confusion. You will notice there are references to two images in the <code>:root</code> and <code>.dark</code> classes, those images can be downloaded from the repository of this project on my GitHub page, or you can use your own.</p><pre><code class="language-css">html, body {
    font-family: &apos;Roboto&apos;, Helvetica, Arial, sans-serif;
    margin: 0px;
    padding: 0px;
}

h1:focus {
    outline: none;
}

:root {
    /*Default Light Theme*/
    --primary-color: #fff;
    --secondary-color: #fafafa;
    --text-color: #000;
    --border-color: #eee;
    --accent-color:  linear-gradient(190deg, rgba(85, 150, 255, 0.8) 0%, rgba(172, 45, 235, 0.8) 100%);
    --bground-img: url(&apos;../img/bground.jpg&apos;);
    --accent-secondary-color: #f0f7f4;
    transition: background 0.3s;
}

.dark-theme {
    --primary-color: #25273d;
    --secondary-color: #171823;
    --text-color: #fff;
    --border-color: #5a5757;
    --bground-img: url(&apos;../img/bground-dark.jpg&apos;);
    --accent-color:  linear-gradient(190deg, rgba(80, 255, 100, 0.8) 0%, rgba(50, 150, 255, 0.8) 100%);
    --accent-secondary-color: #494C6B;
    transition: background 0.3s;
}

#blazor-error-ui {
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

.blazor-error-boundary::after {
    content: &quot;An error has occurred.&quot;
}

.loading-progress {
    position: relative;
    display: block;
    width: 8rem;
    height: 8rem;
    margin: 20vh auto 1rem auto;
}

.loading-progress circle {
    fill: none;
    stroke: #e0e0e0;
    stroke-width: 0.6rem;
    transform-origin: 50% 50%;
    transform: rotate(-90deg);
}

.loading-progress circle:last-child {
    stroke: #1b6ec2;
    stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
    transition: stroke-dasharray 0.05s ease-in-out;
}

.loading-progress-text {
    position: absolute;
    text-align: center;
    font-weight: bold;
    inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}

.loading-progress-text:after {
    content: var(--blazor-load-percentage-text, &quot;Loading&quot;);
}</code></pre><h3 id="calling-the-header-component-from-the-home-page">Calling the header component from the home page</h3><p>Now, you can remove the old markup to display the app title and call the header component instead. You will have to pass the name of the application to the <code>AppTitle</code> parameter as well for the icons and for the <code>ToggleState</code> event callback,k you will pass the function that will be called when this event is triggered.</p><p>The <code>OnInitializedAsync</code> function was added to look for the stored <code>appTheme</code> value in the local storage. If it does not exist, then the default value will be an empty string. The <code>ToggleTheme</code> function receives a bool as a parameter, as you can see in the <code>TodoHeader</code> component, we are not passing any argument, so where is this value coming from? Well, it turns out that the <code>ToggleState</code> event callback is of type <code>bool</code>, and when you invoke it in the header component, you pass back that bool value when calling this line of code in the <code>Toggle</code> function <code>await ToggleState.InvokeAsync(!isDarkMode)</code> So that&#x2019;s where that value is coming from, and what this function does is that it sets the app theme to <code>dark-theme</code> or to blank string depending on the flag it receives and then stores that value in the local storage. Now, this was,y you can have your component in place and ready to work, but before that let&#x2019;s add some more styling to the application also you need to install some libraries to make everything work.</p><pre><code class="language-csharp">/*Home.razor*/
&lt;div class=&quot;app-container @appTheme&quot;&gt; /*Dont forget to add this class to get the theme toggle working*/
    &lt;div class=&quot;hero&quot;&gt;
        &lt;div class=&quot;container&quot;&gt;
            &lt;TodoHeader
                AppTitle=&quot;TODO&quot;
                LightIcon=&quot;las la-sun&quot;
                DarkIcon=&quot;las la-moon&quot;
                ToggleState=&quot;ToggleTheme&quot;
            /&gt;
        &lt;/div&gt;
	    &lt;/div&gt;
   ...
   
   @code {
   ...
      private string appTheme = string.Empty;

	  protected async override Task OnInitializedAsync() {
      //Get Theme values from Local Storage
      appTheme = await localStorage.GetItemAsync&lt;string&gt;(&quot;appTheme&quot;) ?? &quot;&quot;;
    }
    ...
    private async Task ToggleTheme(bool isDarkTheme) {
      appTheme = isDarkTheme ? &quot;dark-theme&quot; : &quot;&quot;;
      await localStorage.SetItemAsync&lt;string&gt;(&quot;appTheme&quot;, appTheme);
    }
    ...
  }</code></pre><h3 id="styles-for-the-home-page">Styles for the home page</h3><p>There&apos;s not much to say here; just adjusting the header layout and adding color to the background.</p><pre><code class="language-css">/*Home.razor.css*/
* {
    box-sizing: border-box;
}

.app-container {
    position: relative;
    background-color: var(--secondary-color);
    height: 100vh;
}

.hero {
    display: block;
    position: absolute;
    height: 40vh;
    background: var(--accent-color), var(--bground-img);
    background-size: cover;
    background-position: center 40%;
    mix-blend-mode: normal;
    width: 100%;
    min-width: 500px;
    transition: all .3s ease;
}

.footer {
    position: relative;
    display: block;
    height: 40vh;
    width: 100%;
}

.container {
    flex-direction: column;
    align-items: center;
    position: relative;
    margin: 50px auto;
    display: flex;
    width: 40%;
    transition: 
    width 0.5s ease, 
    height 0.5s ease, 
    font-size 0.5s ease, 
    transform 0.5s ease;
}

.remove-icon:hover {
    cursor: pointer;
}

.body-container {
    width: 100%;
}

@media only screen and (max-width: 1200px) {
    .container {
        width: 60%;
        transition: all .3s linear;
    }
}

@media only screen and (max-width: 720px) {
    .container {
        width: 80%;
        transition: all .3s linear;
    }
}</code></pre><h3 id="using-line-awesome-icons">Using Line Awesome icons</h3><p>To be able to use the sun and moon icons in our application, we will be using the Line Awesome icons library, which is free, and you can start using it by loading it from CDN, as shown below. Go to your <code>index.html</code> file and place this link above the <code>head</code> tag.</p><pre><code class="language-csharp">...
	link rel= &quot;stylesheet&quot; href= &quot;&lt;https://maxst.icons8.com/vue-static/landings/line-awesome/line-awesome/1.3.0/css/line-awesome.min.css&quot; &gt;
&lt;/head&gt;
...</code></pre><h3 id="install-blazoredlocalstorage-nuget-package">Install <code>Blazored.LocalStorage</code> NuGet package</h3><p>To have the local storage working in our application, we will use a third-party library, which you can install using the command below.</p><p><code>dotnet add package Blazored.LocalStorage</code></p><p>Then, go to your <code>Program.cs</code> file and register your service there.</p><pre><code class="language-csharp">builder.Services.AddScoped(sp =&gt; new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddBlazoredLocalStorage(); //This is where you should place it.

await builder.Build().RunAsync();</code></pre><p>And add the Blazored.LocalStorage reference in the Home page and TodoHeader component like shown below.</p><pre><code class="language-csharp">/*Add these two lines to both Home.razor and TodoHeader.razor*/
@using Blazored.LocalStorage
@inject ILocalStorageService localStorage</code></pre><p>Now you can run your application, and it should look something like this.</p><figure class="kg-card kg-image-card"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743139148931/f7852dda-5d59-41d5-9806-6b6cf27daedf.png" class="kg-image" alt="Build a Todo application with Blazor and C#" loading="lazy"></figure><h3 id="styling-the-todo-input">Styling the todo input</h3><p>Let&#x2019;s make the to-do input element bigger and adjust it to the layout. Add the code below to the <code>Home.razor.css</code> and then take a look at the changes.</p><pre><code class="language-css">/*Home.razor.css*/
/* Todo Text Input */
input[type=&quot;text&quot;] {
    padding-top: 15px;
    padding-bottom: 15px;
    padding-left: 30px;
    padding-right: 30px;
    margin-bottom: 20px;
    border-radius: 4px;
    width: 100%;
    border: none;
    font-size: 1.2rem;
    color: var(--text-color);
    background-color: var(--primary-color);
}

input::placeholder {
    font-size: 1.2rem;
}</code></pre><figure class="kg-card kg-image-card"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743139217828/010a0eb8-9d9e-4b3e-a872-830b10ce5378.png" class="kg-image" alt="Build a Todo application with Blazor and C#" loading="lazy"></figure><p>Now it looks incredible and gives the application a fresh and professional look by making the font and the placeholder bigger as well as adjusting the size of the container.</p><p>For the todo form we will not be making it a component as the functionality is not that much so creating a component just for the sake of doing it would be an overkill so having said this, let&#x2019;s move on.</p><h3 id="adding-the-tasks-container-and-todo-component">Adding the tasks container and todo component</h3><p>In the components folder, add the new <code>TodoComponent</code> and its styling sheet <code>TodoComponent.razor.css</code>.</p><pre><code class="language-csharp">/*TodoComponent.razor*/
@using TodoApplication.Models

&lt;div class=&quot;checkbox-wrapper add-task @RemoveAnimation&quot;&gt;
    &lt;div class=&quot;task-container&quot; @onclick=&quot;CheckTask&quot;&gt;
        &lt;input type=&quot;checkbox&quot; @bind=&quot;Todo.IsDone&quot;&gt;
        &lt;label&gt;
            &lt;div class=&quot;tick-mark&quot;&gt;&lt;/div&gt;
        &lt;/label&gt;
        &lt;span class=&quot;task-title @StrikeoutClass&quot;&gt;@Todo.Title&lt;/span&gt;
    &lt;/div&gt;
    &lt;div class=&quot;icon-container&quot;&gt;
        &lt;i class=&quot;las la-times&quot; @onclick=&quot;RemoveTodo&quot;&gt;&lt;/i&gt;
    &lt;/div&gt;
&lt;/div&gt;

@code {
    [Parameter]
    public Todo Todo {get; set;} = new();
    [Parameter]
    public EventCallback&lt;Todo&gt; OnRemoveTodo{get; set;}
    [Parameter]
    public EventCallback OnCheckTodo {get; set;}
    [Parameter]
    public string RemoveAnimation {get; set;} = string.Empty;
    private string StrikeoutClass =&gt; Todo.IsDone ? &quot;strikeout-gradient&quot; : &quot;&quot;;
    

    private void CheckTask() {
        this.Todo.IsDone = !this.Todo.IsDone;
        OnCheckTodo.InvokeAsync();
    }

    private async Task RemoveTodo() {
        this.RemoveAnimation = &quot;remove-task&quot;;
        await Task.Delay(300);
        await OnRemoveTodo.InvokeAsync(this.Todo);
    }
}</code></pre><p>The markup is pretty straightforward: a wrapper with three classes to outline the container, add an animation when adding a new task, and an animation for when that task is removed. Within this wrapper, we have the checkbox bound to the <code>Todo.IsDone</code> property. Next to it, we have the label with a div to display the custom check. There is a span for the to-do title with a class to add a strikeout style to the text when the task is marked as done, and we also pass a function to the <code>onclick</code> event to mark the task as done when clicking on the label and an <code>i</code> tag to display the cross to remove the task so we also pass a function to the <code>onclick</code> event.</p><p>For the component code, we define a todo object that you can pass as a parameter, the todo unique identifier as a parameter, and two event callbacks: one for removing the current todo and the other to be fired up after checking the task as done. The <code>StrikeoutClass</code> function toggles the class to add the strikeout style based on the current todo <code>IsDone</code> value. The <code>CheckTask</code> function toggles the current todo <code>IsDone</code> value and the <code>RemoveTodo</code> function triggers the <code>remove-task</code> animation by adding the class to the component, waits 300 milliseconds, and invokes <code>RemoveTodoCallback</code> passing back the current task to be removed.</p><p>The styles are somewhat complex and I will not act like I understand all of this code, I took most of it from <a href="https://uiverse.io/checkboxes?ref=unitcoding.com" rel="noopener noreferrer nofollow">uiverse</a> which is an incredible website where you can get inspiration from tons of designs made by other talented developers and reuse the code adjusting it to your needs as I did for the checkbox.</p><pre><code class="language-css">/*TodoComponent.razor.css*/
.checkbox-wrapper {
    display: flex;
    align-items: center;
    border-bottom: 0.5px solid var(--border-color);
    background-color: var(--primary-color);
    transition: transform 0.3s ease, opacity 0.3s ease;
  }

  .task-container {
    flex: 0 0 85%;
    display: flex;
    align-items: center;
    padding: 20px;
    cursor: pointer;
  }
  
  .checkbox-wrapper:hover .la-times {
    visibility: visible;
  }
  
  .checkbox-wrapper input[type=&quot;checkbox&quot;] {
    display: none;
  }
  
  .checkbox-wrapper label {
    --size: 30px;
    --shadow: calc(var(--size) * .07) calc(var(--size) * .1);
    position: relative;
    display: block;
    width: var(--size);
    height: var(--size);
    background-color: #4158D0;
    background-image: var(--accent-color);
    border-radius: 50%;
    cursor: pointer;
    overflow: hidden;
    z-index: 1;
  }
  
  .checkbox-wrapper label:before {
    content: &quot;&quot;;
    position: absolute;
    top: 50%;
    right: 0;
    left: 0;
    width: calc(var(--size) * .7);
    height: calc(var(--size) * .7);
    margin: 0 auto;
    background-color: #fff;
    transform: translateY(-50%);
    border-radius: 50%;
    box-shadow: inset 0 var(--shadow) #ffbeb8;
    transition: 0.2s ease width, 0.2s ease height;
  }
  
  .checkbox-wrapper label:hover:before {
    width: calc(var(--size) * .55);
    height: calc(var(--size) * .55);
    box-shadow: inset 0 var(--shadow) #ff9d96;
  }
  
  .checkbox-wrapper label:active {
    transform: scale(0.9);
  }
  
  .checkbox-wrapper .tick-mark {
    position: absolute;
    top: -1px;
    right: 0;
    left: calc(var(--size) * -.05);
    width: calc(var(--size) * .6);
    height: calc(var(--size) * .6);
    margin: 0 auto;
    margin-left: calc(var(--size) * .14);
    transform: rotateZ(-40deg);
  }
  
  .checkbox-wrapper .tick-mark:before,
    .checkbox-wrapper .tick-mark:after {
    content: &quot;&quot;;
    position: absolute;
    background-color: #fff;
    border-radius: 2px;
    opacity: 0;
    transition: 0.2s ease transform, 0.2s ease opacity;
  }
  
  .checkbox-wrapper .tick-mark:before {
    left: 0;
    bottom: 0;
    width: calc(var(--size) * .1);
    height: calc(var(--size) * .3);
    box-shadow: -2px 0 5px rgba(0, 0, 0, 0.23);
    transform: translateY(calc(var(--size) * -.68));
  }
  
  .checkbox-wrapper .tick-mark:after {
    left: 0;
    bottom: 0;
    width: 100%;
    height: calc(var(--size) * .1);
    box-shadow: 0 3px 5px rgba(0, 0, 0, 0.23);
    transform: translateX(calc(var(--size) * .78));
  }
  
  .checkbox-wrapper input[type=&quot;checkbox&quot;]:checked + label {
    background-color: #4158D0;
    background-image: var(--accent-color);
  
  }
  
  .checkbox-wrapper input[type=&quot;checkbox&quot;]:checked + label:before {
    width: 0;
    height: 0;
  }
  
  .checkbox-wrapper input[type=&quot;checkbox&quot;]:checked + label .tick-mark:before,
    .checkbox-wrapper input[type=&quot;checkbox&quot;]:checked + label .tick-mark:after {
    transform: translate(0);
    opacity: 1;
  }
  
  .task-title {
    margin-left: 10px;
    font-size: 1rem;
    color: var(--text-color);
    cursor: pointer;
  }

  .icon-container {
    flex-grow: 1;
  }
  
  .la-times {
    margin-left: auto;
    cursor: pointer;
    color: var(--text-color);
    font-size: 1.5rem;
    visibility: hidden;
  }
  
  .la-times:hover {
    background-color: rgba(240, 240, 240, 0.8);
    padding: 2px;
    border-radius: 50%;
    color: #0a0a0a
  }
  
  .strikeout-gradient {
    background-image: var(--accent-color);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent; /* Makes the gradient visible */
    position: relative; /* Enables positioning of the pseudo-element */
  }
  
  .strikeout-gradient::after {
    content: &apos;&apos;; /* Required for pseudo-element */
    position: absolute;
    left: 0;
    right: 0;
    top: 50%; /* Positions the line in the middle of the text */
    height: 2px; /* Adjust for thickness of the line */
    background-color: rgba(0, 0, 0, 0.5); /* A semi-transparent black or any desired color */
    transform: translateY(-50%); /* Centers the line perfectly */
  }
  
  /* Add Animation */
  .add-task {
    animation: grow 0.3s ease backwards;
  }
  
  /* Keyframes for grow (adding a task) */
  @keyframes grow {
    0% {
        opacity: 0;
        transform: scale(0.5);
    }
    100% {
        opacity: 1;
        transform: scale(1);
    }
  }
  
  /* Remove Animation */
  .remove-task {
    animation: shrink 0.3s ease forwards;
    opacity: 0;
  }
  
  /* Keyframes for shrink (removing a task) */
  @keyframes shrink {
    0% {
        opacity: 1;
        transform: scale(1);
    }
    100% {
        opacity: 0;
        transform: scale(0.5);
    }
  }</code></pre><p>Now place your <code>TodoComponent</code> inside the foreach loop at the home page to display all the tasks in the list and pass the values for all its parameters as shown below. Also, add the following style rules to your <code>Home.razor.css</code> style sheet above the media queries section. As you may have noticed, we are still not passing a handler to the <code>OnCheckTodo</code> event, we will do that in a moment.</p><pre><code class="language-xml">&lt;!-- Home.razor --&gt;
&lt;div class=&quot;body-container&quot;&gt;
    &lt;input type=&quot;text&quot; placeholder=&quot;Create a new todo...&quot; @bind=&quot;todoTitle&quot; @bind:event=&quot;oninput&quot;
        @onkeydown=&quot;AddTodo&quot;&gt;

     &lt;div class=&quot;todos-container&quot;&gt;
          @if(!todos.Any()) 
          {
               &lt;p class=&quot;no-tasks-text&quot;&gt;
                   Start adding some tasks! &#x2705;
               &lt;/p&gt;
           } 
           else
           {
                @foreach (var todo in todos)
                {
                    &lt;TodoComponent 
                       Todo=&quot;todo&quot;
                        RemoveAnimation=&quot;@String.Empty&quot;
                        OnRemoveTodo=&quot;RemoveTodo&quot;/&gt;
                }
           }
      &lt;/div&gt;
&lt;/div&gt;</code></pre><pre><code class="language-css">/*Home.razor.css*/
.todos-container {
    background-color: #fff;
    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(0, 0, 0, 0.12);
    border-top-left-radius: 5px;
    border-top-right-radius: 5px;
    overflow-x: hidden;
    background-color: var(--primary-color);
    overflow-y: scroll;
    height: auto;
    max-height: 400px;
}

.no-tasks-text {
    padding: 5px;
    text-align: center;
    color: #8f8f8f;
    font-weight: 500;
}

::-webkit-scrollbar {
    width: 6px;
}

::-webkit-scrollbar:horizontal {
    height: 6px;
}

::-webkit-scrollbar-track {
    background: transparent;
}
 
::-webkit-scrollbar-thumb {
    border-radius: 10px;
    background-color: #aaa;
    opacity: 0;
    transition: opacity 0.3 ease;
}</code></pre><p>Your to-do app is looking more and more stunning as you continue adding more stuff.</p><figure class="kg-card kg-image-card"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742600141577/57274be3-5dde-429a-8224-a598ff37c855.png" class="kg-image" alt="Build a Todo application with Blazor and C#" loading="lazy"></figure><h3 id="storing-tasks-in-local-storage">Storing tasks in local storage</h3><p>The next step is to save the list of tasks to local storage so you don&#x2019;t lose your tasks every time the application is refreshed or closed. You have to modify 3 methods on the home page and create another one to be used in the <code>TodoComponent</code>.</p><pre><code class="language-csharp">   /*Home.razor*/
    &lt;TodoComponent 
        Todo=&quot;todo&quot; 
        RemoveAnimation=&quot;@String.Empty&quot;
        OnRemoveTodo=&quot;RemoveTodo&quot;
        OnCheckTodo=&quot;UpdateTodoList&quot;/&gt; // Add the update todo handler

    ...
    protected async override Task OnInitializedAsync() {
        //Get Theme values from Local Storage
        appTheme = await localStorage.GetItemAsync&lt;string&gt;(&quot;appTheme&quot;) ?? &quot;&quot;;
        
        // Getting the todos from local storage when initializing the application
        todos = await localStorage.GetItemAsync&lt;List&lt;Todo&gt;&gt;(&quot;todos&quot;) ?? Enumerable.Empty&lt;Todo&gt;().ToList();
    }

    private async Task AddTodo(KeyboardEventArgs e) {
        if (e.Key == &quot;Enter&quot;) {
            var newTodo = new Todo() { Title = todoTitle };
            todos.Add(newTodo);
            //Updated the todos in the local storage after adding a todo
            await localStorage.SetItemAsync(&quot;todos&quot;, todos);
            todoTitle = string.Empty;
        }
    }

    // This method will be used in the Todo component in a moment
    private async Task UpdateTodoList() {
        await localStorage.SetItemAsync(&quot;todos&quot;, todos);
    }
    
    private async Task RemoveTodo(Todo todo) {
        todos.Remove(todo);
        // Update todos in the loca storage after removing a todo
        await localStorage.SetItemAsync(&quot;todos&quot;, todos);
    }</code></pre><p>With this, you update the tasks list every time you add a new task or remove and get the saved tasks list from the local storage when the application is refreshed and the <code>UpdateTodoList</code> method will be passed as a handler to the <code>OnRemoveTodo</code> event in the <code>TodoComponent</code> to update the list after marking a task as done.</p><h3 id="adding-the-tasks-filter">Adding the tasks filter</h3><p>You have come to the last section of this article, Here, you will add a task filter to display how many tasks remain, filter by some criteria, and remove completed tasks. For this, you have to create the <code>TodoFilter</code> component.</p><pre><code class="language-csharp">/*TodoFilter.razor*/
&lt;div class=&quot;filter-container&quot;&gt;
    &lt;span class=&quot;items-left&quot;&gt; @ItemsLeft items left&lt;/span&gt;

    &lt;InputRadioGroup @bind-Value=&quot;selectedOption&quot;&gt;
        &lt;div class=&quot;radio-group&quot;&gt;
            @foreach(var filter in FilterOptions)
            {
                &lt;label @onclick=&quot;() =&gt; FilterTasksBy(filter.Key)&quot; class=&quot;radio-label&quot;&gt;
                    &lt;span class=&quot;radio-mask&quot;&gt;
                        &lt;InputRadio Value=&quot;@filter.Key&quot;/&gt;
                    &lt;/span&gt;
                    @filter.Value
                &lt;/label&gt;
            }
        &lt;/div&gt;
    &lt;/InputRadioGroup&gt;

    &lt;span class=&quot;clear-completed&quot; @onclick=&quot;ClearCompletedTasks&quot;&gt;Clear Completed&lt;/span&gt;
&lt;/div&gt;

@code {
    [Parameter]
    public int ItemsLeft { get; set; }
    [Parameter]
    public Dictionary&lt;string, string&gt; FilterOptions { get; set; } = new();
    [Parameter]
    public EventCallback ClearCompleted { get; set; }
    [Parameter]
    public EventCallback&lt;string&gt; FilterBy { get; set;}
    private string selectedOption = &quot;all&quot;;

    private void ClearCompletedTasks() {
        selectedOption = &quot;all&quot;;
        ClearCompleted.InvokeAsync();
    }

    private void FilterTasksBy(string taskStatus) {
        selectedOption = taskStatus;
        FilterBy.InvokeAsync(taskStatus);
    }
}</code></pre><p>This component consists of a span displaying the number of tasks left, a set of <code>InputRadio</code> elements that will filter the tasks by their status and a button to clear all completed tasks from the list. You must pass the number of tasks left, the filtering options, and the handlers for FilterBy and ClearCompleted events as parameters for this component. The <code>clearCompletedTasks</code> method will reset the selected filter option to all and then invoke the <code>clearCompleted</code> event, the <code>FilterTasksBy</code> method does something similar as it sets the <code>selectedOption</code> to the filter option selected and then invoke the <code>FilterBy</code> event passing back the task status.</p><p>For the styling, we are just using flexbox to get everything horizontally aligned and hiding the radio input to only show its label, and applying style if the input is checked.</p><pre><code class="language-css">/*TodoFilter.razor.css*/
.filter-container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 20px;
    box-sizing: border-box;
    background-color: var(--primary-color);
    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(0, 0, 0, 0.12);
    border-bottom-left-radius: 5px;
    border-bottom-right-radius: 5px;
    overflow-x: hidden;
}

 span {
    font-size: 10pt;
    color: #afafaf;
    font-weight: bold;
}

span:hover:not(:first-child) {
    cursor: pointer;
    font-size: 10pt;
    color: #6f6f6f;
    font-weight: bold;
}

.radio-group {
    display: flex;
    gap: 3px;
    justify-items: center;
}

.radio-group label{
  padding: 2px 4px;
  cursor: pointer;
  font-size: 10pt;
  font-weight: bold;
  color: #afafaf;
  transition: transform 0.3s ease, background-color 0.3s ease, color 0.3s ease;
}

.radio-group label:has(input:checked) {
  color: #5596FF;
  transform: scale(1.09);
}

.radio-mask {
  display: none;
}</code></pre><p>Let&#x2019;s move ahead and use our new component in our app!</p><pre><code class="language-csharp">/*Home.razor*/
...
&lt;TodoFilter
    ItemsLeft=&quot;todos.Count()&quot; 
    FilterOptions=&quot;filterOptions&quot; 
    FilterBy=&quot;FilterTodoList&quot; 
    ClearCompleted=&quot;ClearCompletedTasks&quot;/&gt;
...

@code {
    // This dictionary will hold the list of filters
    public Dictionary&lt;string, string&gt; filterOptions = new();

    protected async override Task OnInitializedAsync() {
        /*Code ommited for brevity*/
        
        //Add the filters instead of hardcoding them in the component
        filterOptions.Add(&quot;all&quot;, &quot;All&quot;);
        filterOptions.Add(&quot;active&quot;, &quot;Active&quot;);
        filterOptions.Add(&quot;completed&quot;, &quot;Completed&quot;);
    }

    // Return the filtered list after selecting the desired filter option
    private async Task FilterTodoList(string filterOption)
    {
        todos = await localStorage.GetItemAsync&lt;List&lt;Todo&gt;&gt;(&quot;todos&quot;) ?? Enumerable.Empty&lt;Todo&gt;().ToList();

         todos = filterOption switch
        {
            &quot;active&quot; =&gt;  todos.Where(x =&gt; !x.IsDone).ToList(),
            &quot;completed&quot; =&gt; todos.Where(x =&gt; x.IsDone).ToList(),
            _ =&gt;  await localStorage.GetItemAsync&lt;List&lt;Todo&gt;&gt;(&quot;todos&quot;) ?? Enumerable.Empty&lt;Todo&gt;().ToList()
        };
    }
    
    // Clear all the tasks that are marked as done
    private async Task ClearCompletedTasks() {
        todos = await localStorage.GetItemAsync&lt;List&lt;Todo&gt;&gt;(&quot;todos&quot;) ?? Enumerable.Empty&lt;Todo&gt;().ToList();
        todos = todos.Where(x =&gt; !x.IsDone).ToList();
        await localStorage.SetItemAsync(&quot;todos&quot;, todos);
    }
}</code></pre><p>Place the <code>TodoFilter</code> component below the tasks container and pass the parameters listed previously, you have to create a <code>&lt;string, string&gt;</code> dictionary to hold the filter values along with the text that will be displayed in the component, then add the filter options inside the <code>OnInitialized</code> method to make sure the filter is not empty when running the application. The <code>FilterTodoList</code> method gets the tasks list from the local storage and then filters the list based on the status of the task and the <code>ClearlCompletedTasks</code> also gets the stored tasks from the local storage and then removes the ones that have been marked as done.</p><h3 id="your-todo-app-is-now-complete">Your Todo app is now complete!</h3><figure class="kg-card kg-image-card"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742948865544/d18a3fb6-ee24-4e65-b175-6620916a6d17.png" class="kg-image" alt="Build a Todo application with Blazor and C#" loading="lazy"></figure><p>Your application is now complete and ready to streamline your tasks! You can seamlessly add, remove, filter, and clear completed items or switch to dark mode for a visually comfortable experience. I hope you&#x2019;ve found the process as rewarding as I did&#x2014;while perfection wasn&#x2019;t the goal, creating something functional and enjoyable while learning Blazor certainly was.</p><p>If you&#x2019;d like to see more articles like this or have ideas to enhance future tutorials, feel free to share your thoughts. Thank you for joining me on this journey, and I look forward to connecting again soon!</p>]]></content:encoded></item><item><title><![CDATA[Optimizing Your .NET Application Development with NDepend]]></title><description><![CDATA[<p>Lately I&#x2019;ve been absent taking some time to rest and finishing some delayed work. But I&#x2019;ve also been trying a new tool these days on my side projects, you already know what tool I&#x2019;m talking about by the title of the article so yeah</p>]]></description><link>https://unitcoding.com/devtools-ndepend/</link><guid isPermaLink="false">6499c2cbbb0b09c27afc2f4c</guid><category><![CDATA[DevTools]]></category><dc:creator><![CDATA[Oscar Montenegro]]></dc:creator><pubDate>Mon, 26 Jun 2023 17:29:32 GMT</pubDate><media:content url="https://unitcoding.com/content/images/2023/06/post_cover.png" medium="image"/><content:encoded><![CDATA[<img src="https://unitcoding.com/content/images/2023/06/post_cover.png" alt="Optimizing Your .NET Application Development with NDepend"><p>Lately I&#x2019;ve been absent taking some time to rest and finishing some delayed work. But I&#x2019;ve also been trying a new tool these days on my side projects, you already know what tool I&#x2019;m talking about by the title of the article so yeah NDepend it&#x2019;s a pretty cool tool for code analysis for projects where many devs are involved all of them applying their code conventions and committing changes every day, we know that code can become unmanageable pretty quick as we make changes for bugfixes of new features being added continuously. Also for projects with many dependencies, NDepend shines as it tracks all these dependencies and provides us with a meaningful dependencies map but more of that in just a bit.</p><h2 id="overview"><strong>Overview</strong></h2><p>NDepend is a static code analysis tool, that allows developers to manage code base quality through an array of metrics, visualizations, and rules. It helps identify bugs and vulnerabilities while ensuring your code complies with industry standards and best practices. Compatible with .NET and .NET Core applications, it simplifies the way you approach complex code bases, giving you more control and visibility.</p><p>NDepend manages the entire solution providing metrics, code review, graphs, and more for all your code within your solution. You can find it available for Visual Studio 2010 - 2022 so in terms of VS version NDepent got you covered.</p><h2 id="code-review"><strong>Code Review</strong></h2><p>The Code Review feature is one of the central functionalities provided by NDepend. Designed with a focus on improving code quality, it leverages static code analysis to systematically examine your code base.</p><p>This feature generates a detailed report on the potential issues within the code, identifying bugs, vulnerabilities, and areas where coding standards or best practices are not being adhered to. It provides insights into areas that require improvement, thereby allowing developers to fix issues before they escalate into bigger problems.</p><p>After installing the NDepend extension on VS2022 I searched for the Blog API project that we have been working on all this time and initialized the analysis on it.</p><figure class="kg-card kg-image-card"><img src="https://unitcoding.com/content/images/2023/06/begin_project.png" class="kg-image" alt="Optimizing Your .NET Application Development with NDepend" loading="lazy" width="1012" height="662" srcset="https://unitcoding.com/content/images/size/w600/2023/06/begin_project.png 600w, https://unitcoding.com/content/images/size/w1000/2023/06/begin_project.png 1000w, https://unitcoding.com/content/images/2023/06/begin_project.png 1012w" sizes="(min-width: 720px) 720px"></figure><p>I was presented with these different options and I must confess that I was eager to test every one of them. So I clicked on the dashboard option and I was amazed at how much information they set up for you and the level of analysis this tool can handle.</p><figure class="kg-card kg-image-card"><img src="https://unitcoding.com/content/images/2023/06/ndepend_dashboard.png" class="kg-image" alt="Optimizing Your .NET Application Development with NDepend" loading="lazy" width="931" height="747" srcset="https://unitcoding.com/content/images/size/w600/2023/06/ndepend_dashboard.png 600w, https://unitcoding.com/content/images/2023/06/ndepend_dashboard.png 931w" sizes="(min-width: 720px) 720px"></figure><p>You can see NDepend shows us the number of code lines our project contains, and how many do not belong to our code, this means code that belongs to external assemblies. Also, we can see the technical debt we have in our project as a percentage which I think is one of the most appealing graphics. Finally, on the right side, you can see the rules violations, quality gates, and existing issues in our code and you can define your own custom rules to make sure your code is enforcing the best practices.</p><h2 id="code-diff"><strong>Code Diff</strong></h2><p>The Code Diff feature in NDepend allows you to compare different versions of your code base, identifying changes, updates, or regressions. This is especially helpful in tracking the progress of refactoring, identifying risky code changes, or confirming if new versions are improving the code base quality.</p><figure class="kg-card kg-image-card"><img src="https://unitcoding.com/content/images/2023/06/code_diff.png" class="kg-image" alt="Optimizing Your .NET Application Development with NDepend" loading="lazy" width="1872" height="640" srcset="https://unitcoding.com/content/images/size/w600/2023/06/code_diff.png 600w, https://unitcoding.com/content/images/size/w1000/2023/06/code_diff.png 1000w, https://unitcoding.com/content/images/size/w1600/2023/06/code_diff.png 1600w, https://unitcoding.com/content/images/2023/06/code_diff.png 1872w" sizes="(min-width: 720px) 720px"></figure><p>With the diff tool, we can search by element, assembly, &#xA0;namespace, type, method, and so on. We can search for recent changes, removed lines, updated code, and wide criteria to look for code changes.</p><h2 id="trendings"><strong>Trendings</strong></h2><p>Monitoring trends is a pivotal aspect of maintaining code quality, and NDepend shines brightly in this arena. With its Trending feature, NDepend monitors various metrics over time, providing valuable insights into the evolution of your code base. You can easily visualize and analyze these trends to assess your development strategies&apos; effectiveness.</p><p>You know how sometimes you wish you could see how your code has changed over time? Like, has it gotten better or worse? Are certain bugs popping up more often? That&apos;s exactly what the Trendings feature does.</p><p>Trendings in NDepend are like a record of how you tend to code. It keeps an eye on various metrics over time and helps you understand how your code base is evolving. It&apos;s like a progress report that shows you the ups and downs of your code quality over different periods.</p><p>Imagine that you&apos;ve been working on refactoring some parts of your code, and you want to see if it&apos;s making a positive difference. The Trendings feature could show you if your changes have reduced code complexity or increased code coverage over time.</p><h2 id="dependencies-graph"><strong>Dependencies Graph</strong></h2><p>This is one of my favorite tools and the reason which I know NDepend, a couple of years ago I was working on a legacy project that was like 20 years old so I had like a ton of dependencies some of which I had no access or I didn&#x2019;t even have knowledge about and NDepend helped me to create a dependencies graph and finally be able to at least understand what was going on with that project. I shared a snapshot of the graph with my coworkers that had much more time working with that solution and even they were surprised by all the dependencies they didn&#x2019;t know were there.</p><p>In the case of the graph shown below this is an example of a dependencies graph generated from our BlogAPI project which is not that complex and has been coded all this time by only one developer so here you will not see something that complicated. Regardless of that it does not means that we are not getting any value from this feature for our project, this is very useful and I&#x2019;m pretty sure it will come in handy in the future as we continue to develop our API.</p><figure class="kg-card kg-image-card"><img src="https://unitcoding.com/content/images/2023/06/dependencies_graph.png" class="kg-image" alt="Optimizing Your .NET Application Development with NDepend" loading="lazy" width="1324" height="575" srcset="https://unitcoding.com/content/images/size/w600/2023/06/dependencies_graph.png 600w, https://unitcoding.com/content/images/size/w1000/2023/06/dependencies_graph.png 1000w, https://unitcoding.com/content/images/2023/06/dependencies_graph.png 1324w" sizes="(min-width: 720px) 720px"></figure><p>This feature gives you a visual map of your code, showing how different parts are linked or &apos;dependent&apos; on each other. It&apos;s like Google Maps but for your code. And just like you can see different routes and connections on a city map, the Dependencies Graph lets you see the intricate web of connections in your code.</p><p>This is super useful when you&apos;re trying to understand your code structure, especially if it&apos;s a large or complex code base. The graph can show you if there are any weird or unexpected connections in your code, which could be a sign that something&apos;s off. It can also help you figure out the best way to refactor or restructure your code.</p><p>Plus, the visual nature of the Dependencies Graph makes it easier to grasp and communicate these dependencies to others on your team. It&apos;s a way of turning complicated code connections into something you can see and understand.</p><h2 id="dependency-matrix"><strong>Dependency Matrix</strong></h2><p>NDepend&#x2019;s Dependency Matrix provides another way to analyze dependencies. It presents a matrix view of dependencies between elements in your code. With this feature, spotting and managing circular dependencies becomes effortless, ultimately leading to a cleaner, more efficient code base.</p><p>It lays out your code in a grid, with rows and columns representing different code elements. Where a row and a column intersect, you can see if and how those two elements are dependent on each other. For example, if class A uses class B, the intersection of A&apos;s row and B&apos;s column will show this.</p><p>The Dependency Matrix also helps you get a handle on the overall structure and organization of your code. You can quickly see which parts of your code are heavily interconnected and which parts are more isolated.</p><p>Below you can see an example of how this feature would look like, the image was taken from the NDepend docs.</p><figure class="kg-card kg-image-card"><img src="https://unitcoding.com/content/images/2023/06/matrix.png" class="kg-image" alt="Optimizing Your .NET Application Development with NDepend" loading="lazy" width="1230" height="509" srcset="https://unitcoding.com/content/images/size/w600/2023/06/matrix.png 600w, https://unitcoding.com/content/images/size/w1000/2023/06/matrix.png 1000w, https://unitcoding.com/content/images/2023/06/matrix.png 1230w" sizes="(min-width: 720px) 720px"></figure><h2 id="metrics-view"><strong>Metrics View</strong></h2><p>The Metrics View presents a kind of heatmap or a colored treemap, where each little block represents a piece of your code, like a class or a method. The size of the block shows the size of the code it represents, and its color indicates some specific characteristic you&apos;re interested in, like complexity or test coverage.</p><p>This lets you see at a glance what&apos;s going on with your code. You can instantly spot parts of your code that are large (the big blocks) or super complex (the blocks with darker colors). This is super useful because these areas are usually where bugs love to hide and where future issues may crop up.</p><p>The cool thing is that you can customize what characteristic the colors represent based on what you care about most. For example, if you&apos;re focused on making sure your code is well-tested, you could set up the colors to represent test coverage. That way, any parts of your code that don&apos;t have enough tests will stand out like a sore thumb.</p><figure class="kg-card kg-image-card"><img src="https://unitcoding.com/content/images/2023/06/code_metrics.png" class="kg-image" alt="Optimizing Your .NET Application Development with NDepend" loading="lazy" width="1542" height="904" srcset="https://unitcoding.com/content/images/size/w600/2023/06/code_metrics.png 600w, https://unitcoding.com/content/images/size/w1000/2023/06/code_metrics.png 1000w, https://unitcoding.com/content/images/2023/06/code_metrics.png 1542w" sizes="(min-width: 720px) 720px"></figure><h2 id="conclusion"><strong>Conclusion</strong></h2><p>From my perspective, NDepend is a good fit for almost every serious project as it will continue to grow and be supported by more than one developer in most cases so having all these features in hand with a single tool is a great help and can provide early relief to future problems on dependencies, bugs, code not following the best practices and being able to specify your own rules and metrics to make sure all your code is consistent with your code style.</p><p>If you want to know more about NDepend and try it by yourself and see if it fits your needs head to <a href="https://www.ndepend.com/?ref=unitcoding.com">https://www.ndepend.com/</a> and take the 14 days trial and use it on your side projects to have the chance to experience all the benefits it provides.</p>]]></content:encoded></item><item><title><![CDATA[Implementing CORS in ASP.NET Core Web API: Enabling Secure Cross-Origin Resource Sharing]]></title><description><![CDATA[In the world of ASP.NET Core Web API development, enabling secure cross-origin resource sharing (CORS) is essential to ensure controlled access to your API from different domains. In our upcoming blog post, "CORS in ASP.NET Core Web API: Enabling Secure Cross-Origin Resource Sharing," we will explore the importance of CORS and guide you through the implementation process.]]></description><link>https://unitcoding.com/implementing-cors-aspnetcore/</link><guid isPermaLink="false">6487eb85bb0b09c27afc2f16</guid><category><![CDATA[ASP NET Core]]></category><category><![CDATA[REST API Development]]></category><category><![CDATA[Web API]]></category><dc:creator><![CDATA[Oscar Montenegro]]></dc:creator><pubDate>Tue, 13 Jun 2023 04:29:10 GMT</pubDate><media:content url="https://unitcoding.com/content/images/2023/06/Blue-Memphis-Doctor-Youtube-Banner.png" medium="image"/><content:encoded><![CDATA[<img src="https://unitcoding.com/content/images/2023/06/Blue-Memphis-Doctor-Youtube-Banner.png" alt="Implementing CORS in ASP.NET Core Web API: Enabling Secure Cross-Origin Resource Sharing"><p>In the world of web development, ensuring secure communication between different origins is crucial. Cross-Origin Resource Sharing (CORS) comes to the rescue by allowing controlled access to resources on different domains. In this article, we&apos;ll delve into the realm of CORS, exploring its purpose and benefits. We&apos;ll also guide you through the implementation of CORS in an ASP NET Core Web API, ensuring secure cross-origin interactions.</p><h2 id="what-is-cors">What is CORS?</h2><p>CORS is a feature implemented by web browsers to control how web applications on different domains interact with each other.</p><p>Imagine you have a website on one domain, and you want to access some resources (like data or images) from another website on a different domain. By default, web browsers are a bit cautious about this because they want to protect you from potential security risks. That&apos;s where CORS comes in.</p><p>CORS allows web servers to specify who can access their resources and under what conditions. It acts as a communication channel between the web browser and the server, making sure that it&apos;s safe for your website to access resources from another domain.</p><p>Now, it&apos;s important to note that <strong>CORS is not a complete security solution on its own</strong>. It&apos;s more like a helpful tool that works alongside other security measures. CORS focuses on managing cross-origin requests, which are requests made from one domain to another. It helps prevent certain types of attacks that could exploit the same-origin policy, a security feature in browsers.</p><p>However, CORS doesn&apos;t handle all aspects of security. It doesn&apos;t provide end-to-end security for data transfer or protect against all possible threats. <strong>For a robust security setup, you need to combine CORS with other practices like proper authentication and authorization, input validation, encryption, and following secure coding practices.</strong></p><p>Think of CORS as a friendly bouncer at a party who checks your invitation before allowing you in. It helps control access to resources between different domains, but you still need to make sure you have other security measures in place to throw a safe and secure party.</p><p>So, remember, while CORS is a helpful feature, it&apos;s not the whole security package. It&apos;s part of a bigger picture, and by combining it with other security practices, you can ensure the overall safety of your web application.</p><h2 id="why-should-i-use-cors">Why Should I Use CORS?</h2><p>CORS is essential when you want to allow clients from different domains to access and interact with resources on your web API. By enabling CORS, you can securely expose selected resources to trusted origins, facilitating seamless data exchange between client applications and your API. CORS helps prevent unauthorized cross-origin requests while promoting collaboration and interoperability among web applications.</p><h2 id="enabling-a-cors-in-your-web-app">Enabling a CORS in your Web App</h2><p>To add CORS to your web application you have to call the <code>AddCors</code> method in the services container and define a CORS policy. In the code example below a default policy is added and is set to allow any method and any header from the defined source <code>https://www.example.com</code> in this case, this means that your web application will not allow it to be consumed from any other source.</p><pre><code class="language-csharp">builder.Services.AddCors(options =&gt; 
{
    options.AddDefaultPolicy(builder =&gt;
    {
        builder.WithOrigins(&quot;&lt;https://www.example.com&gt;&quot;)
                .AllowAnyMethod()
                .AllowAnyHeader();
    });
});
</code></pre><p>Now the last piece of the puzzle is to set your app to use CORS in the middleware pipeline as shown below. An important tip is that you must call <code>UseCors</code> after <code>UseRouting</code> and before the <code>UseAuthorization</code> method to work properly.</p><pre><code class="language-csharp">app.UseHttpsRedirection();

app.UseCors();

app.UseAuthorization();

app.UseResponseCaching();

app.MapControllers();

app.Run();
</code></pre><h2 id="default-policies">Default Policies</h2><p>A default policy is like the one defined above, you have to define the default policy within the <code>AddCors</code> method and set the origins, methods, and headers allowed. Then this policy will be applied globally to your application as the name says it&#x2019;s the default policy for your web app.</p><pre><code class="language-csharp">builder.Services.AddCors(options =&gt; 
{
    options.AddDefaultPolicy(builder =&gt;
    {
        builder.WithOrigins(&quot;&lt;https://www.example.com&gt;&quot;)
                .AllowAnyMethod()
                .AllowAnyHeader();
    });
});
</code></pre><h2 id="named-policies">Named Policies</h2><p>Another way to define a CORS policy is through named policies which will not be applied globally to your web app instead you have to enable it using attributes but we will see that in just a bit. The way to define a named policy is pretty similar to a default policy but here you have to call the <code>AddPolicy</code> method instead of the <code>AddDefaultPolicy</code>.</p><pre><code class="language-csharp">builder.Services.AddCors(options =&gt;
{
		options.AddPolicy(&quot;MyNamedPolicy&quot;,policy =&gt;
		    {
		        policy.WithOrigins(&quot;&lt;http://example.com&gt;&quot;,
		                            &quot;&lt;http://www.contoso.com&gt;&quot;);
		        policy.AllowAnyMethod();
		        policy.AllowAnyHeader();
		    });
});
</code></pre><h2 id="enable-cors-using-attributes">Enable CORS using attributes</h2><p>If instead of enforcing CORS for all your application you just want it on a set of specific endpoints or a controller then you can achieve this using the attribute <code>[UseCors]</code>. You can use this attribute on top of your controller or action and a default CORS policy will be implemented but the preferred way is to use the attribute and pass the <code>Policy Name</code> property to implement that CORS policy. And this is the way to implement named policies as they are not implemented globally or by default as the default policy.</p><pre><code class="language-csharp">[HttpGet]
[EnableCors(PolicyName = &quot;MyNamedPolicy&quot;)]
public async Task&lt;IActionResult&gt; GetPost([FromQuery] QueryParameters parameters)
{
	...
}
</code></pre><p>This will implement the named policy <code>MyNamedPolicy</code> in the <code>GetPost</code> action. And you might suspect it but in case you don&#x2019;t, you can implement different CORS policies for different actions and controllers.</p><h2 id="enable-cors-for-subdomains">Enable CORS for Subdomains</h2><p>If you want to enable CORS in all the subdomains from a source you have to call the <code>SetIsOriginAllowedToAllowWildcardSubdomains()</code> method.</p><blockquote>Taken from Microsoft Documentation: &#x201C;<a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.cors.infrastructure.corspolicybuilder.setisoriginallowedtoallowwildcardsubdomains?ref=unitcoding.com">SetIsOriginAllowedToAllowWildcardSubdomains</a>: Sets the <a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.cors.infrastructure.corspolicy.isoriginallowed?ref=unitcoding.com">IsOriginAllowed</a> property of the policy to be a function that allows origins to match a configured wildcard domain when evaluating if the origin is allowed.&#x201D;</blockquote><p>Below is an example of how you would have to implement it.</p><pre><code class="language-csharp">builder.Services.AddCors(options =&gt;
{
    options.AddPolicy(&quot;AllowSubdomainsPolicy&quot;,
        policy =&gt;
        {
            policy.WithOrigins(&quot;https://*.example.com&quot;)
                .SetIsOriginAllowedToAllowWildcardSubdomains();
        });
});
</code></pre><h2 id="specify-methods-on-your-cors-policy">Specify methods on your CORS policy</h2><p>So far we have been using the <code>AllowAnyMethod</code> policy but it won&#x2019;t make much sense to allow external sources to have access to all the method types all the time. For example, imagine you developed a web API and you want full access to your sources so you use the <code>AllowAnyMethod</code> but for external sources, you want to restrict access to <code>PUT</code> and <code>DELETE</code> methods.</p><pre><code class="language-csharp">builder.Services.AddCors(options =&gt; 
{
    options.AddPolicy(&quot;MyDomainsPolicy&quot;,policy =&gt;
    {
        policy.WithOrigins(&quot;&lt;http://mydomain.com&gt;&quot;,
                            &quot;&lt;http://www.mydomain2.com&gt;&quot;);
        policy.AllowAnyMethod();
        policy.AllowAnyHeader();
    });

    options.AddPolicy(&quot;PublicPolicy&quot;,policy =&gt;
    {
        policy.AllowAnyOrigin();
        policy.WithMethods(&quot;GET&quot;, &quot;POST&quot;);
        policy.AllowAnyHeader();
    });
});
</code></pre><h2 id="set-allowed-request-headers">Set allowed Request Headers</h2><p>As with methods you can set what headers your application will accept</p><pre><code class="language-csharp">options.AddPolicy(&quot;PublicPolicy&quot;,policy =&gt;
    {
        policy.AllowAnyOrigin();
        policy.WithMethods(&quot;GET&quot;, &quot;POST&quot;, &quot;PUT&quot;);
        policy.WithHeaders(HeaderNames.Accept, HeaderNames.CacheControl);
    });
</code></pre><h2 id="set-exposed-headers">Set Exposed Headers</h2><p>The browser by default will not expose all response headers. So to make other headers available you should use the <code>WithExposedHeaders</code> method.</p><pre><code class="language-csharp">options.AddPolicy(&quot;PublicPolicy&quot;,policy =&gt;
    {
        policy.AllowAnyOrigin()
              .WithMethods(&quot;GET&quot;, &quot;POST&quot;, &quot;PUT&quot;)
              .WithHeaders(HeaderNames.Accept, HeaderNames.CacheControl)
              .WithExposedHeaders(&quot;x-custom-header&quot;);

    });
</code></pre><p>The only response headers that are available by default are the next:</p><ul><li><code>Cache-Control</code></li><li><code>Content-Language</code></li><li><code>Content-Type</code></li><li><code>Expires</code></li><li><code>Last-Modified</code></li><li><code>Pragma</code></li></ul><h2 id="disable-cors">Disable CORS</h2><p>Finally, if you want to disable CORS from a controller or an action you can use the <code>[DisableCors]</code> attribute to achieve it.</p><pre><code class="language-csharp">[HttpPost]
[DisableCors]
public async Task&lt;IActionResult&gt; CreatePost(AddPostDTO addPostDTO)
{
	...
}
</code></pre><p>It is important to say that DisableCors will not disable CORS that have been enabled using endpoint routing. An example of CORS enabled with endpoint routing is provided below taken from the Microsoft Documentation.</p><pre><code class="language-csharp">app.UseEndpoints(endpoints =&gt;
{
    endpoints.MapGet(&quot;/echo&quot;,
        context =&gt; context.Response.WriteAsync(&quot;echo&quot;))
        .RequireCors(MyAllowSpecificOrigins);

    endpoints.MapControllers()
             .RequireCors(MyAllowSpecificOrigins);

    endpoints.MapGet(&quot;/echo2&quot;,
        context =&gt; context.Response.WriteAsync(&quot;echo2&quot;));

    endpoints.MapRazorPages();
});
</code></pre><h2 id="conclusion">Conclusion</h2><p>Enabling CORS in your ASP.NET Core Web API is a crucial step to ensure secure cross-origin resource sharing. By implementing CORS, you can control and allow access to resources from trusted origins, promoting collaboration and interoperability. Understanding the benefits and drawbacks of CORS will help you make informed decisions while building secure and scalable web applications. Implement CORS in your ASP.NET Core Web API using the provided steps</p><h2 id="follow-me-for-developer-tips-and-clean-code-tips">Follow me for Developer Tips and Clean Code Tips</h2><p>From tomorrow I will start sharing advice for software developers from the experiences I&#x2019;ve lived working in big enterprises as a freelancer, also I will share useful code snippets that can help you write cleaner and more maintainable code for your job or side projects. All this will be on my Twitter page so go and start following me so you don&#x2019;t miss a single tip <a href="https://twitter.com/OscarOsempu?ref=unitcoding.com">@OscarOsempu</a>. We are almost reaching 15k monthly views on <a href="https://unitcoding.com/">Unit Coding</a>, Thanks for being along with me on this exciting journey, to be honest, it was harder than I thought it would be but I&#x2019;ve learned a lot from this experience and I&#x2019;m still developing consistency as I can say it&#x2019;s something I&#x2019;ve never been good at, but your comments and feedback have been there to make me push forward and always bring you some quality content while enjoying the ride, what can I say? I&#x2019;m very blessed to have a community like this, thanks for everything!</p>]]></content:encoded></item><item><title><![CDATA[A Comprehensive Guide to Caching Strategies in Web API Development]]></title><description><![CDATA[Boosting the performance of your Web API is vital for delivering fast and efficient experiences to your users. Learn the fundamentals, discover different caching strategies, and uncover best practices to optimize your API's performance.]]></description><link>https://unitcoding.com/caching-asp-net-core/</link><guid isPermaLink="false">64822550bb0b09c27afc2eb8</guid><category><![CDATA[ASP NET Core]]></category><category><![CDATA[REST API Development]]></category><category><![CDATA[Software Development]]></category><category><![CDATA[Web API]]></category><dc:creator><![CDATA[Oscar Montenegro]]></dc:creator><pubDate>Thu, 08 Jun 2023 19:29:16 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1667308274522-886ce9a3f0cc?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDl8fG1lbW9yeSUyMGNpcmN1aXR8ZW58MHx8fHwxNjg2MjUyMDczfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1667308274522-886ce9a3f0cc?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDl8fG1lbW9yeSUyMGNpcmN1aXR8ZW58MHx8fHwxNjg2MjUyMDczfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="A Comprehensive Guide to Caching Strategies in Web API Development"><p>Welcome to another exciting chapter in this series on Web API Development! If you&apos;ve ever wondered how to make your API lightning-fast and more efficient, caching is one of those steps to take in the right direction to achieve it. In the last chapter, I showed you how to implement HATEOAS in your Web API, it had a great impact when I shared it online as many experienced developers shared their experiences with this component since it has some pros and cons as with everything in life but if you want to take a look at it I will leave the link to the post below. Ok so without further ado let&apos;s get into today&apos;s post.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://unitcoding.com/implementing-hateoas/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Implementing HATEOAS in your ASP NET Core web API: Enhancing API Discoverability and Navigability</div><div class="kg-bookmark-description">As developers, we strive to build robust and user-friendly web APIs that provide a seamless experience for clients. One powerful approach to achieve this is by implementing HATEOAS (Hypermedia as the Engine of Application State) in our ASP.NET Core Web APIs as this provides a handful of benefits for</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://unitcoding.com/content/images/size/w256h256/2023/03/Copy-of-Unit-1.png" alt="A Comprehensive Guide to Caching Strategies in Web API Development"><span class="kg-bookmark-author">Unit Coding</span><span class="kg-bookmark-publisher">Oscar Montenegro</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://unitcoding.com/content/images/2023/06/hateoas_image.png" alt="A Comprehensive Guide to Caching Strategies in Web API Development"></div></a></figure><h2 id="what-is-caching"><strong>What is Caching ?</strong></h2><p>Caching is like having secret storage where you can temporarily store frequently accessed data. Instead of going through the whole process of generating a response from scratch every time, you can retrieve it directly from the cache. It&apos;s like having a shortcut to lightning-fast responses!</p><p>In the context of Web API, caching involves storing API responses, either partially or in their entirety, so that subsequent requests for the same data can be served directly from the cache. This reduces the need for expensive computations or database queries, resulting in improved response times and better performance.</p><h2 id="benefits-of-caching"><strong>Benefits of Caching</strong></h2><p>Caching offers several compelling benefits for your Web API:</p><h3 id="1-lightning-fast-response-times"><strong>1. Lightning-Fast Response Times</strong></h3><p>By serving responses from the cache, you can skip the time-consuming steps of processing and generating a fresh response. This significantly reduces the overall response time, leading to a smoother and more responsive user experience.</p><h3 id="2-reduced-server-load"><strong>2. Reduced Server Load</strong></h3><p>Caching helps offload the work from your server by minimizing the number of requests that need to hit your API endpoints. When a request can be fulfilled from the cache, it eliminates the need for processing and querying the underlying data source. This, in turn, reduces the server load, allowing it to handle more concurrent requests and improving the overall scalability of your API.</p><h3 id="3-improved-scalability"><strong>3. Improved Scalability</strong></h3><p>With caching in place, your Web API becomes more scalable. By reducing the load on your server, caching enables your application to handle increased traffic and accommodate a larger user base without compromising performance. It helps you make the most of your server&apos;s resources and ensure a consistent experience for your users, even during peak usage periods.</p><h2 id="types-of-caching"><strong>Types of Caching</strong></h2><p>There are different types of caching that you can implement in your Web API:</p><h3 id="1-in-memory-caching"><strong>1. In-Memory Caching</strong></h3><p>In-memory caching stores the cached data in the memory of your application. It offers lightning-fast access to the cached data but is limited to a single server instance. This type of caching is suitable for scenarios where the cached data is not critical and can be easily recreated if lost.</p><h3 id="2-distributed-caching"><strong>2. Distributed Caching</strong></h3><p>Distributed caching involves storing the cached data in a shared cache that can be accessed by multiple server instances or even across different machines. This allows for better scalability and resilience, as multiple servers can share the same cache. Distributed caching is commonly used in scenarios where high availability and reliability are required.</p><h3 id="3-client-side-caching"><strong>3. Client-Side Caching</strong></h3><p>Client-side caching involves storing the cached data on the client side, typically in the web browser. This is achieved by setting appropriate caching headers in the API responses. Client-side caching can significantly reduce the number of requests made to the server, as the client can use the cached data for subsequent requests. It improves the overall performance and responsiveness of your API.</p><h2 id="what-is-response-caching"><strong>What is Response Caching?</strong></h2><p>Response caching is a technique that allows you to store the response of an API endpoint and serve it directly from the cache for subsequent requests. Instead of re-computing the response or hitting the database every time, you can leverage response caching to retrieve the data from a cache store. This significantly improves response times, reduces server load, and enhances the overall scalability of your Web API. <strong>This is the technique we will be using in this tutorial.</strong></p><h2 id="the-response-cache-attribute"><strong>The Response Cache Attribute</strong></h2><p>In <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core Web API, response caching is made easy with the <strong><code>[ResponseCache]</code></strong> attribute. By applying this attribute to your controller or action methods, you can control how the response is cached. The <strong><code>[ResponseCache]</code></strong> attribute provides various options to customize caching behavior, such as cache duration, location, and more.</p><p>For example, you can specify the cache duration using the <strong><code>Duration</code></strong> property, like this:</p><pre><code class="language-csharp">[HttpGet]
[ResponseCache(Duration = 60)] // Cache the response for 60 seconds
public IActionResult Get()
{
    // Your code here
}
</code></pre><h2 id="the-response-cache-parameters">The Response Cache Parameters</h2><p>In <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core, the <strong><code>[ResponseCache]</code></strong> attribute gives you different options to control how your API responses are cached. Let&apos;s take a look at these options in a beginner-friendly way:</p><ol><li><strong>Duration</strong>: This parameter lets you specify how long the response should be cached. You can set it to a specific number of seconds using the <strong><code>Duration</code></strong> property. For example, if you set <strong><code>[ResponseCache(Duration = 60)]</code></strong>, the response will be cached for 60 seconds before it needs to be refreshed.</li><li><strong>Location</strong>: This parameter determines where the response can be cached. You have three options:</li></ol><ul><li><strong><code>ResponseCacheLocation.Any</code></strong>: The response can be cached by both client-side browsers and proxy servers.</li><li><strong><code>ResponseCacheLocation.Client</code></strong>: The response can be cached by client-side browsers only.</li><li><strong><code>ResponseCacheLocation.None</code></strong>: The response should not be cached at all.</li></ul><ol><li><strong>VaryByHeader</strong>: Sometimes, you want to cache responses separately based on specific request headers. This parameter allows you to specify the headers that should be considered when deciding if a cached response can be served. For example, if you set <strong><code>[ResponseCache(VaryByHeader = &quot;User-Agent&quot;)]</code></strong>, the response will be cached separately for different user agents.</li><li><strong>VaryByQueryKeys</strong>: Similar to <strong><code>VaryByHeader</code></strong>, this parameter helps you cache responses separately based on specific query string parameters. You can specify the query parameters that should be considered when deciding if a cached response can be served. For example, if you set <strong><code>[ResponseCache(VaryByQueryKeys = new[] { &quot;page&quot;, &quot;pageSize&quot; })]</code></strong>, the response will be cached separately for different values of the <strong><code>page</code></strong> and <strong><code>pageSize</code></strong> query parameters.</li><li><strong>NoStore</strong>: This parameter determines whether the response should be stored in the cache at all. Setting <strong><code>NoStore</code></strong> to <strong><code>true</code></strong> ensures that the response is not cached.</li></ol><p>These response cache parameters give you control over how your API responses are cached. By using them, you can specify the caching duration, where the response can be cached, and even cache responses differently based on headers or query parameters. It&apos;s a powerful way to optimize your API&apos;s performance and reduce server load.</p><h2 id="response-caching-middleware"><strong>Response Caching Middleware</strong></h2><p>ASP NET Core also provides a built-in response caching middleware that you can add to your API pipeline. The response caching middleware intercepts incoming requests and checks if a cached response exists. If a cached response is found, it&apos;s served directly, bypassing the entire request pipeline. This saves processing time and improves the API&apos;s responsiveness.</p><p>To enable response caching middleware, you can add the following code to your <strong><code>Program.cs</code></strong> file:</p><pre><code class="language-csharp">builder.Services.AddControllers();
builder.Services.AddResponseCaching();
...
app.MapControllers();
app.UseResponseCaching();

app.Run();
</code></pre><h2 id="cache-profiles"><strong>Cache Profiles</strong></h2><p>Cache profiles allow you to define caching behavior in a centralized and reusable manner. Instead of repeating the same caching settings for multiple actions, you can define a cache profile and apply it across different endpoints. This promotes consistency and simplifies cache management.</p><p>To configure cache profiles, you can add the following code to your <strong><code>Program.cs</code></strong> file:</p><pre><code class="language-csharp">builder.Services.AddControllers(options =&gt;
{
    options.CacheProfiles.Add(&quot;DefaultCache&quot;,
	      new CacheProfile()
	      {
	          Duration = 60,
	          Location =  ResponseCacheLocation.Any,
              VaryByQueryKeys = new[] { &quot;page&quot;, &quot;pageSize&quot; } 
              // Vary the cache by these query parameters
	      });
	});
</code></pre><p>In the code snippet above, we&apos;ve defined a cache profile named &quot;DefaultCache&quot; It has a duration of 60 seconds, meaning that the response will be cached for that period. We&apos;ve also allowed caching from any location, which means both client-side browsers and proxy servers can cache the response. Additionally, we&apos;ve specified that the cache should vary based on the &quot;page&quot; and &quot;pageSize&quot; query parameters. Feel free to adjust these settings based on your specific needs.</p><p>Once the cache profile is defined, you can apply it to your API endpoints. Let&apos;s say you have a controller with an action method you want to cache. Simply add the <strong><code>[ResponseCache]</code></strong> attribute to that action method and specify the cache profile name:</p><pre><code class="language-csharp">[HttpGet]
[ResponseCache(CacheProfileName = &quot;DefaultCache&quot;)]
public IActionResult GetData(int page, int pageSize)
{
    // Your code here
}
</code></pre><p>By setting <strong><code>CacheProfileName</code></strong> to &quot;DefaultCache,&quot; you&apos;re instructing <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core to apply the caching settings defined in the &quot;DefaultCache&quot; cache profile to this specific action method. You can reuse the same cache profile across multiple endpoints to maintain consistent caching behavior.</p><p>Using cache profiles in <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core 7 simplifies the management of caching settings, making it easier to update or modify caching behavior in the future. It centralizes your caching rules, improving code readability and maintainability.</p><h3 id="defining-cache-profiles-in-the-appsettingsjson-file">Defining Cache Profiles in the appsettings.json file</h3><p>To define a cache profile in the <strong><code>appsettings.json</code></strong> file and use it in your <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core application, follow these steps:</p><ol><li>Open your <strong><code>appsettings.json</code></strong> file and add a new section for cache profiles. Here&apos;s an example of how it might look:</li></ol><figure class="kg-card kg-code-card"><pre><code class="language-json">{
  &quot;CacheProfiles&quot;: {
    &quot;DefaultCache&quot;: {
      &quot;Duration&quot;: 60,
      &quot;Location&quot;: &quot;Any&quot;,
      &quot;VaryByQueryKeys&quot;: [ &quot;page&quot;, &quot;pageSize&quot; ]
    },
    &quot;CustomProfile&quot;: {
      &quot;Duration&quot;: 120,
      &quot;Location&quot;: &quot;Client&quot;,
      &quot;VaryByHeader&quot;: [ &quot;User-Agent&quot; ]
    }
  }
}
</code></pre><figcaption>JSON</figcaption></figure><p>In your <strong><code>Program.cs</code></strong> file, register your cache profiles defined in the <code>appsettings.json</code> file as shown below:</p><pre><code class="language-csharp">builder.Services.AddControllers(options =&gt;
{
    var cacheProfiles = builder.Configuration
            .GetSection(&quot;CacheProfiles&quot;)
            .GetChildren();

    foreach (var cacheProfile in cacheProfiles)
    {
        options.CacheProfiles
        .Add(cacheProfile.Key, 
        cacheProfile.Get&lt;CacheProfile&gt;());
    }
});
</code></pre><p>Now, you can use the cache profiles in your API endpoints. For example, let&apos;s assume you have an action method in your controller that you want to cache using the &quot;DefaultCache&quot; cache profile. Add the <strong><code>[ResponseCache]</code></strong> attribute and specify the cache profile name:</p><pre><code class="language-csharp">[HttpGet]
[ResponseCache(CacheProfileName = &quot;DefaultCache&quot;)]
public IActionResult GetData(int page, int pageSize)
{
    // Your code here
}
</code></pre><ol><li>By setting <strong><code>CacheProfileName</code></strong> to &quot;DefaultCache,&quot; the caching settings defined in the &quot;DefaultCache&quot; cache profile will be applied to this action method.</li></ol><p>That&apos;s it! You&apos;ve defined cache profiles in the <strong><code>appsettings.json</code></strong> file and used them in your <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core application. This approach allows you to configure cache profiles externally, making it easier to modify caching behavior without modifying code.</p><h2 id="get-the-code-repo-from-github">Get the code repo from GitHub</h2><p>If you want to follow along get the code from GitHub and make sure you get the code from the HATEOAS branch which contains the code changes up to this tutorial.</p><h2 id="implementing-response-caching-in-your-web-api">Implementing Response Caching in your Web API</h2><p>First, add the response caching in the services container and the response cache middleware so the code in the <code>Program</code> file should look like this:</p><pre><code class="language-csharp">builder.Services.AddResponseCaching();
builder.Services.AddControllers()
                .AddNewtonsoftJson(options =&gt;
                {
                    options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                    options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
                });
...
app.UseResponseCaching();

app.MapControllers();

app.Run();
</code></pre><p>You can add the response caching above or below the controllers and the response caching should be above the <code>MapControllers()</code>.</p><h2 id="add-a-response-cache-attribute-to-the-get-endpoints">Add a Response Cache attribute to the Get Endpoints</h2><pre><code class="language-csharp">[HttpGet]
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Any, VaryByQueryKeys = new []{&quot;*&quot;})]
public async Task&lt;IActionResult&gt; GetPost([FromQuery] QueryParameters parameters)
{
	...
}

[HttpGet(&quot;{id:int}&quot;)]
[PostExists]
[ResponseCache(Duration = 60, VaryByQueryKeys = new []{&quot;*&quot;})]
public async Task&lt;IActionResult&gt; GetPost(int id)
{
	...
}
</code></pre><p>For the <code>GetPost</code> endpoint, a duration of 60 seconds is set for the response lifetime, the location for the response cache is set to any, which means that both the server and the client will cache the response and lastly, there is a <code>VaryByQuerykeys</code> parameter that we set to update the cache every time that a query string is changed as this method uses pagination, sorting and filtering there will be many cases where the query strings change.</p><p>For the <code>GetPost(id)</code> method a duration of 60 seconds is set as well and the <code>VaryByQueryKeys</code> parameter is initialized as we did for the <code>GetPost</code> method.</p><h2 id="testing-your-application">Testing your application</h2><p>Now you are ready to test your application, using a tool like Postman make a call to any of these endpoints and check the response headers, there you will see the <code>Cache-Control</code> header which contains the max-age value that indicates how long the cached response will last in this case it is 60 seconds for any of the endpoints. If this is the first time you call the endpoint you will only be able to see the <code>Cache-Control</code> header but if you call the same endpoint again there will be another header named <code>Age</code> this header contains the age in seconds of the cached response as you are getting the same response if you did not change any query string parameter then you should be getting a cached response this means a previously stored response to save some resources on your application.</p><figure class="kg-card kg-image-card"><img src="https://unitcoding.com/content/images/2023/06/caching2.png" class="kg-image" alt="A Comprehensive Guide to Caching Strategies in Web API Development" loading="lazy" width="1755" height="730" srcset="https://unitcoding.com/content/images/size/w600/2023/06/caching2.png 600w, https://unitcoding.com/content/images/size/w1000/2023/06/caching2.png 1000w, https://unitcoding.com/content/images/size/w1600/2023/06/caching2.png 1600w, https://unitcoding.com/content/images/2023/06/caching2.png 1755w" sizes="(min-width: 720px) 720px"></figure><h2 id="conclusion"><strong>Conclusion</strong></h2><p>Caching is a powerful technique that can greatly enhance the performance and scalability of your Web API. By leveraging caching, you can achieve lightning-fast response times, reduce server load, and improve the overall user experience. Whether you choose in-memory caching, distributed caching, or client-side caching depends on your specific requirements and the nature of your application.</p><p>So, don&apos;t wait any longer! Implement caching in your Web API and witness the transformation in performance. Your users will thank you for the lightning-fast responses and smooth user experience.</p><p>Happy caching!</p><h3 id="share-this-article-with-our-brand-new-sharing-buttons">Share this article with our brand-new sharing buttons!</h3><p>This week I worked on some stuff in the blog for example now you can share this article on your favorite social media platform. Also as we achieved more than 10K views this month I&#x2019;m planning on the future of this blog as well with the YouTube channel I want to start more series and create resources that help you on your learning Journey but I will talk about that later. Thanks for everything I hope you have an amazing day!</p>]]></content:encoded></item><item><title><![CDATA[Implementing HATEOAS in your ASP NET Core web API: Enhancing API Discoverability and Navigability]]></title><description><![CDATA[<p>As developers, we strive to build robust and user-friendly web APIs that provide a seamless experience for clients. One powerful approach to achieve this is by implementing HATEOAS (Hypermedia as the Engine of Application State) in our <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core Web APIs as this provides a handful of benefits for</p>]]></description><link>https://unitcoding.com/implementing-hateoas/</link><guid isPermaLink="false">6478ca696358ae04c7ec3b50</guid><category><![CDATA[ASP NET Core]]></category><category><![CDATA[REST API Development]]></category><category><![CDATA[Software Development]]></category><category><![CDATA[Web API]]></category><dc:creator><![CDATA[Oscar Montenegro]]></dc:creator><pubDate>Thu, 01 Jun 2023 16:51:03 GMT</pubDate><media:content url="https://unitcoding.com/content/images/2023/06/hateoas_image.png" medium="image"/><content:encoded><![CDATA[<img src="https://unitcoding.com/content/images/2023/06/hateoas_image.png" alt="Implementing HATEOAS in your ASP NET Core web API: Enhancing API Discoverability and Navigability"><p>As developers, we strive to build robust and user-friendly web APIs that provide a seamless experience for clients. One powerful approach to achieve this is by implementing HATEOAS (Hypermedia as the Engine of Application State) in our <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core Web APIs as this provides a handful of benefits for the client that you will see in just a bit. In the last post, we talked about exposing related entities with Entity Framework Core in our web API and how to avoid some known problems with nested entities so I will leave you the link for that post below. Now let&#x2019;s get into today&#x2019;s topic, implementing HATEOAS.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://unitcoding.com/exposing-related-entitites/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Exposing Related Entities in your Web API</div><div class="kg-bookmark-description">When working on building a powerful API you will find yourself dealing with resources and more resources and these &#x201C;resources&#x201D; have &#x201C;relations&#x201D; between them and this is powerful as we can leverage the power of relational data to create amazing ways of displaying information or use it. But if you</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://unitcoding.com/content/images/size/w256h256/2023/03/Copy-of-Unit-1.png" alt="Implementing HATEOAS in your ASP NET Core web API: Enhancing API Discoverability and Navigability"><span class="kg-bookmark-author">Unit Coding</span><span class="kg-bookmark-publisher">Oscar Montenegro</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://unitcoding.com/content/images/2023/05/post_image.png" alt="Implementing HATEOAS in your ASP NET Core web API: Enhancing API Discoverability and Navigability"></div></a></figure><h2 id="overview-of-hateoas-and-its-significance-in-web-apis"><strong>Overview of HATEOAS and its Significance in web APIs </strong></h2><p>HATEOAS is an architectural principle that emphasizes the use of hypermedia links to drive the interaction between clients and APIs. It enables us to create self-describing APIs where clients can dynamically discover available resources and navigate through them using standardized links. By providing hypermedia-driven responses, we enhance the discoverability and navigability of our APIs, making them more intuitive and easier to consume.</p><h2 id="benefits-of-using-hateoas-in-asp-net-core-web-apis"><strong>Benefits of using HATEOAS in ASP NET Core Web APIs </strong></h2><p>Implementing HATEOAS in our ASP NET Core Web APIs brings several benefits that greatly improve the user experience and API design:</p><ol><li><strong>Improved Discoverability</strong>: HATEOAS enables the automatic discovery of resources and endpoints within an API. By including hypermedia links in API responses, clients can dynamically navigate through the available resources without the need for prior knowledge of the API structure. This improves the discoverability of the API and reduces the learning curve for developers integrating with it.</li><li><strong>Enhanced Navigability</strong>: With HATEOAS, clients can seamlessly navigate through related resources by following hypermedia links. This eliminates the need for hard-coded dependencies on specific endpoints and allows for flexible exploration of the API. Clients can traverse from one resource to another, making the API more dynamic and adaptable to changes over time.</li><li><strong>Flexible API Evolution</strong>: HATEOAS promotes a decoupled architecture between clients and servers. By using hypermedia links to represent relationships between resources, the API design becomes more flexible and allows for gradual changes without breaking existing client applications. It enables versioning and evolution of the API without requiring clients to update their code every time the API changes.</li><li><strong>Simplified Integration</strong>: HATEOAS reduces the complexity of integrating with an API by providing a standardized way to interact with resources. Clients can rely on the hypermedia links to understand the available actions and the next steps to take. This simplifies the integration process and promotes interoperability between different clients and servers.</li><li><strong>Improved User Experience</strong>: By leveraging HATEOAS, we can create more intuitive and user-friendly APIs. Clients can follow a consistent navigation pattern based on the hypermedia links provided in the responses. This reduces the cognitive load on developers and makes it easier to understand and interact with the API, resulting in a better user experience.</li></ol><h2 id="definition-and-core-principles-of-hateoas"><strong>Definition and core principles of HATEOAS </strong></h2><p>HATEOAS revolves around the concept of including hypermedia links in API responses. These links provide additional information and context to clients, allowing them to navigate through the API and discover related resources. By adhering to the core principles of HATEOAS, we create APIs that are self-describing, decoupled, and highly adaptable.</p><h2 id="how-hateoas-enhances-the-discoverability-and-navigability-of-apis"><strong>How HATEOAS enhances the discoverability and navigability of APIs </strong></h2><p>One of the key advantages of HATEOAS is its ability to enhance the discoverability of APIs. By including hypermedia links in our responses, we guide clients to explore available resources, eliminating the need for prior knowledge of the API structure. This makes our APIs more intuitive and reduces the learning curve for developers who integrate with our API.</p><p>Moreover, HATEOAS promotes navigability within the API. Clients can effortlessly traverse through related resources by following the hypermedia links, creating a dynamic and flexible experience. This eliminates the hard-coded dependencies on specific endpoints and allows for seamless API evolution and versioning.</p><h2 id="role-of-hypermedia-in-hateoas"><strong>Role of hypermedia in HATEOAS </strong></h2><p>Hypermedia plays a central role in HATEOAS by providing the means to represent and navigate resources. Hypermedia formats such as HAL (Hypertext Application Language) and JSON-LD (JSON Linked Data) provide standardized ways to include links and other metadata in API responses. By leveraging these hypermedia formats, we can ensure consistency and interoperability across different clients and APIs.</p><p>Hypermedia links can be used to indicate available actions, suggest related resources, or provide contextual information. They enable clients to follow a uniform navigation pattern, reducing the coupling between client and server and promoting a more flexible and adaptive API design.</p><h2 id="get-the-code-from-github">Get the code from GitHub </h2><p>Before starting to code I recommend if you want to follow along then go and grab the code from the GitHub repository and make sure you get the code from the &#x201C;RelatedEntities&#x201D; branch.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Osempu/BlogAPI/tree/RelatedEntities?ref=unitcoding.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - Osempu/BlogAPI at RelatedEntities</div><div class="kg-bookmark-description">Contribute to Osempu/BlogAPI development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Implementing HATEOAS in your ASP NET Core web API: Enhancing API Discoverability and Navigability"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">Osempu</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/1b5d888713539a0904a95ec49a4cb579fdc2c061ec5da8bfb26a1a0c4d889f5b/Osempu/BlogAPI" alt="Implementing HATEOAS in your ASP NET Core web API: Enhancing API Discoverability and Navigability"></div></a></figure><h2 id="install-the-riskfirsthateoas-nuget-package">Install the RiskFirst.Hateoas nuget package </h2><p>To implement HATEOAS in your project first you will need to install the RiskFirst nuget package using the following dotnet cli command.</p><p><code>dotnet add package RiskFirst.Hateoas</code></p><h2 id="add-a-hateoas-response-model">Add a Hateoas Response Model </h2><p>Now add a new kind of response model for your main entity in this case the Post model that will be called <code>PostHateoasResponse</code>.</p><pre><code class="language-csharp">public class PostHateoasResponse : ILinkContainer
{
    public PostResponseDTO Data;
    private Dictionary&lt;string, Link&gt; links;

    [JsonPropertyName(&quot;links&quot;)]
    public Dictionary&lt;string, Link&gt; Links 
    { 
        get =&gt; links ?? (links = new Dictionary&lt;string, Link&gt;());
        set =&gt; links = value;
    }

    public void AddLink(string id, Link link)
    {
        Links.Add(id, link);
    }
}
</code></pre><p>This class represent the HATEOAS response for the post model and is implementing the <code>ILinkContainer</code> interface exposed by the <code>RiskFirst.Hateoas</code> package. The response model contains a <code>Dictionary&lt;string, Link&gt;</code> that contains the URLs to the methods (GET, POST, DELETE, PUT, PATCH). The <code>AddLink</code> method will just add new links to the links dictionary.</p><h2 id="implementing-hateoas-in-a-new-controller">Implementing HATEOAS in a new Controller </h2><p>To implement HATEOAS you can do it in your main controller but in this case we will create a new PostsController where you will be able to get the HATEOAS responses.</p><pre><code class="language-csharp">[ApiController]
[Route(&quot;api/hateoas/posts&quot;)]
public class PostsHateoasController : ControllerBase
{
    private readonly ILinksService linksService;
    private readonly IPostRepository postRepository;
    private readonly IMapper mapper;

    public PostsHateoasController(ILinksService linksService, IPostRepository postRepository, IMapper mapper)
    {
        this.linksService = linksService;
        this.postRepository = postRepository;
        this.mapper = mapper;
    }

    [HttpGet(Name = nameof(Get))]
    public async Task&lt;IActionResult&gt; Get([FromQuery] QueryParameters parameters)
    {
        var posts = await postRepository.GetPostAsync(parameters);
        var postsDto = mapper.Map&lt;IEnumerable&lt;PostResponseDTO&gt;&gt;(posts);

        var hateoasResults = new List&lt;PostHateoasResponse&gt;();

        foreach (var post in postsDto)
        {
            var hateoasResult = new PostHateoasResponse { Data = post};
            await linksService.AddLinksAsync(hateoasResult);
            hateoasResults.Add(hateoasResult);
        }

        return Ok(hateoasResults);
    }

    [HttpGet(&quot;{id:int}&quot;, Name = nameof(GetById))]
    public async Task&lt;IActionResult&gt; GetById(int id)
    {
        var post = await postRepository.GetPostAsync(id);
        var postDto = mapper.Map&lt;PostResponseDTO&gt;(post);

        var hateoasResult = new PostHateoasResponse{Data = postDto};
        await linksService.AddLinksAsync(hateoasResult);

        return Ok(hateoasResult);
    }

    [HttpPost(Name = nameof(Post))]
    public async Task&lt;IActionResult&gt; Post(AddPostDTO addPostDTO)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest();
        }

        var newPost = mapper.Map&lt;AddPostDTO, Post&gt;(addPostDTO);
        newPost.CreatedDate = DateTime.Now;
        await postRepository.AddAsync(newPost);
        return CreatedAtAction(nameof(Get), new { id = newPost.Id }, null);
    }

    [HttpPut(&quot;{id:int}&quot;, Name = nameof(Edit))]
    public async Task&lt;IActionResult&gt; Edit(int id, [FromBody] EditPostDTO editPostDto)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest();
        }

        var post = mapper.Map&lt;EditPostDTO, Post&gt;(editPostDto);

        post.LastUpdated = DateTime.Now;
        await postRepository.EditAsync(post);
	      return NoContent();
    }

    [HttpDelete(&quot;{id:int}&quot;, Name = nameof(Delete))]
    public async Task&lt;IActionResult&gt; Delete(int id)
    {
        await postRepository.DeleteAsync(id);
        return NoContent();
    }

    [HttpPatch(&quot;{id:int}&quot;, Name = nameof(Patch))]
    public async Task&lt;ActionResult&gt; Patch(int id, [FromBody] JsonPatchDocument&lt;Post&gt; doc)
    {
        var post = await postRepository.GetPostAsync(id);

        doc.ApplyTo(post);
        await postRepository.EditAsync(post);

        return NoContent();
    }
}
</code></pre><p>First, define the route attribute as <code>[Route(&quot;api/hateoas/posts&quot;)]</code> then in the constructor add a dependency to the <code>ILinksService</code> interface to create the links. Above every controller in the method attribute, you will have to add the name of the method to be able to call it from the services contained in the program class later. All the methods remain the same but for the Get methods for example in the Get method a list of <code>PostHateoasResponse</code> is created to populate it with a foreach loop that takes every <code>PostResponseDto</code> and creates the links for every method and finally adds that response to the <code>List&lt;PostHateoasResponse&gt;</code> and return that list. For the GetById method, it&#x2019;s the same process but no foreach loop is needed as you will only create the links for a single resource and then return it.</p><h2 id="register-the-links-service-in-the-program-class">Register the Links Service in the program class </h2><p>Finally to set up the HATEOAS implementation you will have to register the <code>LinksService</code> in the services container as shown below.</p><pre><code class="language-csharp">builder.Services.AddLinks(config =&gt;
{
    config.AddPolicy&lt;PostHateoasResponse&gt;(policy =&gt;
    {
        policy
            .RequireRoutedLink(nameof(PostsHateoasController.Get), nameof(PostsHateoasController.Get))
            .RequireRoutedLink(nameof(PostsHateoasController.GetById), nameof(PostsHateoasController.GetById), _ =&gt; new {id = _.Data.Id})
            .RequireRoutedLink(nameof(PostsHateoasController.Edit), nameof(PostsHateoasController.Edit), x =&gt; new {id = x.Data.Id})
            .RequireRoutedLink(nameof(PostsHateoasController.Delete), nameof(PostsHateoasController.Delete), x =&gt; new {id = x.Data.Id})
            .RequireRoutedLink(nameof(PostsHateoasController.Patch), nameof(PostsHateoasController.Patch), x =&gt; new {id = x.Data.Id});
    });
});
</code></pre><p>Here you need to call a <code>RequiredRoutedLink</code> for every endpoint in your controller in this case we are supporting GET, GET(id), POST, PUT, DELETE &amp; PATCH.</p><h2 id="test-your-web-api-and-inspect-the-new-response">Test your web API and inspect the new Response </h2><p>Now you are ready to go and take your API for a test and you will be able to see the changes right away on the Get and Get(id) methods as these are the only two methods that actually return something different to a <code>NoContent</code> response as the other three methods.</p><h2 id="get-post-hateoas-response">Get Post HATEOAS Response </h2><p>Here you can appreciate the response for a single post, the Get all posts will return a much much larger response and to save some space I will not post an example as you can figure out how it will look or you can run your own test.</p><pre><code class="language-json">{
  &quot;data&quot;: {
    &quot;id&quot;: 13,
    &quot;title&quot;: &quot;Github Basics&quot;,
    &quot;body&quot;: &quot;New Body&quot;,
    &quot;createdDate&quot;: &quot;0001-01-01T00:00:00&quot;,
    &quot;author&quot;: {
      &quot;id&quot;: 5,
      &quot;name&quot;: &quot;Oscar Montenegro&quot;
    },
    &quot;tags&quot;: [
      {
        &quot;id&quot;: 1,
        &quot;name&quot;: &quot;My first Tag&quot;,
        &quot;description&quot;: &quot;This is the first Tag&quot;
      },
      {
        &quot;id&quot;: 2,
        &quot;name&quot;: &quot;Programming&quot;,
        &quot;description&quot;: &quot;Topics related to programming&quot;
      },
      {
        &quot;id&quot;: 4,
        &quot;name&quot;: &quot;DevOps&quot;,
        &quot;description&quot;: &quot;Learn the latest DevOps trends and news&quot;
      }
    ]
  },
  &quot;links&quot;: {
    &quot;Get&quot;: {
      &quot;rel&quot;: &quot;PostsHateoas/Get&quot;,
      &quot;href&quot;: &quot;&lt;http://localhost:5049/api/hateoas/posts&gt;&quot;,
      &quot;method&quot;: &quot;GET&quot;
    },
    &quot;GetById&quot;: {
      &quot;rel&quot;: &quot;PostsHateoas/GetById&quot;,
      &quot;href&quot;: &quot;&lt;http://localhost:5049/api/hateoas/posts/13&gt;&quot;,
      &quot;method&quot;: &quot;GET&quot;
    },
    &quot;Edit&quot;: {
      &quot;rel&quot;: &quot;PostsHateoas/Edit&quot;,
      &quot;href&quot;: &quot;&lt;http://localhost:5049/api/hateoas/posts/13&gt;&quot;,
      &quot;method&quot;: &quot;PUT&quot;
    },
    &quot;Delete&quot;: {
      &quot;rel&quot;: &quot;PostsHateoas/Delete&quot;,
      &quot;href&quot;: &quot;&lt;http://localhost:5049/api/hateoas/posts/13&gt;&quot;,
      &quot;method&quot;: &quot;DELETE&quot;
    },
    &quot;Patch&quot;: {
      &quot;rel&quot;: &quot;PostsHateoas/Patch&quot;,
      &quot;href&quot;: &quot;&lt;http://localhost:5049/api/hateoas/posts/13&gt;&quot;,
      &quot;method&quot;: &quot;PATCH&quot;
    }
  }
}
</code></pre><h2 id="conclusion"><strong>Conclusion </strong></h2><p>Implementing HATEOAS in our ASP NET Core Web APIs unlocks a wealth of benefits, including improved discoverability, enhanced navigability, and a more intuitive client experience. By embracing the principles of HATEOAS and leveraging hypermedia links, we empower clients to dynamically explore and interact with our APIs.</p><p>As you continue to develop your ASP NET Core Web APIs, consider incorporating HATEOAS to create more robust and user-friendly interfaces. By embracing this architectural principle, you&apos;ll be able to build APIs that provide seamless navigation, decoupled interactions, and a more adaptable design.</p><h2 id="almost-hitting-5k-monthly-views">Almost Hitting 5K monthly views</h2><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://unitcoding.com/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Unit Coding</div><div class="kg-bookmark-description">Learn software development creating fun &amp; amazing projects and get professional developers advice on life and work.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://unitcoding.com/content/images/size/w256h256/2023/03/Copy-of-Unit-1.png" alt="Implementing HATEOAS in your ASP NET Core web API: Enhancing API Discoverability and Navigability"><span class="kg-bookmark-author">Unit Coding</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://unitcoding.com/content/images/2023/03/Untitled-design.png" alt="Implementing HATEOAS in your ASP NET Core web API: Enhancing API Discoverability and Navigability"></div></a></figure><p>I can&#x2019;t hide my happiness as this has been an amazing week full of work, reaching milestones, and planning new content for your guys I enjoy to be constantly learning something new to share with this beautiful community. I can&#x2019;t help but thank you all for your support this helps me to create even more amazing and quality content for you as I know you have been enjoying reading this series and we are reaching the end of it, I&#x2019;m so excited to create a grand finale and to continue with more great content. Please help me sharing this on your networks and with other fellow developers that are still learning or that have time developing but that you think they will get value from reading this articles. Thank you guys for everything, have a great day and happy coding!</p>]]></content:encoded></item><item><title><![CDATA[Exposing Related Entities in your Web API]]></title><description><![CDATA[<p>When working on building a powerful API you will find yourself dealing with resources and more resources and these &#x201C;resources&#x201D; have &#x201C;relations&#x201D; between them and this is powerful as we can leverage the power of relational data to create amazing ways of displaying information or use</p>]]></description><link>https://unitcoding.com/exposing-related-entitites/</link><guid isPermaLink="false">647773b76358ae04c7ec3b32</guid><category><![CDATA[ASP NET Core]]></category><category><![CDATA[Entity Framework]]></category><category><![CDATA[REST API Development]]></category><category><![CDATA[Web API]]></category><category><![CDATA[Software Development]]></category><dc:creator><![CDATA[Oscar Montenegro]]></dc:creator><pubDate>Wed, 31 May 2023 16:30:43 GMT</pubDate><media:content url="https://unitcoding.com/content/images/2023/05/post_image.png" medium="image"/><content:encoded><![CDATA[<img src="https://unitcoding.com/content/images/2023/05/post_image.png" alt="Exposing Related Entities in your Web API"><p>When working on building a powerful API you will find yourself dealing with resources and more resources and these &#x201C;resources&#x201D; have &#x201C;relations&#x201D; between them and this is powerful as we can leverage the power of relational data to create amazing ways of displaying information or use it. But if you don&#x2019;t really understand how to define this relationship as I showed you in my last article about Relationships in Entity Framework Core or you don&#x2019;t know how to make them work together as you will see later in this post, then it can be a nightmare to work with primary keys, constraints, LINQ, etc. &#x1F630;</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://unitcoding.com/ef-core-relationships/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Relationships in Entity Framework Core</div><div class="kg-bookmark-description">Hello guys, welcome to yet another exciting chapter of this series on developing a web API with ASP NET Core. Today we will move on to an advanced topic &#x201C;Relationships on entity framework core&#x201D; We will create more models that are a vital part of a blog, for example, authors</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://unitcoding.com/content/images/size/w256h256/2023/03/Copy-of-Unit-1.png" alt="Exposing Related Entities in your Web API"><span class="kg-bookmark-author">Unit Coding</span><span class="kg-bookmark-publisher">Oscar Montenegro</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://unitcoding.com/content/images/2023/05/relationships-1.png" alt="Exposing Related Entities in your Web API"></div></a></figure><p>So for that reason, it&#x2019;s a necessary skill to know how to expose and represent the related entities from your web API resources. This article will teach you how to achieve that while building meaningful endpoints to get the required resources.</p><h2 id="what-are-related-entities">What are related Entities ?</h2><p>Related entities refer to interconnected entities or objects within a data model. In the context of databases and ORMs (Object-Relational Mapping) like Entity Framework Core, related entities represent the associations and relationships between different tables or entities in a database schema.</p><p>These relationships come in different flavors, such as one-to-one, one-to-many, or many-to-many. They basically tell us how the pieces fit together. For example, in a blog application, a post may have one author (one-to-one), or an author can have multiple posts (one-to-many). These relationships bring structure and meaning to our data.</p><p>Understanding these relationships is like unlocking the secrets of your data model. It allows you to create more complex and intertwined models, giving you the power to fetch and manipulate related data effortlessly. You can easily access information from different entities, perform queries, and build powerful applications.</p><p>To sum it up, related entities are the links between data pieces in your database. They give your data model its structure and define how the different parts work together. With a good grasp of these relationships, you can navigate through your data, create efficient queries, and build amazing applications.</p><h2 id="how-to-expose-related-entities">How to expose related Entities ?</h2><p>Exposing related entities in <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core Web API involves making those connections accessible and retrievable to clients who interact with your API. By exposing related entities, you allow clients to access and manipulate interconnected data in a meaningful way.</p><p>There are several approaches you can take to achieve this:</p><ol><li><strong>Nested Serialization</strong>: One way is to include related entities as nested objects within the JSON response. For example, when retrieving a blog post, you can also include the author information as part of the response, making it easy for clients to access both the post and its author in a single request.</li><li><strong>Expandable Endpoints</strong>: Another approach is to provide expandable endpoints, where clients can specify which related entities they want to include in the response. This gives clients more control over the data they receive, reducing unnecessary data transfer and improving performance.</li><li><strong>Hypermedia Links</strong>: Hypermedia-driven APIs use links to represent relationships between entities. By including links in your API responses, clients can navigate through related entities by following these links. This approach provides a more dynamic and flexible way to expose related entities.</li><li><strong>Custom Endpoints</strong>: Depending on your application&apos;s requirements, you can create custom endpoints specifically designed to retrieve related entities. For example, you might have an endpoint that returns all the comments associated with a blog post or all the products in a specific category.</li></ol><p>When exposing related entities, it&apos;s essential to consider factors like performance, data size, and security. You want to strike a balance between providing enough related data for clients to work with and avoiding excessive data transfer that could impact performance.</p><p>In this article, we will end up using a mix of those approaches to return the client all the resources needed.</p><h2 id="get-the-code-from-github">Get the code from GitHub </h2><p>As always before we get into the code if you want to follow along with this tutorial make sure you get the code from the GitHub repository and double-check that you are getting the code from the &#x201C;EfCoreRelationship&#x201D; branch.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Osempu/BlogAPI/tree/EfCoreRelationships?ref=unitcoding.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - Osempu/BlogAPI at EfCoreRelationships</div><div class="kg-bookmark-description">Contribute to Osempu/BlogAPI development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Exposing Related Entities in your Web API"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">Osempu</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/1b5d888713539a0904a95ec49a4cb579fdc2c061ec5da8bfb26a1a0c4d889f5b/Osempu/BlogAPI" alt="Exposing Related Entities in your Web API"></div></a></figure><h2 id="updating-the-postrepository-class">Updating the PostRepository class </h2><p>The <code>PostRepository</code> class has been retrieving the posts from the database but it lacks power as it is not returning the author for every repository only the <code>authorId</code> and neither is returning the <code>tags</code> that the <code>Post</code> has so for that reason we will extend the functionality of the repository class updating its methods and adding two new methods.</p><h2 id="irepository-class-updated">IRepository class updated </h2><pre><code class="language-csharp">public interface IPostRepository 
{
    Task&lt;IEnumerable&lt;Post&gt;&gt; GetPostAsync(QueryParameters parameters);
    Task&lt;Post&gt; GetPostAsync(int id);
    Task&lt;IEnumerable&lt;Post&gt;&gt; GetPostByAuthorId(int id);
    Task&lt;IEnumerable&lt;Post&gt;&gt; GetPostByTagId(int id);
    Task AddAsync(Post post);
    Task EditAsync(Post post);
    Task DeleteAsync(int id);
}
</code></pre><p>As you can see there are two new methods <code>GetPostByAuthorId</code> and <code>GetPostByTagId</code> this is to retrieve all the posts from the user and all the posts related to a specific tag which is the normal filter functionality of any existing blog.</p><h2 id="postrepository-class">PostRepository Class </h2><pre><code class="language-csharp">public async Task&lt;IEnumerable&lt;Post&gt;&gt; GetPostAsync(QueryParameters parameters)
{
		//Code ommited for brevity
    var pagedPosts = await allPosts
            .Skip((parameters.PageNumber - 1) * parameters.PageSize)
            .Take(parameters.PageSize)
            .Include(x =&gt; x.Author)
            .Include(x =&gt; x.Tags)
            .ToListAsync();

    return pagedPosts;
}

public async Task&lt;Post&gt; GetPostAsync(int id)
{
    var post = await context.Posts.AsNoTracking()
                                    .Where(x =&gt; x.Id == id)
                                    .Include(x =&gt; x.Author)
                                    .Include(x =&gt; x.Tags)
                                    .FirstOrDefaultAsync();
    return post;
}

public async Task&lt;IEnumerable&lt;Post&gt;&gt; GetPostByAuthorId(int id)
{
    var posts = await context.Posts.AsNoTracking()
                                    .Where(x =&gt; x.AuthorId == id)
                                    .Include(x =&gt; x.Author)
                                    .Include(x =&gt; x.Tags)
                                    .ToListAsync();
    return posts;
}

public async Task&lt;IEnumerable&lt;Post&gt;&gt; GetPostByTagId(int id)
{
    var posts = await context.Posts.AsNoTracking()
                                    .Include(x =&gt; x.Author)
                                    .Include(x =&gt; x.Tags)
                                    .Where(x =&gt; x.Tags.Any(t =&gt; t.Id == id))
                                    .ToListAsync();

    return posts;
}
</code></pre><p>The first method is the <code>GetPostAsync</code> that we created to retrieve a paginated response for all the posts. Here your work is to include the author of the post and the related tags for every post. So in the final query before calling the <code>ToListAsync</code> you will add two calls to the <code>Include</code> method one for the author and the second for the tags, this way your post response will now include those data sets.</p><p>The next method is the <code>GetPostByAuthorId</code> method which will return all the posts belonging to a single author. First, you filter the post from the author with the corresponding Id and then again you call two <code>Include</code> methods to add the author and tag data to the response.</p><p>Finally, the <code>GetPostByTagId</code> is similar to the <code>GetPostByAuthorId</code> but you will notice that first there are the two calls to the <code>Include</code> method and then a filter using <code>where</code> to filter by the specified <code>Tag</code>. This must be done this way because the <code>Post</code> &#x21D2; <code>Tag</code> relation is a many-to-many relationship therefore there is not a single tag to filter from as with the <code>Author</code> but a set of tags and we need to select the one we desire to filter for.</p><h2 id="foreseeing-self-reference-loop-from-property-error">Foreseeing Self-Reference Loop from Property Error </h2><p>Now you would likely go to the <code>Post</code> controller and update it to test the new changes right? Well, it&#x2019;s not that simple because if you go and actually do that then you will get a self-reference error because when you try to get a list of posts you will get the author with it, and then you would get the posts again and you will get it&#x2019;s author and you kinda see where this is going right? Yep, it&#x2019;s an infinite loop and you know that programming and infinite loops don&#x2019;t get along in most of cases so to avoid that you will have to use Dtos to return your resources because something you should not do is to return your data models as they are, it&#x2019;s always a good practice to create some Dtos to only return the data we want to show and avoid this kind of problems and the second thing you must do in order to avoid an infinite loop in your response is to add some configurations to <code>NewtonsoftJson</code></p><pre><code class="language-csharp">.AddNewtonsoftJson(options =&gt; options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);
</code></pre><p>The above line of code will prevent the reference loop to continue over and over by ignoring the request to be continuously returning the nested JSON.</p><h2 id="adding-some-new-dtos">Adding some new Dtos </h2><pre><code class="language-csharp">public record AuthorOnlyResponseDto(int Id, string Name);
public record TagOnlyResponseDto(int Id, string Name, string Description);
</code></pre><p>As said earlier you will need to use Dtos to return the resources in this case we are returning the author without the collection of <code>Post</code> and the <code>Tag</code> without the collection of <code>Post</code> as well.</p><h2 id="updating-postresponsedto">Updating PostResponseDto</h2><pre><code class="language-csharp">public record PostResponseDTO(
  [property: JsonPropertyOrder(1)] int Id,
  [property: JsonPropertyOrder(2)] string Title,
  [property: JsonPropertyOrder(3)] string Body,
  [property: JsonPropertyOrder(4)] DateTime CreatedDate,
  [property: JsonPropertyOrder(5)] AuthorOnlyResponseDto Author,
  [property: JsonPropertyOrder(6)] ICollection&lt;TagOnlyResponseDto&gt; Tags);
</code></pre><p>In this Dto there are some things happening. First, we are adding the <code>JsonPropertyOrder</code> attribute to set the order in which every property will be returned to have a nicely formatted response because otherwise the properties are ordered alphabetically for the <code>Author</code> now we return an <code>AuthorOnlyResponse</code> so we just return the author resource without the nested <code>Post</code> collection and finally, we return a collection of <code>TagOnlyResponseDto</code> to return only the collection of <code>Tag</code> without the nested <code>Post</code>.</p><h2 id="adding-the-new-mapping-profiles">Adding the new mapping profiles</h2><p>Now to have your Dtos working add the corresponding mappings to their profile classes as shown below.</p><pre><code class="language-csharp">public AuthorProfiles()
{
    CreateMap&lt;Author, AuthorOnlyResponseDto&gt;();
}

public TagProfiles()
{
    CreateMap&lt;Tag, TagOnlyResponseDto&gt;();
}
</code></pre><h2 id="updating-the-authorscontroller">Updating the AuthorsController</h2><p>After the changes in the <code>PostRepository</code> class there is no need to update the <code>PostsController</code> as all we needed in the controller was to return the author and tags related to the post and that is done in the repository class so now you have to update the <code>Authors</code> and <code>Tags</code> controllers to add an endpoint to return all the post under a certain author and the same for the tags.</p><pre><code class="language-csharp">[ApiController]
[Route(&quot;api/authors&quot;)]
public class AuthorsController : ControllerBase
{
    private readonly IAuthorRepository repository;
    private readonly IPostRepository postRepository;
    private readonly IMapper mapper;

    public AuthorsController(IAuthorRepository repository, IPostRepository postRepository, IMapper mapper)
    {
        this.repository = repository;
        this.postRepository = postRepository;
        this.mapper = mapper;
    }

		[HttpGet]
	  public async Task&lt;IActionResult&gt; GetAuthor()
	  {
	      var authors = await repository.GetAsync();
	      var authorsDto = mapper.Map&lt;IEnumerable&lt;AuthorOnlyResponseDto&gt;&gt;(authors);
	      return Ok(authorsDto);
	  }
	
		[HttpGet(&quot;{id:int}&quot;)]
		public async Task&lt;IActionResult&gt; GetAuthor(int id)
		{
		    var author = await repository.GetAsync(id);
		    var authorDto = mapper.Map&lt;AuthorOnlyResponseDto&gt;(author);
		    return Ok(authorDto);
		}
		
		[HttpGet(&quot;{id:int}/posts&quot;)]
		public async Task&lt;IActionResult&gt; GetPostByAuthorId(int id)
		{
		    var posts = await postRepository.GetPostByAuthorId(id);
		    var postDto = mapper.Map&lt;IEnumerable&lt;PostResponseDTO&gt;&gt;(posts);
		
		    return Ok(postDto);
		}
}
</code></pre><p>You will need to add a reference to the <code>IPostRepository</code> interface to get the collection of posts from an author. Then on both Get methods you only have to map the response from <code>Author</code> to an <code>AuthorOnlyResponseDto</code> to return only the author resource and not its nested resources.</p><p>Finally, you will have to add a new endpoint names <code>GetPostByAuthorId</code> which will retrieve all the posts from a certain author. First, you have to specify the route as <code>{id:int}/posts</code> so the way of calling this endpoint would be like this <code>api/authors/{authoId}/posts</code> and this will give us all the posts from the specified author. The code is pretty much like both previous get methods but instead of using the author repository here, you will need to call the <code>postRepository.GetPostByAuthorId</code> method and after that map the response into a <code>PostResponseDto</code>.</p><h2 id="updating-the-tagscontroller">Updating the TagsController</h2><pre><code class="language-csharp">[ApiController]
[Route(&quot;api/tags&quot;)]
public class TagsController : ControllerBase
{
    private readonly ITagRepository repository;
    private readonly IPostRepository postRepository;
    private readonly IMapper mapper;

    public TagsController(ITagRepository repository, IPostRepository postRepository ,IMapper mapper)
    {
        this.repository = repository;
        this.postRepository = postRepository;
        this.mapper = mapper;
    }

    [HttpGet]
    public async Task&lt;IActionResult&gt; GetTag()
    {
        var tags = await repository.GetAsync();
        var tagsDto = mapper.Map&lt;IEnumerable&lt;TagOnlyResponseDto&gt;&gt;(tags);
        return Ok(tagsDto);
    }

    [HttpGet(&quot;{id:int}&quot;)]
    public async Task&lt;IActionResult&gt; GetTag(int id)
    {
        var tag = await repository.GetAsync(id);
        var tagDto = mapper.Map&lt;TagOnlyResponseDto&gt;(tag);
        return Ok(tagDto);
    }

    [HttpGet(&quot;{id:int}/posts&quot;)]
    public async Task&lt;IActionResult&gt; GetPostFromTagId(int id)
    {
        var posts = await postRepository.GetPostByTagId(id);
        var postsDto = mapper.Map&lt;IEnumerable&lt;PostResponseDTO&gt;&gt;(posts);
        return Ok(postsDto);
    }
}
</code></pre><p>For the <code>TagsController</code> the thing is pretty much the same, you have to inject the <code>IPostRepository</code> interface and then update the get methods mapping the response to a <code>TagOnlyResponseDto</code> and finally add a new endpoint to get all the <code>Posts</code> under a certain <code>Tag</code>.</p><h2 id="testing-the-api">Testing the API </h2><p>Now let&#x2019;s proceed to test the new endpoints and check out our updated responses.</p><h2 id="getting-all-the-authors">Getting all the Authors </h2><pre><code class="language-json">[
  {
    &quot;id&quot;: 4,
    &quot;name&quot;: &quot;John Doe&quot;
  },
  {
    &quot;id&quot;: 5,
    &quot;name&quot;: &quot;Oscar Montenegro&quot;
  },
  {
    &quot;id&quot;: 6,
    &quot;name&quot;: &quot;Yolanda Montenegro&quot;
  }
]
</code></pre><p>In the authors controller we are getting only the authors id and name, exposing only the data we ant without exposing the nested collection of post for every author for that we will use the new endpoint.</p><h2 id="getting-all-the-posts-from-an-author">Getting all the Posts from an Author</h2><pre><code class="language-json">[
  {
    &quot;id&quot;: 11,
    &quot;title&quot;: &quot;Setting up a CI/CD Pipeline&quot;,
    &quot;body&quot;: &quot;Setup a CI/CD Pipeline using GitHub actions&quot;,
    &quot;createdDate&quot;: &quot;2023-05-29T13:25:52.0306732&quot;,
    &quot;author&quot;: {
      &quot;id&quot;: 5,
      &quot;name&quot;: &quot;Oscar Montenegro&quot;
    },
    &quot;tags&quot;: [
      {
        &quot;id&quot;: 2,
        &quot;name&quot;: &quot;Programming&quot;,
        &quot;description&quot;: &quot;Topics related to programming&quot;
      }
    ]
  },
  {
    &quot;id&quot;: 13,
    &quot;title&quot;: &quot;GitHub basics&quot;,
    &quot;body&quot;: &quot;Check out this amazing series on the GitHub basics to start working on a code repository&quot;,
    &quot;createdDate&quot;: &quot;2023-05-30T14:25:48.3537618&quot;,
    &quot;author&quot;: {
      &quot;id&quot;: 5,
      &quot;name&quot;: &quot;Oscar Montenegro&quot;
    },
    &quot;tags&quot;: [
      {
        &quot;id&quot;: 1,
        &quot;name&quot;: &quot;My first Tag&quot;,
        &quot;description&quot;: &quot;This is the first Tag&quot;
      },
      {
        &quot;id&quot;: 2,
        &quot;name&quot;: &quot;Programming&quot;,
        &quot;description&quot;: &quot;Topics related to programming&quot;
      },
      {
        &quot;id&quot;: 4,
        &quot;name&quot;: &quot;DevOps&quot;,
        &quot;description&quot;: &quot;Learn the latest DevOps trends and news&quot;
      }
    ]
  }
]
</code></pre><p>Here we are getting all the posts for the author with an id of 5 and what makes sense when you get a Post is to get the author from that post and the related tags for that post as well. For that reason, this is the optimal Post response exposing the related and relevant entities. The response is nicely formated presenting the post properties and then exposing the author and finally an array of tags.</p><h2 id="getting-all-the-tags">Getting all the Tags </h2><pre><code class="language-json">[
  {
    &quot;id&quot;: 1,
    &quot;name&quot;: &quot;My first Tag&quot;,
    &quot;description&quot;: &quot;This is the first Tag&quot;
  },
  {
    &quot;id&quot;: 2,
    &quot;name&quot;: &quot;Programming&quot;,
    &quot;description&quot;: &quot;Topics related to programming&quot;
  },
  {
    &quot;id&quot;: 4,
    &quot;name&quot;: &quot;DevOps&quot;,
    &quot;description&quot;: &quot;Learn the latest DevOps trends and news&quot;
  }
]
</code></pre><p>Now the tags are returning only the properties we want to expose on this endpoint being this the <code>name</code> and the <code>description</code> and the collection of posts related to each tag can be retrieved in a separate endpoint.</p><h2 id="getting-all-the-posts-related-to-a-tag">Getting all the posts related to a Tag </h2><pre><code class="language-json">[
  {
    &quot;id&quot;: 11,
    &quot;title&quot;: &quot;Setting up a CI/CD Pipeline&quot;,
    &quot;body&quot;: &quot;Setup a CI/CD Pipeline using GitHub actions&quot;,
    &quot;createdDate&quot;: &quot;2023-05-29T13:25:52.0306732&quot;,
    &quot;author&quot;: {
      &quot;id&quot;: 5,
      &quot;name&quot;: &quot;Oscar Montenegro&quot;
    },
    &quot;tags&quot;: [
      {
        &quot;id&quot;: 2,
        &quot;name&quot;: &quot;Programming&quot;,
        &quot;description&quot;: &quot;Topics related to programming&quot;
      }
    ]
  },
  {
    &quot;id&quot;: 13,
    &quot;title&quot;: &quot;GitHub basics&quot;,
    &quot;body&quot;: &quot;Check out this amazing series on the GitHub basics to start working on a code repository&quot;,
    &quot;createdDate&quot;: &quot;2023-05-30T14:25:48.3537618&quot;,
    &quot;author&quot;: {
      &quot;id&quot;: 5,
      &quot;name&quot;: &quot;Oscar Montenegro&quot;
    },
    &quot;tags&quot;: [
      {
        &quot;id&quot;: 1,
        &quot;name&quot;: &quot;My first Tag&quot;,
        &quot;description&quot;: &quot;This is the first Tag&quot;
      },
      {
        &quot;id&quot;: 2,
        &quot;name&quot;: &quot;Programming&quot;,
        &quot;description&quot;: &quot;Topics related to programming&quot;
      },
      {
        &quot;id&quot;: 4,
        &quot;name&quot;: &quot;DevOps&quot;,
        &quot;description&quot;: &quot;Learn the latest DevOps trends and news&quot;
      }
    ]
  }
]
</code></pre><p>This response is produced after calling the <strong><code>api/tags/2/posts</code></strong> endpoint which returns all the posts related to the <code>programming</code> tag and as before you can see that the response contains the post properties along with the author of the post and the related tags.</p><h2 id="posts-controller">Posts Controller </h2><p>The response in the posts controller will look the same as before so for that reason I will not post the response to save you from reading the same &#x1F605; but is important to say again that we have formatted the post response just the way we wanted and in a way that makes sense so whenever the client looks for a post or a collection of posts they contain all the needed data to display the post with the author name and the collection of tags for that post.</p><h2 id="conclusion">Conclusion </h2><p>To wrap it up, exposing related entities in your web API opens up a world of possibilities for working with interconnected data. By making these relationships accessible to clients, you empower them to effortlessly retrieve, modify, and navigate through linked data.</p><p>It&apos;s crucial to strike a balance between providing enough related data and optimizing performance when designing your API endpoints and responses. Factors like data size, performance impact, and security requirements should be taken into account to ensure a smooth and efficient experience for API users.</p><p>As you continue to develop your web API, make use of the strategies and techniques discussed in this article to effectively expose related entities. Remember to align your approach with the specific requirements and objectives of your application.</p><p>Armed with the knowledge and understanding of how to expose related entities, you can take your <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core Web API to new heights. By implementing the right approach, you&apos;ll create an API that offers seamless navigation, robust data retrieval, and efficient manipulation of interconnected data.</p><h2 id="we%E2%80%99ve-reached-3k-views-on-unit-coding">We&#x2019;ve reached 3K views on Unit Coding</h2><p>I&#x2019;m so happy to share that the last weekend after posting my article about Entity framework relationships I was expecting to reach 1K monthly views but suddenly when I woke up on Saturday I checked and there were more than 2K views only in one night! Man, I was so happy and today we passed the 3K views. I want to thank all of you guys that have been checking out my content and constantly reading, without you this would have not been possible so this is an achievement for all of us that make part of this community.</p><p>Also, I want to share with you that this series has somewhere 10 posts before it comes to an end and I&#x2019;m already getting ready for all the new series I want to launch for example a series on Web App development with Blazor, ASP NET MVC, LINQ and so many more and after finishing this series on web API development I will announce the launch of a surprise to all of you that have been supporting me all along this amazing journey of becoming a writer it will be free so star posted so you don&#x2019;t lose it.</p><p>There are so many words in my mind that I cannot express and so many things have been happening since the beginning of this journey. I&#x2019;m on my third month unemployed, it&#x2019;s been hard and I&#x2019;m almost running out of money (no joke &#x1F628;) but I know I&#x2019;m not out of options and there are some things that I can do before that happens. Well, I think that I must say goodbye for now because I&#x2019;m making this longer than it should be &#x1F602; thanks for your kind support and beautiful words, remember to follow me on my blog <a href="https://unitcoding.com/">Unit Coding</a>, and on my <a href="https://www.youtube.com/@unitcoding6783?ref=unitcoding.com">YouTube channel</a> under the same name and if you like Twitter you can find me there as <a href="https://twitter.com/OscarOsempu?ref=unitcoding.com">@OscarOsempu</a> I&#x2019;m still trying to get constant at twitting but it&#x2019;s sometimes hard. Thanks and see you in the next chapter! Happy coding! &#x1F44B;&#x1F3FE;</p>]]></content:encoded></item><item><title><![CDATA[Relationships in Entity Framework Core]]></title><description><![CDATA[<p>Hello guys, welcome to yet another exciting chapter of this series on developing a web API with ASP NET Core. Today we will move on to an advanced topic &#x201C;Relationships on entity framework core&#x201D; We will create more models that are a vital part of a blog, for</p>]]></description><link>https://unitcoding.com/ef-core-relationships/</link><guid isPermaLink="false">64713b336358ae04c7ec3ab7</guid><category><![CDATA[ASP NET Core]]></category><category><![CDATA[Entity Framework]]></category><category><![CDATA[REST API Development]]></category><category><![CDATA[Software Development]]></category><category><![CDATA[Web API]]></category><dc:creator><![CDATA[Oscar Montenegro]]></dc:creator><pubDate>Fri, 26 May 2023 23:10:50 GMT</pubDate><media:content url="https://unitcoding.com/content/images/2023/05/relationships-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://unitcoding.com/content/images/2023/05/relationships-1.png" alt="Relationships in Entity Framework Core"><p>Hello guys, welcome to yet another exciting chapter of this series on developing a web API with ASP NET Core. Today we will move on to an advanced topic &#x201C;Relationships on entity framework core&#x201D; We will create more models that are a vital part of a blog, for example, authors and tags and you will learn how they relate to each other and how to configure those relationships using different approaches of entity framework core, also I will leave down a link to the last chapter of this series, it was about &#x201C;Understanding the filter pipeline&#x201D; which is something you should understand to leverage the power of action filters in your web apps, and having said this without a further ado let&#x2019;s get into it.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://unitcoding.com/understanding-filter-pipeline/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Understanding The Filter Pipeline In ASP.NET Core</div><div class="kg-bookmark-description">Hey guys I&#x2019;m so happy to be writing again after a long absence I was sick and also I&#x2019;m looking for a job so a lot of things are happening right now but the post I have prepared for you today is all worth the wait. In my</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://unitcoding.com/content/images/size/w256h256/2023/03/Copy-of-Unit-1.png" alt="Relationships in Entity Framework Core"><span class="kg-bookmark-author">Unit Coding</span><span class="kg-bookmark-publisher">Oscar Montenegro</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://images.unsplash.com/photo-1588800549188-b103a104ce33?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fGZ1bm5lbHxlbnwwfHx8fDE2ODQ5MDIzOTJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Relationships in Entity Framework Core"></div></a></figure><h2 id="what-are-relationships-in-entity-framework-core">What are relationships in Entity Framework Core </h2><p>In Entity Framework Core, relationships refer to how different database tables or entities are connected or related to each other. Just like in real life, where people, objects, or concepts can have relationships with each other, databases also have relationships between tables.</p><p>Think of a relationship as a way to establish a connection between two entities in a database. These entities could represent real-world objects or concepts, such as customers and orders in an e-commerce application. By defining relationships, we can specify how these entities are associated and how they interact with each other.</p><p>Entity Framework Core allows us to define and manage different types of relationships between entities, which helps in organizing and retrieving data effectively. These relationships can be <strong>one-to-one</strong>, <strong>one-to-many</strong>, or <strong>many-to-many</strong>, depending on the nature of the data and the requirements of our application.</p><h2 id="one-to-one-relationship">One-to-One Relationship </h2><ul><li>In a one-to-one relationship, it&apos;s like having a special connection between two things. It means that each record in one table is associated with exactly one record in another table, and vice versa.</li><li>Think of it like a person and their passport. Each person has only one passport, and that passport is unique to that person. So, we can say that the person and the passport have a one-to-one relationship.</li><li>In database terms, this relationship is useful when we want to split information about an entity into separate tables to maintain cleanliness and avoid duplicating data.</li></ul><pre><code class="language-csharp">// Entities
public class Person
{
    public int PersonId { get; set; }
    public string Name { get; set; }
    public Passport Passport { get; set; }
}

public class Passport
{
    public int PassportId { get; set; }
    public string City { get; set; }
    public Person Person { get; set; }
}

// Configuration
public class MyContext : DbContext
{
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity&lt;Person&gt;()
            .HasOne(p =&gt; p.Passport)
            .WithOne(a =&gt; a.Person)
            .HasForeignKey&lt;Passport&gt;(a =&gt; a.PassportId);
    }
}
</code></pre><h2 id="one-to-many-relationship">One-to-Many Relationship </h2><ul><li>A one-to-many relationship is like a parent-child relationship, where one record in a table is associated with multiple records in another table.</li><li>For example, think of a bookstore. Each book can have many reviews, but each review is tied to only one book. So, we can say that the relationship between books and reviews is one-to-many.</li><li>In database terms, this relationship is useful when we need to represent situations where one entity can have multiple related entities.</li></ul><pre><code class="language-csharp">// Entities
public class Book
{
    public int BookId { get; set; }
    public string Name { get; set; }
    public ICollection&lt;Review&gt; Reviews { get; set; }
}

public class Review
{
    public int ReviewId { get; set; }
    public string Reviewer { get; set; }
    public Book Book { get; set; }
}

// Configuration
public class MyContext : DbContext
{
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity&lt;Review&gt;()
            .HasOne(r =&gt; r.Book)
            .WithMany(b =&gt; b.Reviews)
            .HasForeignKey(r =&gt; r.BookId);
    }
}
</code></pre><h2 id="many-to-many-relationship">Many-to-Many Relationship </h2><ul><li>A many-to-many relationship is like a group of friends. Each person can have many friends, and each friend can have many people they are friends with.</li><li>For example, think of students and courses. A student can enroll in multiple courses, and each course can have multiple students. So, we can say that students and courses have a many-to-many relationship.</li><li>In database terms, this relationship is implemented using an intermediary table, often called a junction or join table, to connect the entities.</li></ul><pre><code class="language-csharp">// Entities
public class Student
{
    public int StudentId { get; set; }
    public string Name { get; set; }
    public ICollection&lt;Course&gt; Courses { get; set; }
}

public class Course
{
    public int CourseId { get; set; }
    public string Name { get; set; }
    public ICollection&lt;Student&gt; Students { get; set; }
}

// Configuration
public class MyContext : DbContext
{
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity&lt;Student&gt;()
            .HasMany(s =&gt; s.Courses)
            .WithMany(c =&gt; c.Students)
            .UsingEntity(j =&gt; j.ToTable(&quot;StudentCourse&quot;));
    }
}
</code></pre><h2 id="configurations-in-entity-framework-core">Configurations in Entity Framework Core </h2><p>Relationship configurations in Entity Framework Core are a way to define and control how different entities are related to each other in a database. These configurations help establish the rules and behavior of the relationships between entities, such as how they are mapped to database tables, how foreign key constraints are created, and how navigation properties are set up.</p><p>Above I listed all the relationships and showed you how to set them up using the fluent API configuration because it&#x2019;s my favorite way to do it as it keeps my models clean and free of data annotations but it doesn&#x2019;t have to be the same for you, maybe you do like using data annotations or setup the relationships by convention which by the way is a pretty powerful way to do it too so I will show you how to use these three type of configurations.</p><p>To configure these relationships, Entity Framework Core provides different ways to specify the rules. There are three common approaches to relationship configuration.</p><h3 id="by-convention">By Convention </h3><p>Entity Framework Core has a set of conventions that can automatically configure relationships based on naming conventions and default behaviors. For example, if you have a navigation property named &quot;Address&quot; in the &quot;Person&quot; entity, Entity Framework Core will assume it&apos;s a one-to-one relationship and configure it accordingly. This approach is convenient when your code follows the naming conventions expected by Entity Framework Core.</p><pre><code class="language-csharp">// Entities
public class Person
{
    public int PersonId { get; set; }
    public string Name { get; set; }
    public Address Address { get; set; }
}

public class Address
{
    public int AddressId { get; set; }
    public string City { get; set; }
    public Person Person { get; set; }
}
</code></pre><h3 id="data-annotations"><strong>Data Annotations </strong></h3><p>Data annotations are attributes that you can apply to your entity classes and properties to specify relationship configurations. For example, you can use the <strong><code>[ForeignKey]</code></strong> attribute to specify the foreign key property or the <strong><code>[InverseProperty]</code></strong> attribute to specify the navigation property for a relationship. Data annotations are helpful when you want to explicitly define the relationships within your entity classes using attributes.</p><pre><code class="language-csharp">// Entities
public class Person
{
    public int PersonId { get; set; }
    public string Name { get; set; }

    [ForeignKey(&quot;Address&quot;)]
    public int AddressId { get; set; }
    public Address Address { get; set; }
}

public class Address
{
    [Key, ForeignKey(&quot;Person&quot;)]
    public int AddressId { get; set; }
    public string City { get; set; }
    public Person Person { get; set; }
}
</code></pre><p>Entity Framework Core provides several data annotations that you can use to configure entities and their relationships. These data annotations can be applied to entity classes and properties to specify various aspects of the configuration. Here are some commonly used data annotations for entity configuration:</p><ol><li><strong><code>[Key]</code></strong>: Specifies the primary key property of an entity. By default, Entity Framework Core assumes that a property named &quot;Id&quot; or &quot;&lt;EntityName&gt;Id&quot; is the primary key, but you can use this annotation to explicitly designate a property as the primary key.</li><li><strong><code>[ForeignKey]</code></strong>: Specifies the foreign key property in a relationship. This annotation is used to define the foreign key column that relates to another entity.</li><li><strong><code>[Required]</code></strong>: Indicates that a property is required and cannot be null. This annotation ensures that the corresponding column in the database is configured as non-nullable.</li><li><strong><code>[MaxLength]</code></strong>: Sets the maximum length or size for a string or byte array property. It can be used to limit the length of a string column in the database.</li><li><strong><code>[Column]</code></strong>: Specifies the name of the column in the database associated with a property. This annotation allows you to define custom column names.</li><li><strong><code>[Table]</code></strong>: Specifies the table name for an entity in the database. It can be used to override the default table name generated by Entity Framework Core.</li><li><strong><code>[NotMapped]</code></strong>: Excludes a property from being mapped to a column in the database. This annotation is useful when you have properties in your entity that don&apos;t have corresponding columns in the database.</li><li><strong><code>[InverseProperty]</code></strong>: Specifies the inverse navigation property for a relationship. It is used when you have multiple navigation properties between two entities and need to specify the inverse relationship explicitly.</li><li><strong><code>[Index]</code></strong>: Indicates that an index should be created on one or more columns in the database. This annotation can improve query performance by optimizing data retrieval.</li></ol><h3 id="fluent-api"><strong>Fluent API </strong></h3><p>Fluent API provides a more flexible and explicit way to configure relationships. With the Fluent API, you can use a set of builder methods to define the relationships between entities. This approach gives you fine-grained control over how the relationships are configured and allows you to specify additional options like cascading delete behavior, index creation, or table names.</p><pre><code class="language-csharp">// Entities
public class Person
{
    public int PersonId { get; set; }
    public string Name { get; set; }
    public Address Address { get; set; }
}

public class Address
{
    public int AddressId { get; set; }
    public string City { get; set; }
    public Person Person { get; set; }
}

// Configuration
public class MyContext : DbContext
{
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity&lt;Person&gt;()
            .HasOne(p =&gt; p.Address)
            .WithOne(a =&gt; a.Person)
            .HasForeignKey&lt;Address&gt;(a =&gt; a.AddressId);
    }
}
</code></pre><p>Whether you choose to configure relationships by convention, data annotations, or fluent API depends on your preference and specific requirements. Using any of these approaches, you can define the relationships between entities in a clear and understandable manner, ensuring that your database schema and entity model are aligned and properly represented.</p><h2 id="implementing-entities-relationships-in-your-project">Implementing Entities Relationships in Your Project </h2><p>Now let&#x2019;s move on to apply the needed relationships in your web API or any kind of web project. We will use the same project we have been using for so long the &#x201C;Blog API&#x201D; which you can clone from GitHub using the link down below, make sure you get the code from the &#x201C;ActionFilters&#x201D; branch which contains the code up to this chapter.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Osempu/BlogAPI/tree/ActionFilters?ref=unitcoding.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - Osempu/BlogAPI at ActionFilters</div><div class="kg-bookmark-description">Contribute to Osempu/BlogAPI development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Relationships in Entity Framework Core"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">Osempu</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/1e5c86a6afeddef0aa50856d2a1530f3c16d8fad6fbba81aa2e676315f27479e/Osempu/BlogAPI" alt="Relationships in Entity Framework Core"></div></a></figure><h2 id="adding-new-models">Adding new Models </h2><p>&#x26A0;&#xFE0F; <strong><strong><strong><strong><strong><strong><strong><strong>Important Note:</strong></strong></strong></strong></strong></strong></strong></strong> I will not show you all the code changes the project suffered at this stage as two new models were added there was a need to create relationships, update old dtos, and add repositories and mapping profiles to say the least. But do not worry you will be able to get the code from GitHub at the end of this article to compare with your changes or to directly go and clone the branch.</p><p>Let&#x2019;s begin by adding two new needed models to create the relationships between them and enrich our project domain layer.</p><h3 id="author-model">Author Model</h3><p>Every Post will have an author and every author can have many posts as he wants so the model would end up looking like this, you will add an <code>ICollection&lt;Post&gt;</code> which will be the collection navigation property</p><pre><code class="language-csharp">public class Tag
{
	public int Id { get; set; }
    public string Name { get; set; }

    public ICollection&lt;Post&gt; Posts { get; set; }
}
</code></pre><h3 id="tag-model">Tag model</h3><p>Every <code>Post</code> can have multiple tags and every <code>Tag</code> can be applied to any number of posts so this will be a many-to-many relationship. The model will contain some basic properties and again a collection navigation property <code>ICollection&lt;Post&gt;</code>.</p><pre><code class="language-csharp">public class Tag
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public ICollection&lt;Post&gt; Posts { get; set; }
}
</code></pre><h3 id="updating-the-post-model">Updating the Post model</h3><p>The post model suffered some changes as now we have two other models that interact and have a direct relationship with it so we added a navigation property for the <code>Author</code> of the post and a collection navigation property for the <code>Tags</code>.</p><pre><code class="language-csharp">public class Post
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime LastUpdated { get; set; }

    public int AuthorId { get; set; }
    public Author Author { get; set; }

    public ICollection&lt;Tag&gt; Tags { get; set; }
}
</code></pre><p><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>Important Note:</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong> Now that the <code>Author</code> of a post is an entity and not a single string this means that you will have to change the PostDto&#x2019;s that were created before now instead of specifying the name of the author to add it you will need to specify the id of that author to create a relationship between the post and the author.</p><h3 id="post-dtos-updated">Post Dtos updated</h3><pre><code class="language-csharp">public record AddPostDTO(string Title, string Body, int AuthorId);

public record EditPostDTO(int Id, string Title, string Body, int AuthorId);
</code></pre><h2 id="configure-the-entities-relationships">Configure the Entities Relationships </h2><p>Now go to your <code>PostConfiguration</code> class and update it adding the relationship with the <code>Tag</code> and <code>Author</code> models, down below you can see how it will end looking using the EF Core Fluent API.</p><pre><code class="language-csharp">public class PostConfiguration : IEntityTypeConfiguration&lt;Post&gt;
  {
      public void Configure(EntityTypeBuilder&lt;Post&gt; builder)
      {
          builder.HasOne( p =&gt; p.Author)
              .WithMany( a =&gt; a.Posts)
              .HasForeignKey( p =&gt; p.AuthorId);

          builder.HasMany( p =&gt; p.Tags)
              .WithMany( t =&gt; t.Posts)
              .UsingEntity( j =&gt; j.ToTable(&quot;PostTag&quot;));

					//Data seeding ** this is not used for relationship configuration **
          builder.HasData(
              new Post {Id = 1, Author = new Author {Id = 1, Name = &quot;Oscar Montenegro&quot;}, Title = &quot;My first Post&quot;, Body = &quot;Hello world, this is my first post&quot;},
              new Post {Id = 2, Author = new Author {Id = 2, Name = &quot;Another Author&quot;}, Title = &quot;My second Post&quot;, Body = &quot;Hello world, this is my second post&quot;}
          );
      }
  }
</code></pre><h2 id="update-your-database">Update your Database </h2><p>Now that you have all the changes in place the only thing that you need to do is to update your database. For this, I recommend you delete your old database to avoid having problems and to be able to update it seamlessly.</p><p>Now perform the next <code>dotnet ef</code> commands to add a new migration and update your database.</p><p><code>dotnet ef migrations add &quot;Added new entities and applied relationships&quot;</code></p><p><code>dotnet ef database update</code></p><p>Now if you go to your <strong>SQL Server Management System</strong> you should be able to see your database and if you get into the <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>Database Diagrams</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong> folder it will ask you if you want to create a new diagram, say yes and select the tables you want to include and then you should have something like this.</p><figure class="kg-card kg-image-card"><img src="https://unitcoding.com/content/images/2023/05/relationships.png" class="kg-image" alt="Relationships in Entity Framework Core" loading="lazy" width="873" height="654" srcset="https://unitcoding.com/content/images/size/w600/2023/05/relationships.png 600w, https://unitcoding.com/content/images/2023/05/relationships.png 873w" sizes="(min-width: 720px) 720px"></figure><p>On this DB diagram we can appreciate that indeed every post can have a single author and an author can have many posts (check the key and kind of infinite symbols). And for the Tag &#x21D2; Post relationship we can see that we have another intermediate table (junction table) that holds both <code>Post</code> and <code>Tag</code> id which makes the many-to-many relationship.</p><h2 id="adding-functionality-to-your-new-models">Adding functionality to your new Models </h2><p>Now comes the hard part, you added the entities relationships and the new models as well but know you need to add their controllers, mapping profiles, Dtos, Repositories, and IRepositories to make sure that you can add, create, read, update,e and delete resources for both the <code>Tag</code> and <code>Author</code> entities.</p><p>As I said earlier I won&#x2019;t be showing the code for all these updates but you can get them here from GitHub.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Osempu/BlogAPI/tree/EfCoreRelationships?ref=unitcoding.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - Osempu/BlogAPI at EfCoreRelationships</div><div class="kg-bookmark-description">Contribute to Osempu/BlogAPI development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Relationships in Entity Framework Core"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">Osempu</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/1e5c86a6afeddef0aa50856d2a1530f3c16d8fad6fbba81aa2e676315f27479e/Osempu/BlogAPI" alt="Relationships in Entity Framework Core"></div></a></figure><h2 id="test-your-application">Test your application </h2><p>As always the moment has come to test your application, you could test your API without having the controllers or repositories as you can insert some records directly to <strong>SQL Server</strong> using the <strong>SSMS (SQL Server Management System).</strong> But I would not recommend you this as anyways you will need those controllers and repos in the future so why not code them now right? take it as an assignment.</p><h2 id="conclusion">Conclusion </h2><p>Entity Framework Core is an amazing tool that makes dealing with different types of relationships in your database a breeze. Whether you&apos;re working with one-to-one, one-to-many, or many-to-many relationships, Entity Framework Core has got you covered. It even supports self-referencing and required/optional relationships, giving you the flexibility to design your database schema just the way you want. With Entity Framework Core, you can create scalable and maintainable <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core applications without breaking a sweat. So, let&apos;s dive in and explore the power of Entity Framework Core&apos;s relationship capabilities. Get ready to unleash your coding skills and enjoy the journey!</p><h2 id="support-me-on-my-journey-as-a-writer-and-content-creator">Support me on my Journey as a Writer and Content Creator! </h2><p>This is the time of the day when I take some time to thank all the amazing people that have supported me and followed this series all along with my other C# projects giving me such energy to continue. But if you are new to my blogs please consider supporting me on my Blog <a href="https://unitcoding.com/">Unit Coding</a> and also on my <a href="https://www.youtube.com/@unitcoding6783?ref=unitcoding.com">YouTube channel</a> under the same name where I returned after a long hiatus and plan to continue with the streak, also you can find me on Twitter as <a href="https://twitter.com/OscarOsempu?ref=unitcoding.com">@OscarOsempu</a>. Thanks for your time in reading my article I hope you can get tons of value from it and that It solved all your doubts about this amazing topic. Thanks for everything, I&#x2019;ll see you soon in my next article!</p>]]></content:encoded></item><item><title><![CDATA[Understanding The Filter Pipeline In ASP.NET Core]]></title><description><![CDATA[<p>Hey guys I&#x2019;m so happy to be writing again after a long absence I was sick and also I&#x2019;m looking for a job so a lot of things are happening right now but the post I have prepared for you today is all worth the wait.</p>]]></description><link>https://unitcoding.com/understanding-filter-pipeline/</link><guid isPermaLink="false">646d91b66358ae04c7ec3a92</guid><category><![CDATA[ASP NET Core]]></category><category><![CDATA[REST API Development]]></category><category><![CDATA[Web API]]></category><category><![CDATA[C#]]></category><dc:creator><![CDATA[Oscar Montenegro]]></dc:creator><pubDate>Wed, 24 May 2023 04:31:18 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1588800549188-b103a104ce33?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fGZ1bm5lbHxlbnwwfHx8fDE2ODQ5MDIzOTJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1588800549188-b103a104ce33?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fGZ1bm5lbHxlbnwwfHx8fDE2ODQ5MDIzOTJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Understanding The Filter Pipeline In ASP.NET Core"><p>Hey guys I&#x2019;m so happy to be writing again after a long absence I was sick and also I&#x2019;m looking for a job so a lot of things are happening right now but the post I have prepared for you today is all worth the wait. </p><p>In my last article, I talked to you guys about how to use the patch request to partially update your web API resources and I put a lot of effort to show you all the types of operations that the patch method supports and how you could use them so I leave a link to that article if you want to check it out. Ok now let&apos;s get into today&apos;s article.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://unitcoding.com/how-to-use-patch-requests-to-update-resources-in-your-rest-api/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">How to Use Patch Requests to Update Resources in Your REST API</div><div class="kg-bookmark-description">Hello guys, Oscar here with another amazing chapter on REST API Development with ASP NET 7. Today we have an amazing and relevant topic for our APIs to have more power and flexibility at the time of updating our API resources. If you&#x2019;re familiar with HTTP requests, you&#x2019;ve probably heard</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://unitcoding.com/content/images/size/w256h256/2023/03/Copy-of-Unit-1.png" alt="Understanding The Filter Pipeline In ASP.NET Core"><span class="kg-bookmark-author">Unit Coding</span><span class="kg-bookmark-publisher">Oscar Montenegro</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://images.unsplash.com/photo-1507525586584-6a9c816efbed?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDExfHxwYXRjaHxlbnwwfHx8fDE2ODM3Nzg2MzN8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Understanding The Filter Pipeline In ASP.NET Core"></div></a></figure><p>Actually, when I first learned about action filters I had a hard time understanding them and they did not look appealing or exciting to me so I pushed myself to my limit to bring you something amazing even though I had a hard time enjoying it.</p><p>As a developer, you must have heard of the term &apos;Action Filters&apos; when working with <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core. Action filters are an essential part of the framework and can help you add additional functionality to your application. In this blog, we will explore what action filters are and why you should use them.</p><h2 id="what-is-an-action-filter"><strong>What is an Action Filter ?</strong></h2><p>An action filter is a type of filter that allows you to add additional behavior to the MVC framework&apos;s action methods. You can use them to execute code before or after an action method is executed, or to modify the results returned by the action method.</p><h2 id="why-should-i-use-action-filters"><strong>Why should I use Action Filters ?</strong></h2><p>Action filters offer several benefits, including:</p><ol><li><strong>Code Reusability</strong>: Action filters are reusable components that can be applied to multiple action methods, reducing code duplication and increasing maintainability.</li><li><strong>Separation of Concerns</strong>: Action filters allow you to separate cross-cutting concerns from the rest of your code. For example, you can use an action filter to handle logging or caching logic, leaving your action methods focused on their specific functionality.</li><li><strong>Customization</strong>: You can create custom action filters to add functionality that is specific to your application&apos;s needs.</li></ol><h2 id="code-example-of-an-action-filter-%F0%9F%A7%91%F0%9F%8F%BE%E2%80%8D%F0%9F%92%BB"><strong>Code Example of an Action Filter &#x1F9D1;&#x1F3FE;&#x200D;&#x1F4BB;</strong></h2><p>Let&apos;s take a look at an example of an action filter that logs the time it takes to execute an action method.</p><pre><code class="language-csharp">public class LogActionFilter : IActionFilter
{
    private readonly ILogger _logger;

    public LogActionFilter(ILogger&lt;LogActionFilter&gt; logger)
    {
        _logger = logger;
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        _logger.LogInformation($&quot;Executing action {context.ActionDescriptor.DisplayName}.&quot;);
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        _logger.LogInformation($&quot;Executed action {context.ActionDescriptor.DisplayName} in {context.HttpContext.Response.Headers[&quot;X-Elapsed-Time&quot;]}.&quot;);
    }
}

</code></pre><p>In this example, we created a custom action filter called <strong><code>LogActionFilter</code></strong> that logs the time it takes to execute an action method. The <strong><code>OnActionExecuting</code></strong> method is called before the action method is executed, and the <strong><code>OnActionExecuted</code></strong> method is called after the action method is executed.</p><p>To use this action filter, we need to register it in the ConfigureServices method of our startup class:</p><pre><code class="language-csharp">services.AddScoped&lt;LogActionFilter&gt;();
</code></pre><p>And then apply it to an action method by adding the <strong><code>[ServiceFilter(typeof(LogActionFilter))]</code></strong> attribute to the action method:</p><pre><code class="language-csharp">[ServiceFilter(typeof(LogActionFilter))]
public IActionResult Index()
{
    // Do something here
}
</code></pre><h2 id="type-of-filters">Type of Filters </h2><p><a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core has six types of filters: Authorization filters, Resource filters, Action filters, and Exception filters. Let&apos;s take a closer look at each type along with a code example for each.</p><h3 id="1-authorization-filters"><strong>1. Authorization Filters </strong></h3><p>Authorization filters are used to check if a user is authorized to access a particular resource or page. They are executed before the action method is invoked.</p><p>Here&apos;s an example of an authorization filter that checks if the user is authenticated:</p><pre><code class="language-csharp">public class CustomAuthorizationFilter : IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        if (!context.HttpContext.User.Identity.IsAuthenticated)
        {
            // Redirect to login page or return unauthorized response
            context.Result = new RedirectToActionResult(&quot;Login&quot;, &quot;Account&quot;, null);
        }
    }
}
</code></pre><p>To apply this authorization filter to an action method, you can use the <strong><code>[Authorize]</code></strong> attribute along with the filter:</p><pre><code class="language-csharp">[Authorize]
[TypeFilter(typeof(CustomAuthorizationFilter))]
public IActionResult SecureAction()
{
    // Code for secure action
}
</code></pre><h3 id="2-resource-filters"><strong>2. Resource Filters </strong></h3><p>Resource filters are used to perform tasks that are related to a particular resource. They are executed before and after the action method.</p><p>Here&apos;s an example of a resource filter that logs the start and end of the action method execution:</p><pre><code class="language-csharp">public class LoggingResourceFilter : IResourceFilter
{
    private readonly ILogger _logger;

    public LoggingResourceFilter(ILogger&lt;LoggingResourceFilter&gt; logger)
    {
        _logger = logger;
    }

    public void OnResourceExecuting(ResourceExecutingContext context)
    {
        _logger.LogInformation(&quot;Executing resource filter - Before action method&quot;);
    }

    public void OnResourceExecuted(ResourceExecutedContext context)
    {
        _logger.LogInformation(&quot;Executing resource filter - After action method&quot;);
    }
}
</code></pre><p>To apply this resource filter to an action method, you can use the <strong><code>[TypeFilter]</code></strong> attribute:</p><pre><code class="language-csharp">[TypeFilter(typeof(LoggingResourceFilter))]
public IActionResult MyAction()
{
    // Code for the action method
}
</code></pre><h3 id="3-action-filters"><strong>3. Action Filters </strong></h3><p>Action filters are used to perform tasks that are related to a particular action method. They are executed before and after the action method.</p><p>Here&apos;s an example of an action filter that logs the time it takes to execute an action method:</p><pre><code class="language-csharp">public class TimingActionFilter : IActionFilter
{
    private readonly Stopwatch _stopwatch;

    public TimingActionFilter()
    {
        _stopwatch = new Stopwatch();
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        _stopwatch.Start();
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        _stopwatch.Stop();
        var elapsedMilliseconds = _stopwatch.ElapsedMilliseconds;
        // Log or use the elapsed time as needed
    }
}
</code></pre><p>To apply this action filter to an action method, you can use the <strong><code>[ServiceFilter]</code></strong> attribute:</p><pre><code class="language-csharp">[ServiceFilter(typeof(TimingActionFilter))]
public IActionResult MyAction()
{
    // Code for the action method
}
</code></pre><h3 id="4-exception-filters"><strong>4. Exception Filters </strong></h3><p>Exception filters are used to handle exceptions that occur during the execution of an action method. They are executed when an exception is thrown.</p><p>Here&apos;s an example of an exception filter that handles and logs exceptions:</p><pre><code class="language-csharp">public class ExceptionLoggingFilter : IExceptionFilter
{
    private readonly ILogger _logger;

    public ExceptionLoggingFilter(ILogger&lt;ExceptionLoggingFilter&gt; logger)
    {
        _logger = logger;
    }

    public void OnException(ExceptionContext context)
    {
        _logger.LogError(context.Exception, &quot;Exception occurred&quot;);
        // Handle the exception or perform any necessary actions
    }
}
</code></pre><p>To apply this exception filter to an action method, you can use the <strong><code>[TypeFilter]</code></strong> attribute:</p><pre><code class="language-csharp">[TypeFilter(typeof(ExceptionLoggingFilter))]
public IActionResult MyAction()
{
    // Code for the action method
}
</code></pre><h3 id="5-endpoint-filters">5. Endpoint Filters </h3><p>Endpoint filters are used to perform actions before and after an endpoint is selected during the routing process. They can be used to modify the selected endpoint or add additional behavior.</p><p>Here&apos;s an example of an endpoint filter that modifies the endpoint&apos;s metadata:</p><pre><code class="language-csharp">public class CustomEndpointFilter : IEndpointFilter
{
    public void OnEndpointSelected(EndpointSelectedContext context)
    {
        // Modify endpoint metadata or perform additional actions
        var endpoint = context.Endpoint;
        // Modify the endpoint as needed
    }
}
</code></pre><p>To apply this endpoint filter, you can use the <code>AddEndpointFilter</code> extension method in the <code>ConfigureServices</code> method of your <code>Startup</code> class:</p><pre><code class="language-csharp">public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
            .AddEndpointFilter&lt;CustomEndpointFilter&gt;();
}
</code></pre><h3 id="6-result-filters">6. Result Filters </h3><p>Result filters are used to perform actions before and after the execution of an action result. They can modify the result, add headers, or perform additional operations.</p><p>Here&apos;s an example of a result filter that modifies the result by adding a custom header:</p><pre><code class="language-csharp">public class CustomResultFilter : IResultFilter
{
    public void OnResultExecuting(ResultExecutingContext context)
    {
        // Modify the result or add headers before the execution
        context.HttpContext.Response.Headers.Add(&quot;CustomHeader&quot;, &quot;CustomValue&quot;);
    }

    public void OnResultExecuted(ResultExecutedContext context)
    {
        // Perform additional actions after the execution
    }
}
</code></pre><p>To apply this result filter to an action method, you can use the <code>[ServiceFilter]</code> attribute:</p><pre><code class="language-csharp">[ServiceFilter(typeof(CustomResultFilter))]
public IActionResult MyAction()
{
    // Code for the action method
}
</code></pre><p>Alternatively, you can apply the result filter globally to all action methods by using the <code>AddMvcOptions</code> method in the <code>ConfigureServices</code> method of your <code>Startup</code> class:</p><pre><code class="language-csharp">public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =&gt;
    {
        options.Filters.Add&lt;CustomResultFilter&gt;();
    });
}
</code></pre><p>By utilizing endpoint filters, you can modify endpoint metadata and add behavior during the routing process. Result filters, on the other hand, allow you to modify action results and perform additional actions before and after their execution. These filters provide flexibility and control over the behavior of your <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core application.</p><p>By utilizing these different types of filters, you can enhance the behavior and functionality of your <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core application, adding security checks, logging, exception handling, and resource-related tasks.</p><h2 id="filters-scope">Filters Scope </h2><p>Filters can be applied at different scopes, depending on where you want them to take effect. Let&apos;s explore the three main scopes: Global, Controller, and Action.</p><h3 id="global-filters">Global Filters </h3><p>Global filters are applied to all action methods in your application. They are registered during application startup and provide common functionality or handle cross-cutting concerns throughout your application.</p><p><strong>Example</strong>:</p><pre><code class="language-csharp">// Custom global filter implementing IActionFilter
public class GlobalLoggingFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Perform actions before the action method execution
        // Example: Logging or request validation
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Perform actions after the action method execution
        // Example: Logging or response modification
    }
}

// Registering global filter in Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =&gt;
    {
        options.Filters.Add&lt;GlobalLoggingFilter&gt;();
    });
}
</code></pre><h3 id="controller-filters">Controller Filters </h3><p>Controller filters are applied to all action methods within a specific controller. They allow you to apply behavior that is specific to a group of related actions.</p><p><strong>Example</strong>:</p><pre><code class="language-csharp">// Custom controller filter implementing IActionFilter
public class AuthenticationFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Perform actions before the action method execution
        // Example: Authentication or authorization checks
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Perform actions after the action method execution
    }
}

// Applying controller filter to a controller
[TypeFilter(typeof(AuthenticationFilter))]
public class MyController : Controller
{
    // Actions within this controller will be subject to the AuthenticationFilter
}
</code></pre><h3 id="action-filters">Action Filters </h3><p>Action filters are applied to individual action methods, allowing you to customize the behavior of specific actions.</p><p><strong>Example</strong>:</p><pre><code class="language-csharp">// Custom action filter implementing IActionFilter
public class LoggingFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Perform actions before the action method execution
        // Example: Logging or input validation
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Perform actions after the action method execution
    }
}

// Applying an action filter to an action method
[ServiceFilter(typeof(LoggingFilter))]
public IActionResult MyAction()
{
    // Code for the action method
}
</code></pre><p>These examples demonstrate the usage of action filters at different scopes. Global filters provide common functionality for all actions, controller filters apply behavior to a specific group of actions within a controller, and action filters allow fine-grained control over individual action methods. By utilizing these action filter scopes, you can add the desired behavior and customization to your <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core application.</p><p>By using these different scopes, you can apply action filters where they are most needed. Global filters provide overarching functionality across your entire application, controller filters offer behavior specific to a group of related actions, and action filters allow you to fine-tune the behavior of individual action methods.</p><p>Remember, each scope serves a unique purpose, and you can mix and match them based on your application&apos;s requirements. Whether you need broad protection, controller-specific enhancements, or action-level customization, action filter scopes in <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core have got you covered!</p><h2 id="implementing-your-own-action-filter">Implementing your Own Action Filter </h2><p>Even thou we reviewed all filter types that ASP NET Core supports we will focus on implementing an action filter to our web API that validates data. The action filter to implement will validate if the <code>Post</code> object is null as this is a repetitive snippet of code that needs to be added to various endpoints in the <code>PostsController</code>.</p><h2 id="clone-the-repository-code-on-github">Clone the Repository Code on GitHub </h2><p>Remember that if you want to follow along with the tutorial get the latest code changes up to this article from the Web API Repository at Github on the <code>Patch</code> branch.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Osempu/BlogAPI/tree/Patch?ref=unitcoding.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - Osempu/BlogAPI at Patch</div><div class="kg-bookmark-description">Contribute to Osempu/BlogAPI development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Understanding The Filter Pipeline In ASP.NET Core"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">Osempu</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/1b5d888713539a0904a95ec49a4cb579fdc2c061ec5da8bfb26a1a0c4d889f5b/Osempu/BlogAPI" alt="Understanding The Filter Pipeline In ASP.NET Core"></div></a></figure><h2 id="create-a-new-action-controller-class">Create a new Action Controller Class </h2><p>Let&#x2019;s begin by first creating a new action controller that will validate if the <code>Post</code> we want to Get, Delete, Edit, Patch actually exists and this way we will avoid duplicating that code in our controller actions.</p><pre><code class="language-csharp">public class PostExistsFilter : IAsyncActionFilter
{
    private readonly IPostRepository postRepository;

    public PostExistsFilter(IPostRepository postRepository)
    {
        this.postRepository = postRepository;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        if (!context.ActionArguments.ContainsKey(&quot;id&quot;))
        {
            context.Result = new BadRequestResult();
            return;
        }

        if (!(context.ActionArguments[&quot;id&quot;] is int id))
        {
            context.Result = new BadRequestResult();
            return;
        }

        var post = await postRepository.GetPostAsync(id);

        if (post is null)
        {
            context.Result = new NotFoundObjectResult($&quot;Post with id {id} does not exist.&quot;);
            return;
        }

        await next();
    }
}
</code></pre><p>You will create a new class called <code>PostExistsFilter</code> that implements the <code>IAsyncActionFilter</code> and this will be your ActionFilter, you have to use the async version as the <code>IPostRepository</code> uses the <code>GetPostAsync</code> function.</p><p>The <code>IPostRepository</code> interface will be injected using constructor injection.</p><p>Next, you will have to implement the interface method <code>OnActionExutionAsync</code> which provides the <code>ActionExecutionContext</code> and <code>ActionExecutionDelegate</code> as parameters.</p><p>Inside the method, the method will check if the action contains an <code>id</code> as an argument, and if not it will throw a new <code>BadRequestResult</code> then in the next if statement it will check the id to be an int and again if it&#x2019;s not it will return a <code>BadRequestResult</code>.</p><p>After both if statements now that the method validated the id to exist as a parameter in the action and that the id is an int it will attempt to retrieve the post using the <code>GetPostAsync(id)</code> method. Last but not least if the post is null it will return a <code>NotFoundObjectResult</code> response with a custom error message and then call the <code>ActionExecutionDelegate</code> to continue with the action request.</p><h2 id="create-an-attribute-class">Create an Attribute Class </h2><p>If you use the <code>PostExistsFilter</code> as it is you would need to register it as a service in the <code>Program</code> class and use it above actions like this:</p><pre><code class="language-csharp">[ServiceFilter(typeof(PostExistsFilter))]
public async Task&lt;IActionResult&gt; EditPost
</code></pre><p>This is not bad but we can achieve a much more clean and enhance the usability of filter attributes that depends on other classes.</p><p>So you will have to create a new attribute class called <code>PostExistsAttribute</code> that implements the <code>TypeFilterAttribute</code> base class and call the base constructor by referring to the <code>PostExistsFilter</code> so in much simpler words you will need to have something like the following:</p><pre><code class="language-csharp">public class PostExistsAttribute : TypeFilterAttribute
{
    public PostExistsAttribute() : base(typeof(PostExistsFilter))
    {
    }
}
</code></pre><p>Yeah, it is that simple. Just an attribute class that calls the base constructor passing our action filter.</p><p>This may seem odd but it&#x2019;s pretty useful as you will no longer need to register your Filter in the service container in the <code>Program</code> class and the attribute will end up looking a lot cleaner when used on the corresponding action endpoints and you will look at that in a brief.</p><h2 id="applying-your-action-filter-in-the-postscontroller">Applying your Action Filter in the PostsController</h2><p>Now all that is left is to do is to apply the action filter to the endpoints that actually make use of the null checking for the <code>Post</code> entity.</p><pre><code class="language-csharp">[HttpGet(&quot;{id:int}&quot;)]
[PostExists]
public async Task&lt;IActionResult&gt; GetPost(int id)

[HttpPut(&quot;{id:int}&quot;)]
[PostExists]
public async Task&lt;IActionResult&gt; EditPost(int id, [FromBody] EditPostDTO editPostDto)

[HttpDelete(&quot;{id:int}&quot;)]
[PostExists]
public async Task&lt;IActionResult&gt; DeletePost(int id)

[HttpPatch(&quot;{id:int}&quot;)]
[PostExists]
public async Task&lt;ActionResult&gt; PatchPost(int id, [FromBody] JsonPatchDocument&lt;Post&gt; doc)
</code></pre><p>You should apply the action filter to these four endpoints and remove all code checking if the post is null. Also, you can note that the way you call the action filter is using the <code>[PostExists]</code> attribute instead of the old way of doing it which looked a lot harder to read.</p><h2 id="update-to-the-getpostasyncid-method-in-the%60postrepository">Update to the GetPostAsync(id) method in the`PostRepository</h2><p>To avoid concurrency problems you will need to update the <code>GetPostAsync(id)</code> method that retrieves a single post.</p><pre><code class="language-csharp">public async Task&lt;Post&gt; GetPostAsync(int id)
{
    var post = await context.Posts.AsNoTracking().SingleOrDefaultAsync(x =&gt; x.Id == id);
    return post;
}
</code></pre><p>This is to avoid tracking the retrieved post as the same post will be accessed to be updated, patched, or deleted and can have concurrency problems as they will all try to access the same entity at the same time.</p><h2 id="take-your-app-for-a-test">Take your app for a test </h2><p>Now you are ready to test your app and you will see no change if your endpoint supported the null check but if not you will notice that if the post you try to access is null then you will receive a <code>NotFound</code> HTTP response code.</p><h2 id="conclusion"><strong>Conclusion </strong></h2><p>Action filters are an important part of the <a href="http://asp.net/?ref=unitcoding.com">ASP.NET</a> Core framework, and they offer several benefits, including code reusability, separation of concerns, and customization. By using action filters, you can add additional functionality to your application and make it more maintainable.</p><h2 id="great-announcement">Great Announcement </h2><p>I&#x2019;m back on <a href="https://www.youtube.com/@unitcoding6783?ref=unitcoding.com">YouTube</a> so make sure you go and check out the new videos that I released these days and don&#x2019;t forget to subscribe, like, and share with your friends that are also learning. Also, remember that you can follow me on Twitter as <a href="https://twitter.com/OscarOsempu?ref=unitcoding.com">Oscar Montenegro</a> and check out my Blog <a href="https://www.youtube.com/@unitcoding6783?ref=unitcoding.com">Unit Coding</a> for more awesome content about designing and developing REST Services using ASP NET 7+ and amazing web applications with Blazor. Thanks for your constant support as I&#x2019;m here because of all the amazing people that follow my work, for you guys cheers &#x1F37B;. See you all in the next article!</p>]]></content:encoded></item><item><title><![CDATA[How to Use Patch Requests to Update Resources in Your REST API]]></title><description><![CDATA[<p>Hello guys, Oscar here with another amazing chapter on REST API Development with ASP NET 7. Today we have an amazing and relevant topic for our APIs to have more power and flexibility at the time of updating our API resources.</p><p>If you&apos;re familiar with HTTP requests, you&</p>]]></description><link>https://unitcoding.com/how-to-use-patch-requests-to-update-resources-in-your-rest-api/</link><guid isPermaLink="false">645c6b996358ae04c7ec3a78</guid><category><![CDATA[ASP NET Core]]></category><category><![CDATA[REST API Development]]></category><category><![CDATA[Software Development]]></category><category><![CDATA[Web API]]></category><dc:creator><![CDATA[Oscar Montenegro]]></dc:creator><pubDate>Thu, 11 May 2023 04:23:34 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1507525586584-6a9c816efbed?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDExfHxwYXRjaHxlbnwwfHx8fDE2ODM3Nzg2MzN8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1507525586584-6a9c816efbed?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDExfHxwYXRjaHxlbnwwfHx8fDE2ODM3Nzg2MzN8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="How to Use Patch Requests to Update Resources in Your REST API"><p>Hello guys, Oscar here with another amazing chapter on REST API Development with ASP NET 7. Today we have an amazing and relevant topic for our APIs to have more power and flexibility at the time of updating our API resources.</p><p>If you&apos;re familiar with HTTP requests, you&apos;ve probably heard of GET, POST, PUT, and DELETE. But have you heard of PATCH? In this article, we&apos;ll explain what a PATCH request is, why it&apos;s useful, and how you can use it, also I will show you the different type of operations that the patch method supports and how you can implement it on your own web API so without further ado let&#x2019;s get into the action.</p><h2 id="what-is-the-patch-request">What is the Patch Request ?</h2><p>The PATCH request is an HTTP method that is used to partially update an existing resource. With PATCH, you can modify specific attributes of a resource without having to send the entire resource back to the server.</p><p>For example, let&apos;s say you have a user profile that includes a name, email address, and phone number. If the user updates their phone number, you could use a PATCH request to send only the new phone number to the server, rather than sending the entire user profile this means a great improvement in flexibility at the time of updating large objects because you will no longer have to provide and update all the resource properties but only the ones that you want.</p><h2 id="why-is-patch-request-useful">Why is Patch Request Useful ?</h2><p>Patch request offers several benefits.</p><p>Firstly, it can be more efficient than other HTTP methods. If you only need to modify a small part of a resource, sending the entire resource to the server can be unnecessary and time-consuming. By using PATCH, you can reduce the amount of data that needs to be sent, which can improve performance.</p><p>Secondly, PATCH is useful when you need to make incremental changes to a resource. For example, if you want to update a user&apos;s email address and phone number separately, PATCH allows you to do this without overwriting any other attributes of the resource.</p><p>Finally, using PATCH can be beneficial for ensuring data consistency. If you use PUT to update a resource, you must send the entire resource to the server, even if only one attribute has changed. This can result in other attributes being overwritten accidentally. PATCH, on the other hand, allows you to modify only the attributes you want to change, reducing the risk of unintended consequences.</p><h2 id="different-patch-operations">Different Patch Operations </h2><p>There are six different patch operations:</p><h3 id="add">Add </h3><p>This operation adds a new value to a property.</p><pre><code class="language-json">{
	&quot;op&quot;: &quot;add&quot;,
	&quot;path&quot;: &quot;/title&quot;,
	&quot;value&quot;: &quot;new value&quot;
}
</code></pre><h3 id="remove">Remove </h3><p>Removes the value from a property or sets it to a default value.</p><pre><code class="language-json">{
	&quot;op&quot;: &quot;remove&quot;,
	&quot;path&quot;: &quot;/title&quot;
}
</code></pre><h3 id="replace">Replace </h3><p>Replaces a value to a new one. It is the equivalent of a remove operation followed by an add operation.</p><pre><code class="language-json">{
	&quot;op&quot;: &quot;replace&quot;,
	&quot;path&quot;: &quot;/title&quot;,
	&quot;value&quot;: &quot;new value&quot;
}
</code></pre><h3 id="copy">Copy </h3><p>Copies the value from one location to another(property) using two JSON pointers <code>from</code> and <code>path</code>.</p><pre><code class="language-json">{
	&quot;op&quot;: &quot;copy&quot;,
	&quot;path&quot;: &quot;/title&quot;,
	&quot;from&quot;: &quot;/author&quot;
}
</code></pre><h3 id="move">Move </h3><p>Moves a value from one location to another(property) using two JSON pointers <code>from</code> and <code>path</code>.</p><pre><code class="language-json">{
	&quot;op&quot;: &quot;move&quot;,
	&quot;path&quot;: &quot;/title&quot;,
	&quot;from&quot;: &quot;/author&quot;
}
</code></pre><h3 id="test">Test</h3><p>Tests if a property has an expected value. if the test fails, then the patch as a whole should not apply.</p><pre><code class="language-json">{
	&quot;op&quot;: &quot;test&quot;,
	&quot;path&quot;: &quot;/title&quot;,
	&quot;value&quot;: &quot;test value&quot;
}
</code></pre><h2 id="example-of-a-patch-request-body">Example of a Patch Request Body </h2><pre><code class="language-json">[
	{
        &quot;op&quot;: &quot;replace&quot;,
        &quot;path&quot;: &quot;/title&quot;,
        &quot;value&quot;: &quot;new title&quot;
	},
	{
        &quot;op&quot;: &quot;add&quot;,
        &quot;path&quot;: &quot;/author&quot;,
        &quot;value&quot;: &quot;new author&quot;
	}
]
</code></pre><p>In the code example above you can see that the request starts with a pair of square brackets that represents an array, in this case, is an array of operations, and every operation starts and is delimited by a pair of curly braces, meaning that you can execute a set of operations to an object and not just one.</p><p>Then every operation has an <code>op</code> property representing the type of operation you are executing, then the path property specifies on which property or field you will execute the operation, and finally, the value property specifies the value that will be used in the operation.</p><p>This is a pretty basic example because as you know you can use properties like <code>from</code> that are JSON pointers that gives you a lot of possibilities working with the patch method.</p><h2 id="clone-the-repository-from-github">Clone the Repository from GitHub </h2><p>Before starting to code I recommend you to go and get the code from the GitHub repository so you can follow along with this example. Make sure you get the code from the <code>Sorting</code> branch to have the latest version of the code up to this article.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Osempu/BlogAPI/tree/Sorting?ref=unitcoding.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - Osempu/BlogAPI at Sorting</div><div class="kg-bookmark-description">Contribute to Osempu/BlogAPI development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="How to Use Patch Requests to Update Resources in Your REST API"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">Osempu</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/1b5d888713539a0904a95ec49a4cb579fdc2c061ec5da8bfb26a1a0c4d889f5b/Osempu/BlogAPI" alt="How to Use Patch Requests to Update Resources in Your REST API"></div></a></figure><h2 id="install-required-nuget-packages">Install required Nuget Packages </h2><p>In order to support the <code>Patch</code> requests we need to install two required libraries:</p><p>The <code>Microsoft.AspNetCore.JsonPatch</code> provides the <code>JsonPatchDocument</code> class type.</p><p>The <code>Microsoft.AspNetCore.Mvc.NewtonsoftJson</code> provides the <code>NewtonSoftJson</code> serializer into the application.</p><p>You can install these two Nuget Packages with the following dotnet cli command:</p><pre><code class="language-csharp">dotnet add package Microsoft.AspNetCore.JsonPatch
dotnet add package Microsoft.AspNetCore.Mvc.NewtonsoftJson
</code></pre><h2 id="register-newtonsoftjson-in-the-program-file">Register NewtonsoftJson in the Program file </h2><p>In order to use the Newtonsoft library you have to add it as a service into the <code>Program</code> file after adding the controllers.</p><pre><code class="language-csharp">builder.Services.AddControllers()
                .AddNewtonsoftJson();
</code></pre><p>Now you are ready to implement the <code>Patch</code> method in the Post controller.</p><h2 id="implementing-the-patch-method">Implementing the Patch method </h2><pre><code class="language-csharp">using Microsoft.AspNetCore.JsonPatch;
//code omitted for brevity

[HttpPatch(&quot;{id:int}&quot;)]
public async Task&lt;ActionResult&gt; PatchPost(int id, [FromBody] JsonPatchDocument&lt;Post&gt; doc)
{
    var post = await repository.GetPostAsync(id);

    if(post is null)
    {
        return NotFound();
    }

    doc.ApplyTo(post);
    await repository.EditAsync(post);

    return NoContent();
}
</code></pre><p>First import the <code>Microsoft.AspNetCore.JsonPatch</code> namespace to support the <code>Patch</code> method and add the <code>HttpPatch</code> attribute to the <code>PatchPost</code> endpoint.</p><p>This <code>Patch</code> endpoint accepts the <code>Post</code> id and a <code>JsonPatchDocument&lt;T&gt;</code> as the payload and it will get it from the body so add the <code>[FromBody]</code> attribute to this parameter.</p><p>You have to get the <code>Post</code> to update using the <code>GetPostAsync(id)</code> method from the repository class, then if the post is null return a <code>NotFoun</code> <code>HttpResponseCode</code> to notify that the resource does not exist.</p><p>Finally, use the <code>ApplyTo()</code> method to merge the changes into the request to the targeted resource. Then update the <code>Post</code> and return a <code>NoContent</code> <code>HttpResponseCode</code>.</p><p>For further information about the patch method visit <a href="https://jsonpatch.com/?ref=unitcoding.com">https://jsonpatch.com/</a></p><h2 id="test-the-patch-method-with-postman-or-swagger">Test the Patch method with Postman or swagger</h2><p>Now you should be ready to test the new patch endpoint updating a single value from one of your posts. Below is an example of how to perform a replace operation to a post.</p><figure class="kg-card kg-image-card"><img src="https://unitcoding.com/content/images/2023/05/patch.png" class="kg-image" alt="How to Use Patch Requests to Update Resources in Your REST API" loading="lazy" width="896" height="882" srcset="https://unitcoding.com/content/images/size/w600/2023/05/patch.png 600w, https://unitcoding.com/content/images/2023/05/patch.png 896w" sizes="(min-width: 720px) 720px"></figure><p>First, you need to input the id from the post you want to update and send the JSON payload in the format</p><h2 id="conclusion">Conclusion</h2><p>HTTP PATCH is a useful method for updating resources partially and incrementally. By sending only the changes you want to make, you can reduce the amount of data sent, improve performance, and reduce the risk of unintended consequences. If you&apos;re working with APIs or web applications that allow partial updates, consider using PATCH to optimize your requests.</p><h2 id="follow-me-for-more-web-development-content">Follow me for more Web Development content</h2><p>Keep posted if you want to grow your career as a Web Developer/Software Engineer as I&#x2019;m constantly updating content on my Blog <a href="www.unitcoding.com">Unit Coding</a> also follow me on Twitter as <a href="https://twitter.com/OscarOsempu?ref=unitcoding.com">Oscar Montenegro</a> where I&#x2019;m starting to post my #100DayOfCode journey.</p><p>Thanks for reading my article and I will see you on the next one, Happy coding everybody!</p>]]></content:encoded></item><item><title><![CDATA[Sorting Resources on your ASP NET Core Web API]]></title><description><![CDATA[<p>Hello my fellow developers, here we are on a new part of this Web API Development series, we continue with exciting topics like the last post about Filtering Data in our API. Today we will be learning about sorting resources on our API, the effect it can have in our</p>]]></description><link>https://unitcoding.com/sorting-resources-on-your/</link><guid isPermaLink="false">645284dc6358ae04c7ec3a5d</guid><category><![CDATA[ASP NET Core]]></category><category><![CDATA[REST API Development]]></category><category><![CDATA[Web API]]></category><dc:creator><![CDATA[Oscar Montenegro]]></dc:creator><pubDate>Wed, 03 May 2023 16:07:55 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1544383835-bda2bc66a55d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fHNvcnR8ZW58MHx8fHwxNjgzMTI5NjEw&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1544383835-bda2bc66a55d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fHNvcnR8ZW58MHx8fHwxNjgzMTI5NjEw&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Sorting Resources on your ASP NET Core Web API"><p>Hello my fellow developers, here we are on a new part of this Web API Development series, we continue with exciting topics like the last post about Filtering Data in our API. Today we will be learning about sorting resources on our API, the effect it can have in our systems, and the benefits that provides for the client. I&#x2019;ll teach you how you can sort your API resources and also will provide some useful code examples for you to follow along. So without further ado let&#x2019;s get our hands on the code!</p><h2 id="the-importance-of-sorting-resources-on-api">The Importance of Sorting Resources on API </h2><p>Sorting resources on an API is crucial for several reasons. Firstly, it enhances the user experience by making it easy to find information. By sorting resources, users do not have to scroll through pages of irrelevant information to find what they are looking for. Instead, they can quickly find the information they need and move on to other tasks.</p><p>Secondly, sorting resources on an API improves the performance of the application. By reducing the amount of data that needs to be loaded, the application loads faster, leading to a better user experience.</p><p>Thirdly, sorting resources on an API makes it easier for developers to maintain the application. When resources are sorted, developers can easily locate specific data and make changes where necessary.</p><h2 id="how-to-sort-resources-on-api">How to Sort Resources on API ?</h2><p>Sorting resources on an API may seem complicated, but it is relatively simple. Here are the steps to follow:</p><ol><li>Determine the field to sort by: The first step is to decide which field you want to sort by. For instance, if you are sorting products, you may choose to sort by price, product name, or product category.</li><li>Choose the sorting order: Once you have identified the field to sort by, you need to decide whether to sort in ascending or descending order. Ascending order means that the data is sorted from the smallest to the largest while descending order means that the data is sorted from the largest to the smallest.</li><li>Use the sorting parameter: Most APIs support a sorting parameter that allows users to sort resources. The sorting parameter is usually added to the end of the API URL and specifies the field to sort by and the sorting order. For instance, to sort products by price in ascending order, the URL may look like this: <code>https://example.com/api/products?sort=price:asc</code>.</li><li>Test the sorting functionality: Once you have implemented the sorting functionality, you need to test it to ensure that it works correctly. Testing involves trying out different sorting options and verifying that the data is sorted correctly.</li></ol><h2 id="clone-the-repo-from-github">Clone the repo from GitHub</h2><p>If you want to follow along I recommend you clone the API repository from GitHub and make sure you get the code from the &#x201C;Filtering&#x201D; branch as it contains the latest code changes up to this article.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Osempu/BlogAPI/tree/Filtering?ref=unitcoding.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - Osempu/BlogAPI at Filtering</div><div class="kg-bookmark-description">Contribute to Osempu/BlogAPI development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Sorting Resources on your ASP NET Core Web API"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">Osempu</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/1b5d888713539a0904a95ec49a4cb579fdc2c061ec5da8bfb26a1a0c4d889f5b/Osempu/BlogAPI" alt="Sorting Resources on your ASP NET Core Web API"></div></a></figure><h2 id="update-the-querypatameters-class">Update the QueryPatameters class </h2><p>Start by adding two new parameters to the <code>QueryParameters</code> class which holds all the parameters used to paginate, filter and now sort the API resources. Add an <code>OrderBy</code> parameter to specify the field to sort by and add another field named <code>OrderAsc</code> which states if the order is ascending if not it will be descending this will be true by default.</p><pre><code class="language-csharp">public class QueryParameters
{
    //Code Ommited for brevity

    //Sorting params
    public string OrderBy { get; set; } = string.Empty;
    public bool OrderAsc { get; set; } = true;
}
</code></pre><h2 id="add-sort-logic-to-postrepositoy-class">Add Sort logic to PostRepositoy Class </h2><p>Now go into the PostRepository class and add the sorting logic. First, you will check if the <code>OrderBy</code> parameter is not null and if not then proceed to check if the <code>OrderAsc</code> is true to set the order flow or order direction to ascending or descending depending on the case. And lastly call the <code>OrderBy</code> method to perform the sorting operation. But you will get an error because the <code>OrderBy</code> does not accept string as an argument so you have to install a new package to be able to work with dynamic Linq queries.</p><pre><code class="language-csharp">public async Task&lt;IEnumerable&lt;Post&gt;&gt; GetPostAsync(QueryParameters parameters)
{
    var allPosts = context.Posts.AsQueryable();

    //Filter by Author
    if(!string.IsNullOrEmpty(parameters.Author))
    {
        allPosts = allPosts.Where(x =&gt; x.Author == parameters.Author);
    }

    //Sort posts
    if(!string.IsNullOrEmpty(parameters.OrderBy))
    {
        string orderFlow = parameters.OrderAsc ? &quot;ascending&quot; : &quot;descending&quot;;
        allPosts = allPosts.OrderBy($&quot;{parameters.OrderBy} {orderFlow}&quot;);
    }

    //Paginated posts
    var pagedPosts = await allPosts
            .Skip((parameters.PageNumber - 1) * parameters.PageSize)
            .Take(parameters.PageSize)
            .ToListAsync();

    return pagedPosts;
}
</code></pre><h2 id="install-the-systemlinqdynamiccore-nuget-package">Install the System.Linq.Dynamic.Core Nuget package</h2><p>Proceed to install this Nuget package using the dotnet cli or the Nuget Package manager if you are using Visual Studio.</p><p><code>dotnet add package System.Linq.Dynamic.Core</code></p><p>This package will allow you to perform the sorting operation with the <code>OrderBy</code> method accepting a string as if it were a string query for example &#x201C;orderby &lt;parameter&gt; ascending&#x201D;. Now the error should be gone and you can take the API for a test for example you can set the <code>OrderBy</code> parameter to <code>Title</code> and it will order the posts by <code>Title</code> alphabetically or you can go and sort them by <code>CreatedDate</code> and will sort the posts by the date they were created. Also, you can set the <code>OrderAsc</code> parameter to true or false to set the order flow.</p><h2 id="updating-the-postresponsedto-class">Updating the PostResponseDTO class </h2><p>Now you can sort by <code>CreatedDate</code> but if you tested the API you noted that when the posts were returned they don&#x2019;t display this property so for that you have to update the <code>PostResponseDTO</code> to display the <code>CreatedDate</code> property so it makes sense when we sort by date. For that, you just have to add the <code>CreatedDate</code> property to the dto and that&#x2019;s it, now you can see the date when the post was created when getting a single post or a list of posts.</p><pre><code class="language-csharp">public record PostResponseDTO(int Id, string Author, string Title, string Body, DateTime CreatedDate);
</code></pre><h2 id="take-your-api-for-a-test">Take your API for a Test </h2><p>Now you should be able to see the created date displayed and the sorting functionality must be working as expected. Think about what properties you can add tot he <code>Post</code> that you can sort by that can enhance your sorting logic or your API in general.</p><h2 id="conclusion">Conclusion </h2><p>Sorting resources on an API is an essential aspect of application development. By sorting resources, users can quickly find the information they need, leading to a better user experience. Sorting resources also improves the performance of the application and makes it easier for developers to maintain it. By following the steps outlined in this article, you can easily sort resources on your API in a user-friendly manner.</p><h2 id="thanks-for-reading">Thanks for reading! </h2><p>As always thanks a lot for reading my articles and for following me on <a href="https://unitcoding.com/">my personal Blog</a>, on <a href="https://twitter.com/OscarOsempu?ref=unitcoding.com">Twitter</a>, and on my YouTube channel. I don&#x2019;t think that we can have a Friday API this week but I will work on something great for the next week so keep posted on that. Thanks and keep coding, see you on my next article!</p>]]></content:encoded></item><item><title><![CDATA[Filtering In Your ASP NET Core Web API: The Key to Efficient Data Retrieval]]></title><description><![CDATA[As the world becomes increasingly connected and data-driven, web APIs have become a critical component of modern applications. APIs, or Application Programming Interfaces, allow developers to interact with the data and functionality of other software systems, enabling them to build more powerful, integrated applications.]]></description><link>https://unitcoding.com/filtering-your-web-api-resources/</link><guid isPermaLink="false">644bd7266358ae04c7ec3a3d</guid><category><![CDATA[REST API Development]]></category><category><![CDATA[ASP NET Core]]></category><category><![CDATA[beginner]]></category><category><![CDATA[C#]]></category><category><![CDATA[Web API]]></category><category><![CDATA[Software Development]]></category><dc:creator><![CDATA[Oscar Montenegro]]></dc:creator><pubDate>Fri, 28 Apr 2023 15:02:25 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1514927298007-a2b56e5270e1?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDE2fHxGaWx0ZXJ8ZW58MHx8fHwxNjgyNjkzODg3&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1514927298007-a2b56e5270e1?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDE2fHxGaWx0ZXJ8ZW58MHx8fHwxNjgyNjkzODg3&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Filtering In Your ASP NET Core Web API: The Key to Efficient Data Retrieval"><p>Hello guys, I&#x2019;m so glad to be here one more day to bring you some more valuable knowledge. Today we will not have API Friday &#x1F972;, I know it&#x2019;s sad but something it takes me more time than expected to build the projects and to play around with the new API every week at the same time that I&#x2019;m creating content for the blog and some other daily life stuff. However today we will continue with our web API development series as we are getting our hands on some fun stuff, on the last article we were talking about pagination and its benefits for our application and the user experience, and today we will continue with a pretty similar topic as it is related. We will be talking about <strong><strong><strong><strong><strong><strong><strong><strong><strong>Filtering,</strong></strong></strong></strong></strong></strong></strong></strong></strong> why should you apply filtering, and as always a code example to continue to improve our <strong>Blog API</strong> so without further ado let&#x2019;s get into today&#x2019;s article.</p><h2 id="on-a-data-driven-world">On a Data-Driven World </h2><p>As the world becomes increasingly connected and data-driven, web APIs have become a critical component of modern applications. APIs, or Application Programming Interfaces, allow developers to interact with the data and functionality of other software systems, enabling them to build more powerful, integrated applications.</p><p>One important feature of many web APIs is filtering. Filtering refers to the process of selecting a subset of data from a larger dataset based on specific criteria. In the context of a web API, filtering allows developers to retrieve only the data they need, rather than having to retrieve and process large amounts of irrelevant data.</p><h2 id="what-is-filtering"><strong>What is filtering ?</strong></h2><p>Filtering is a process used to extract a subset of data from a larger dataset based on specific criteria. For example, if you were looking at a dataset of customer orders, you might want to filter the data to only show orders that were placed in the last month or orders that contained a specific product.</p><p>In a web API, filtering is typically accomplished by passing parameters to an API endpoint that specifies the criteria for selecting data. For example, you might use a parameter like <strong><code>?filter=last_month</code></strong> to retrieve only the data that meets the specified criteria.</p><p>Filtering can be applied to various types of data, including text, numbers, dates, and more. The specific criteria used for filtering depends on the nature of the data and the requirements of the application.</p><h2 id="why-is-filtering-important"><strong>Why is filtering important ?</strong></h2><p>Filtering is an important feature in web APIs for several reasons:</p><h3 id="reduced-data-transfer"><strong>Reduced data transfer </strong></h3><p>One of the primary benefits of filtering is reduced data transfer. When working with large datasets, retrieving all the data can be a slow and resource-intensive process. By filtering the data to only retrieve the necessary subset, developers can significantly reduce the amount of data that needs to be transferred and processed.</p><p>For example, if you&apos;re building an e-commerce application that needs to retrieve a list of products for sale, you might use filtering to retrieve only the products that are currently in stock. This would reduce the amount of data that needs to be transferred, making the application faster and more efficient.</p><h3 id="improved-performance"><strong>Improved performance </strong></h3><p>Filtering can also improve the performance of web APIs by reducing the amount of data that needs to be processed. When retrieving data from a database or other data source, filtering can allow the API to query only the relevant subset of data, rather than retrieving and processing the entire dataset.</p><p>For example, if you&apos;re building a social media application that needs to retrieve a list of posts from a user&apos;s friends, you might use filtering to only retrieve posts that were created in the last week. This would reduce the amount of data that needs to be processed, making the API faster and more responsive.</p><h3 id="increased-flexibility"><strong>Increased flexibility </strong></h3><p>Filtering also provides increased flexibility for developers. By allowing developers to select only the data they need, APIs can be more easily integrated with other applications and systems.</p><p>For example, if you&apos;re building a weather application that needs to retrieve temperature data from a weather API, you might use filtering to retrieve only the data for a specific geographic location. This would allow you to integrate weather data with other parts of your application, such as a map or a location-based search feature.</p><h3 id="improved-data-quality"><strong>Improved data quality </strong></h3><p>Finally, filtering can improve the quality of data returned by web APIs. By selecting only the relevant subset of data, developers can avoid including irrelevant or inaccurate data in their applications.</p><p>For example, if you&apos;re building a financial application that needs to retrieve stock prices from an API, you might use filtering to retrieve only the prices for a specific stock symbol. This would ensure that the data returned by the API is accurate and relevant to the application.</p><h2 id="clone-the-github-repo">Clone the GitHub repo </h2><p>As always if you want to follow along with the article clone the Blog API repository so you can have a hands-on experience applying filtering. Make sure you get the code from the <code>Pagination</code> branch as this contains the latest code up to this point.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Osempu/BlogAPI/tree/Pagination?ref=unitcoding.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - Osempu/BlogAPI at Pagination</div><div class="kg-bookmark-description">Contribute to Osempu/BlogAPI development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Filtering In Your ASP NET Core Web API: The Key to Efficient Data Retrieval"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">Osempu</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/1b5d888713539a0904a95ec49a4cb579fdc2c061ec5da8bfb26a1a0c4d889f5b/Osempu/BlogAPI" alt="Filtering In Your ASP NET Core Web API: The Key to Efficient Data Retrieval"></div></a></figure><h2 id="update-the-queryparameters-class">Update the QueryParameters Class </h2><p>In the last article, we created a class called <code>QueryParameters</code> that holds the pagination parameters such as <code>PageSize</code> and <code>PageNumber</code>, and now we will add a filtering parameter to be able to filter by an author so the class will end looking like this.</p><pre><code class="language-csharp">public class QueryParameters
{
    const int maxPageSize = 50;
    public int PageNumber { get; set; } = 1;
    private int pageSize = 10;
    public int PageSize
    {
        get { return pageSize; }
        set { pageSize = (value &gt; maxPageSize) ? maxPageSize : value; }
    }

    //Filtering params
    public string Author { get; set; } = string.Empty;
}
</code></pre><p>Everything is the same we just added the <code>Author</code> property at the end of the file and initialized it to an empty string.</p><h2 id="update-your-ipostrepository-and-postrepository-classes">Update your IPostRepository and PostRepository classes </h2><p>Once again we see ourselves in the need to update our <code>IPostRepository</code> and <code>PostRepository</code> classes to pass them the <code>QueryParameters</code> as a parameter instead of the raw params. This is to improve the way we add more and more parameters avoiding having a method with a lot of parameters being passed.</p><pre><code class="language-csharp">public interface IPostRepository 
{
    Task&lt;IEnumerable&lt;Post&gt;&gt; GetPostAsync(QueryParameters parameters);
}
</code></pre><pre><code class="language-csharp">public async Task&lt;IEnumerable&lt;Post&gt;&gt; GetPostAsync(QueryParameters parameters)
{
}
</code></pre><p>Now with this change in place, you can keep adding more and more params to the <code>QueryParameters</code> class without having to mess with the signature of any of both the interface and the class.</p><h2 id="applying-filtering-in-the-repository-class">Applying filtering in the repository class </h2><p>As with <code>Pagination</code> you want to apply the filtering in the repository class when you are querying the database for all our resources. Filtering should be applied before pagination because you want to filter against all the database resources, not after the data set is paginated.</p><pre><code class="language-csharp">public async Task&lt;IEnumerable&lt;Post&gt;&gt; GetPostAsync(QueryParameters parameters)
{
    var allPosts = context.Posts.AsQueryable();

    //Filter by Author
    if(!string.IsNullOrEmpty(parameters.Author))
    {
        allPosts = allPosts.Where(x =&gt; x.Author == parameters.Author);
    }

    var pagedPosts = await allPosts
            .Skip((parameters.PageNumber - 1) * parameters.PageSize)
            .Take(parameters.PageSize)
            .ToListAsync();

    return pagedPosts;
}
</code></pre><p>Filtering is added above pagination but before you need to check if the <code>Author</code> parameter is empty or null, as if it&#x2019;s empty it means the client is not asking for filtering, if not then you will retrieve only the posts where the author is the specified one. No call to the <code>ToListAsync</code> method is made on the query as you still need to paginate before actually executing the query to the database.</p><h2 id="test-your-api-filtering-by-author">Test your API filtering by Author </h2><p>Now take your web API to test the new filtering functionality, you should add some posts with the same author if you don&#x2019;t have any to actually see the filtering in action. Now this easy is how you add filtering to your web API, there are actually other ways to implement filtering, I showed you a pretty simple and straightforward to do it but if you look into the internet you will find some more crazy and improved ways to do it.</p><h2 id="conclusion">Conclusion </h2><p>Filtering is an essential and useful feature of Web APIS that allows developers to get subsets of data from a larger dataset based on some specific criteria. By implementing filtering in their web APIs. developers can reduce data transfer from the server to the client and we already know that this is always something that we want as this saves time, improves performance, consume fewer resources, and improves the user experience as he can demand to see only relevant data to him. But as with everything it is not a silver bullet and you should always consider if filtering is something that will actually improve your application and that it makes sense to have it or if it will just add more complexity and make no change.</p><h2 id="thanks-for-your-support-now-follow-me-on-social-media">Thanks for your support, now follow me on social media!</h2><p>As always thanks for reading my articles and I hope you are getting a lot from reading them for your daily coding and work. Now you can follow me on Twitter as <a href="https://twitter.com/OscarOsempu?ref=unitcoding.com">Oscar Montenegro</a> I&#x2019;m still new to Twitter so I don&#x2019;t have that many posts but I will be posting some content there so you know what I&#x2019;m up to in my daily life as a developer.</p><p>Thanks for everything and I hope you have an amazing weekend, enjoy it, take some time to rest and be with your loved ones, and as always, keep coding!</p>]]></content:encoded></item><item><title><![CDATA[Improve Your Web API Performance With Pagination]]></title><description><![CDATA[<p>Hello guys, today continuing with the ASP NET Core web API series we will review an exciting topic and that is <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>pagination</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong> I think that non of us are oblivious to pagination as in almost any website there is an implementation of this functionality say for example on Google Search</p>]]></description><link>https://unitcoding.com/web-api-pagination/</link><guid isPermaLink="false">6449b9b16358ae04c7ec3a15</guid><category><![CDATA[ASP NET Core]]></category><category><![CDATA[beginner]]></category><category><![CDATA[C#]]></category><category><![CDATA[REST API Development]]></category><category><![CDATA[Web API]]></category><dc:creator><![CDATA[Oscar Montenegro]]></dc:creator><pubDate>Thu, 27 Apr 2023 00:02:41 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1532153975070-2e9ab71f1b14?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fHBhZ2VzfGVufDB8fHx8MTY4MjU1MzMzMQ&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1532153975070-2e9ab71f1b14?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fHBhZ2VzfGVufDB8fHx8MTY4MjU1MzMzMQ&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Improve Your Web API Performance With Pagination"><p>Hello guys, today continuing with the ASP NET Core web API series we will review an exciting topic and that is <strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>pagination</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong> I think that non of us are oblivious to pagination as in almost any website there is an implementation of this functionality say for example on Google Search when you search for anything you get some results back and if you hit the bottom then you have a control where you select the next page to get more results in the case that you did not found what you were looking for and that is exactly what we want to implement in our web API today.</p><h2 id="what-is-pagination">What is pagination ?</h2><p>Pagination is a technique used in web APIs to break up a large set of data into smaller, more manageable pieces. This is achieved by limiting the number of results that we send back on each API response and providing a way for the client to request the next set of results.</p><p>In a typical implementation of pagination, the client sends a request to the server providing a certain number of results to be returned to per page and also the current page number.</p><h2 id="why-should-we-use-pagination-in-our-web-api">Why should we use pagination in our web API ?</h2><p>Pagination is commonly used in web APIs to improve performance and reduce the amount of data that must be transferred between the server and the client, especially when dealing with large datasets. Also improves user experience as small data chunks are more digestible than large datasets and help to prevent bad user experience on slow internet connections as it will not load the entire dataset only what is requested.</p><h2 id="clone-the-github-repo">Clone the GitHub repo</h2><p>Before starting to code remember that you can follow along with the tutorial, you just need to go to the GitHub repo and clone the <code>AsynchronousEndpoints</code> branch to get the latest changes up to this point.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Osempu/BlogAPI/tree/AsynchronousEndpoints?ref=unitcoding.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - Osempu/BlogAPI at AsynchronousEndpoints</div><div class="kg-bookmark-description">Contribute to Osempu/BlogAPI development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Improve Your Web API Performance With Pagination"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">Osempu</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/1b5d888713539a0904a95ec49a4cb579fdc2c061ec5da8bfb26a1a0c4d889f5b/Osempu/BlogAPI" alt="Improve Your Web API Performance With Pagination"></div></a></figure><h2 id="adding-query-parameters-support-to-the-get-endpoint">Adding query parameters support to the Get endpoint</h2><p>Currently, we call the <code>Get</code> endpoint and we get all the existing posts from the database so this is a great example of where we should implement pagination as the more our database grows the least likely we would like to return a large dataset.</p><p>The way the client will request the number of results and the page number is through query strings and ASP NET Core have a pretty simple way to deal with them using the <code>[FromQuery]</code> attribute int endpoint. This way we tell ASP NET Core to check the query string and then it will attempt to read the values from the query string and parse it into the parameter we specified.</p><pre><code class="language-csharp">[HttpGet]
public async Task&lt;IActionResult&gt; GetPost([FromQuery] int pageSize = 50, [FromQuery] int currentPage = 1)
{
    var posts = await repository.GetPostAsync(pageSize, currentPage);

    //code ommited for brevity
}
</code></pre><p>We passed the <code>pageSize</code> and the <code>currentPage</code> parameters both decorated with the</p><p><code>[FromQuery]</code> attribute so ASP NET Core attempts to read its values from the query string as we said before and both parameters have default values in case the user does not provide any and then we pass these parameters to the <code>GetPostAsync</code> method. Now you should be getting and error as this method does not accept any parameter and for that, we need to update the <code>IPostRepository</code> interface and <code>PostRepository</code> class.</p><h2 id="updating-the-ipostrepository-interface-and-postrepositoryclass">Updating the IPostRepository interface and PostRepositoryClass </h2><p>Now we need to update our interface and repo class respectively to support the pagination parameters</p><p>For the <code>IPostRepository</code> interface, we only need to define two parameters <code>pageSize</code> and <code>pageNumber</code>.</p><pre><code class="language-csharp">public interface IPostRepository 
{
    Task&lt;IEnumerable&lt;Post&gt;&gt; GetPostAsync(int pageSize, int pageNumbe);
		//Code omitted for brevity
}
</code></pre><p>And for the post repository, we will implement the interface signature supporting the same parameters. Now all that is left is to actually implement the pagination functionality.</p><pre><code class="language-csharp">public async Task&lt;IEnumerable&lt;Post&gt;&gt; GetPostAsync(int pageSize, int pageNumber)
{
		//Code omitted for brevity
}
</code></pre><h2 id="implementing-pagination-in-postrepository-class">Implementing pagination in PostRepository class </h2><pre><code class="language-csharp">public async Task&lt;IEnumerable&lt;Post&gt;&gt; GetPostAsync(int pageSize, int pageNumber)
{
    var allPosts = context.Posts.AsQueryable();

    var pagedPosts = await allPosts
                            .Skip((pageNumber - 1) * pageSize)
                            .Take(pageSize)
                            .ToListAsync();

    return pagedPosts;
}
</code></pre><p>You may get tempted to do this in the Post controller after getting all the posts but the idea behind pagination is to limit the number of resources the database return and this needs to be done in the repository class because that&#x2019;s where we are calling the database.</p><p>First, we make a call to all the posts but as a queryable type, this means that we are asking for all the posts existing in the database but the LINQ query has not been executed yet, this helps us to save resources as we are still building the query, then we make another query to all the posts. We call the skip method to skip the previous pages in case the client is asking to see for example page 3 or 8, then we take a specific amount of posts to show to the user, this is specified by the <code>pageSize</code> parameter and finally, we call the <code>ToListAsync()</code> method to execute the query and return a list of posts.</p><p>Now you can run the app and start testing the pagination, if you are using Swagger then you will see two new parameters which are the query params that you can enter for <code>pageSize</code> and <code>pageNumber</code>, and when you execute the call the request URL should look similar to this</p><p><strong><code>http://localhost:5049/api/post?pageSize=10&amp;currentPage=1</code></strong></p><p>so you should be getting 10 posts from the first page.</p><h2 id="the-problem-with-this-approach">The problem with this approach</h2><p>You must be thinking that this is all and we can move on right? well, spoiler alert, we can&#x2019;t. The thing is that this solution does not scale well as we need to provide some default values for the query parameters in the case that the user does not provide them, although we can do that on the parameters imagine later we want to filter in our search that&#x2019;s another parameter to pass, no think about sorting, we would end up with our endpoint having a lot of parameters to set and we know that&#x2019;s not something good neither scalable that&#x2019;s why we need to refactor our solution to make it more scalable for future changes.</p><p>Let&#x2019;s create a new model class called <code>QueryParameters</code>, this class will hold all the parameters we need for pagination and for future changes in our API.</p><pre><code class="language-csharp">public class QueryParameters
{
  const int maxPageSize = 50;
  public int PageNumber { get; set; } = 1;
  private int pageSize = 10;
  public int PageSize
  {
      get { return pageSize; }
      set { pageSize = (value &gt; maxPageSize) ? maxPageSize : value; }
  }
}
</code></pre><p>Now with the aid of this class, we will hold all the parameters we need for the pagination and future functionality to work. We are defining the max size the page can have, we set the page to a default value of 1 in the case the user does not provide the page to display and lastly we set the page size to a default value of 10 or whatever the user defines.</p><h2 id="implementing-the-new-approach">Implementing the new approach</h2><pre><code class="language-csharp">[HttpGet]
public async Task&lt;IActionResult&gt; GetPost([FromQuery] QueryParameters parameters)
{
    var posts = await repository.GetPostAsync(parameters.PageSize, parameters.PageNumber);

    var postsDto = mapper.Map&lt;IEnumerable&lt;PostResponseDTO&gt;&gt;(posts);

    logger.LogDebug($&quot;Get method called, got {postsDto.Count()} results&quot;);
    return Ok(postsDto);
}
</code></pre><p>If you run the app it will be running as before but now we have an improved version for when we add filtering and other parameters to enhance our endpoint.</p><h2 id="conclusion">Conclusion</h2><p>Pagination is a powerful technique used to improve the user experience while saving server resources as we do not return all the data available, avoiding bottlenecks and performance problems over slow connections. As with all programming techniques, paging must be used wisely as in not every project it will make sense to apply it, for example, in an analytics service, in that context it makes sense to return hundreds if not thousands of records as the more data you have at hand the more reliable and precise this service becomes.</p>]]></content:encoded></item><item><title><![CDATA[Build a Google Translate Clone with Blazor and .NET]]></title><description><![CDATA[<p>Hello guys, it&#x2019;s Friday and you know what it means right? Yeah, it&#x2019;s API Friday so I guess I should have started saying <strong>H-API Friday</strong> to you all (<em>ba dum tss</em>). I&#x2019;m really excited about the project that I got between hands for you.</p>]]></description><link>https://unitcoding.com/create-your-own-google-translator-clone-with-blazor/</link><guid isPermaLink="false">6441b61e6358ae04c7ec3995</guid><category><![CDATA[API Friday]]></category><category><![CDATA[ASP NET Core]]></category><category><![CDATA[Blazor]]></category><category><![CDATA[beginner]]></category><category><![CDATA[C#]]></category><dc:creator><![CDATA[Oscar Montenegro]]></dc:creator><pubDate>Fri, 21 Apr 2023 16:32:52 GMT</pubDate><media:content url="https://unitcoding.com/content/images/2023/04/Web-capture_20-4-2023_171010_ambitious-dune-0cdb0b80f.3.azurestaticapps.net.jpeg" medium="image"/><content:encoded><![CDATA[<img src="https://unitcoding.com/content/images/2023/04/Web-capture_20-4-2023_171010_ambitious-dune-0cdb0b80f.3.azurestaticapps.net.jpeg" alt="Build a Google Translate Clone with Blazor and .NET"><p>Hello guys, it&#x2019;s Friday and you know what it means right? Yeah, it&#x2019;s API Friday so I guess I should have started saying <strong>H-API Friday</strong> to you all (<em>ba dum tss</em>). I&#x2019;m really excited about the project that I got between hands for you. I did my best to present you something with almost full functionality something you can showcase in your developer portfolio if you are a beginner, and don&#x2019;t worry I will start to create some projects for intermediate and advanced developers just have a little patience as I&#x2019;m focusing right now on new .NET developers.</p><p>Today&#x2019;s project is a clone of the <strong>google translate app</strong> using Google&#x2019;s translate API v2. I&#x2019;m a visual person so today I will present you with a nice-looking application, however, it will not only be a &#x201C;pretty &#x201C; app it will also translate text, detect a language based on the user input, display the supported languages, and swap user input with translation result. So if you are as excited as I am to start coding let&#x2019;s go for it!</p><h2 id="google-translate-api-setup">Google Translate API Setup </h2><p>First, you need to follow some steps in order to be able to use the Google Translate API.</p><ol><li>Create a Google account or use your existing account if any</li><li>Access google cloud</li><li>Go to the google cloud console</li><li>Create a new project and name it whatever you want mine was named <code>Google Translate Clone</code></li><li>Access your and look for <code>Cloud Translation API</code></li><li>Enable the API and it will ask you to enable billing in your account</li><li>Enable billing as well (don&#x2019;t worry we will not spend a penny on this project)</li><li>In your project view go to <code>APIs and services</code> &gt; <code>Credentials</code></li><li>Select <code>Create Credentials</code> and then select <code>API Key</code></li></ol><p>After you have followed these steps you can start using your API key for this and many other projects.</p><p>If for some reason you failed to follow the steps and need further help you can watch <a href="https://www.youtube.com/watch?v=1wcE-DfqNtU&amp;ab_channel=Bohemicus&amp;ref=unitcoding.com">this video</a> where he follows the same steps I listed above but you can see the Google Cloud interface and appreciate it more visually.</p><h3 id="alternative-to-accessing-google-cloud">Alternative to accessing Google Cloud </h3><p>if you don&#x2019;t like the idea of accessing Google Cloud and enabling a billing account you can access <a href="https://rapidapi.com/hub?ref=unitcoding.com">Rapid API</a> which is an API marketplace where you can find tons of APIs to use, you would need to create an account and then look for the Google Translate API and subscribe for free after this you will have access to the credentials Rapid API provides you without you having to access Google Cloud or enable a billing account but you would need to send two special headers on every request but don&#x2019;t worry Rapid API got you covered and actually provides you with an example call so you know how to call the API from their host and it will look something like this</p><pre><code class="language-csharp">var client = new HttpClient();
var request = new HttpRequestMessage
{
	Method = HttpMethod.Post,
	RequestUri = new Uri(&quot;&lt;https://google-translate1.p.rapidapi.com/language/translate/v2/detect&gt;&quot;),
	Headers =
	{
		{ &quot;X-RapidAPI-Key&quot;, &quot;YOUR_API_KEY&quot; },
		{ &quot;X-RapidAPI-Host&quot;, &quot;google-translate1.p.rapidapi.com&quot; },
	},
	Content = new FormUrlEncodedContent(new Dictionary&lt;string, string&gt;
	{
		{ &quot;q&quot;, &quot;English is hard, but detectably so&quot; },
	}),
};
using (var response = await client.SendAsync(request))
{
	response.EnsureSuccessStatusCode();
	var body = await response.Content.ReadAsStringAsync();
	Console.WriteLine(body);
}
</code></pre><h2 id="create-a-new-blazor-webassembly-app">Create a new Blazor WebAssembly App </h2><p>Now that you have access to the Google Translate API let&#x2019;s start creating a new blazor wasm app with the aid of the dotnet cli.</p><p><code>dotnet new blazorwasm-empty -o GoogleTranslateClone</code></p><p>As always go to your <code>wwwroot&gt;Index.html</code> file and uncomment your scoped CSS stylesheet as by default this line is always commented and you have to enable it by yourself.</p><pre><code class="language-csharp">&lt;link href=&quot;GoogleTranslateClone.styles.css&quot; rel=&quot;stylesheet&quot; /&gt;
</code></pre><h2 id="add-the-models-to-store-the-data">Add the Models to store the data </h2><p>We need some models to store the data that we are getting back from the web API calls so let&#x2019;s add a folder called <code>Models</code> and let&#x2019;s create the following model classes.</p><pre><code class="language-csharp">public class Language
{
    [JsonPropertyName(&quot;language&quot;)]
    public string language { get; set; }

    [JsonPropertyName(&quot;name&quot;)]
    public string name { get; set; }
}

public class TranslatedText
{
    [JsonPropertyName(&quot;translatedText&quot;)]
    public string translatedText { get; set; }
}
</code></pre><p>We added a <code>Language</code> model to store the collection of supported languages from the API and the <code>TranslatedText</code> class to store the response from the translation endpoint. We are using the <code>JsonpropertyName</code> to map the JSON response to our model properties on deserialization.</p><h2 id="create-googletranslateclient-class">Create GoogleTranslateClient class </h2><p>As we are calling a web API we need a client class that consumes its endpoints so for that reason let&#x2019;s add a new folder called <code>Client</code> and inside it we will create the <code>GoogleTranslateClient</code> class.</p><pre><code class="language-csharp">public class GoogleTranslateClient
{
    private const string baseAddress = &quot;&lt;https://translation.googleapis.com/language/translate/v2&gt;&quot;;
    
		private readonly HttpClient client;

    public GoogleTranslateClient(HttpClient client)
    {
        this.client = client;
    }
}
</code></pre><p>We start by adding a constant that will hold the base address of the client which is the Google API address. After this, we add a constructor and pass an <code>HttpClient</code> as a parameter to instantiate the client via dependency injection in the <code>Program</code> class.</p><p>Now this is not everything but I don&#x2019;t want to throw a bunch of lines of code in front of you and expect you to understand it all like that. So I will explain every method of the client separately.</p><h3 id="getsupportedlanguages-methods">GetSupportedLanguages methods</h3><p>With this method as the name suggests we intend to get a collection of the languages the Google API supports.</p><pre><code class="language-csharp">public async Task&lt;Dictionary&lt;string,Language&gt;&gt; GetSupportedLanguages()
{
    var queryParams = new Dictionary&lt;string, string&gt;()
    {
        [&quot;key&quot;] = &quot;YOUR_API_KEY&quot;,
        [&quot;target&quot;] = &quot;en&quot;
    };

    var uri = QueryHelpers.AddQueryString($&quot;{baseAddress}/languages&quot;, queryParams);

    var response = await client.GetAsync(uri);
    string content = await response.Content.ReadAsStringAsync();

    var data = JsonObject.Parse(content);
    var languagesNode = data[&quot;data&quot;][&quot;languages&quot;];
    var languages = JsonSerializer.Deserialize&lt;List&lt;Language&gt;&gt;(languagesNode)
                        .ToDictionary(x =&gt; x.language);
    return languages;
}
</code></pre><p>Nothing super special or out of the world we start by creating a string dictionary to store the API key and the target language. We use the QueryHelpers class to add the query string seamlessly just passing the address and the query params as parameters but in order to use the QueryHelpers class you need to install a Microsoft library so prepare your terminal to use the dotnet cli.</p><p><code>dotnet add package Microsoft.AspNetCore.WebUtilities</code></p><p>Now you should be able to use it without getting any errors. Then we send the request and parse it to a string as always. Now here comes the hacky stuff, in order to avoid creating a bunch of models to get the languages data I work directly with the JSON nodes and dive into its properties to get the languages to finally just deserialize into a list and call the <code>ToDictionary</code> method to return a Dictionary.</p><h3 id="detectlanguage-method">DetectLanguage method</h3><p>Have you ever found a piece of text that you would like to translate but don&#x2019;t know in which language is it written? well, what this method does is detect the language based on the input the user gives.</p><pre><code class="language-csharp">public async Task&lt;Language&gt; DetectLanguage(string input)
{
    var queryParams = new Dictionary&lt;string, string&gt;()
    {
        [&quot;key&quot;] = &quot;YOUR_API_KEY&quot;,
        [&quot;q&quot;] = input
    };

    var uri = QueryHelpers.AddQueryString($&quot;{baseAddress}/detect&quot;, queryParams);

    var response = await client.PostAsync(uri, null);
    var content = await response.Content.ReadAsStringAsync();

    JsonNode data = JsonNode.Parse(content);
    JsonNode languageNode = data[&quot;data&quot;][&quot;detections&quot;][0][0];
    Language language = JsonSerializer.Deserialize&lt;Language&gt;(languageNode);

    return language;
}
</code></pre><p>We start creating the same string dictionary to store the API key and in this case, we pass the parameter <code>q</code> which is the user input to analyze and detect the source language. Everything is the same, we call the <code>QueryHelpers</code> class to pass the query strings, send the post request and read the response as a string to parse into a JsonNode to manipulate the node data manually and deserialize into a Language object and proceed to return it.</p><h2 id="translate-method">Translate method</h2><p>Finally, the method to translate the input from the client to the desired language.</p><pre><code class="language-csharp">public async Task&lt;TranslatedText&gt; Translate(string input, string source, string target)
{
    var queryParams = new Dictionary&lt;string, string&gt;()
    {
        [&quot;key&quot;] = &quot;YOUR_API_KEY&quot;,
        [&quot;q&quot;] = input,
        [&quot;target&quot;] = target,
        [&quot;source&quot;] = source
    };

    var uri = QueryHelpers.AddQueryString(baseAddress, queryParams);

    var response = await client.PostAsync(uri, null);
    var content = await response.Content.ReadAsStringAsync();

    JsonNode data = JsonNode.Parse(content);
    JsonNode translateNode = data[&quot;data&quot;][&quot;translations&quot;][0];
    TranslatedText translation = JsonSerializer.Deserialize&lt;TranslatedText&gt;(translateNode);

    return translation;
}
</code></pre><p>This method takes three parameters, the input which is the sentence to translate, the language in which the sentence is written, and the target language to translate.</p><p>We pass these three parameters as query strings in the <code>queryParams</code> dictionary and use the <code>QueryHelpers</code> class to pass the query params to the request. We perform the post request and parse the response to a string to finally parse into a JSON node to get into its properties and get the translated text.</p><p>This is it for the <code>GoogleTranslateClient</code> so let&#x2019;s add it to the services collection in the <code>Program</code> class.</p><pre><code class="language-csharp">builder.Services.AddScoped&lt;GoogleTranslateClient&gt;();
</code></pre><h2 id="add-markup-to-indexrazor-file">Add markup to Index.razor file </h2><p>This is our main file so we will add all the markup here, we will not be creating any components although we could have as we will have some repeated markup for this example we did it all inside a single file without components but you can definitely do it and improve the app in many ways.</p><pre><code class="language-csharp">&lt;div class=&quot;container&quot;&gt;
    &lt;h1&gt;Blazor Translate&lt;/h1&gt;
    &lt;div class=&quot;wrapper&quot;&gt;
        &lt;ul class=&quot;controls&quot;&gt;
            &lt;li class=&quot;row from&quot;&gt;
                &lt;select name=&quot;language-select&quot; title=&quot;language-select&quot; @bind=&quot;@sourceLanguage&quot;&gt;
                    &lt;option value=&quot;&quot;&gt;Detect Language&lt;/option&gt;
                    @foreach (var language in supportedLanguages)
                    {
                        &lt;option value=&quot;@language.Key&quot;&gt;@language.Value.name&lt;/option&gt;
                    }
                &lt;/select&gt;
            &lt;/li&gt;

            &lt;li class=&quot;exchange&quot; @onclick=&quot;@ChangeSourceToTarget&quot;&gt;&lt;i class=&quot;fas fa-exchange-alt&quot;&gt;&lt;/i&gt;&lt;/li&gt;

            &lt;li class=&quot;row to&quot;&gt;
                &lt;select name=&quot;language-select&quot; title=&quot;language-select&quot; @bind=&quot;@targetLanguage&quot;&gt;
                    @foreach (var language in supportedLanguages)
                    {
                        &lt;option value=&quot;@language.Key&quot;&gt;@language.Value.name&lt;/option&gt;
                    }
                &lt;/select&gt;
            &lt;/li&gt;
        &lt;/ul&gt;

        &lt;div class=&quot;text-input&quot;&gt;
            &lt;textarea class=&quot;from-text&quot; name=&quot;&quot; id=&quot;&quot; cols=&quot;30&quot; rows=&quot;10&quot; placeholder=&quot;Enter Text&quot;
                @bind=&quot;@sourceText&quot;&gt;&lt;/textarea&gt;
            &lt;textarea class=&quot;to-text&quot; name=&quot;&quot; id=&quot;&quot; cols=&quot;30&quot; rows=&quot;10&quot; readonly disabled placeholder=&quot;Translation&quot;
                @bind=&quot;@translatedText&quot;&gt;&lt;/textarea&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;detected-text&quot;&gt;
        @if (!string.IsNullOrEmpty(notificationText))
        {
            &lt;p&gt;@notificationText&lt;/p&gt;
        }
    &lt;/div&gt;
    &lt;button @onclick=&quot;@Translate&quot;&gt;Translate Text&lt;/button&gt;
&lt;/div&gt;
</code></pre><p>We define some basic HTML markup but there are some parts that I would like to point out and that is that we are populating the select controls using the supported languages method using a foreach loop to create an option tag for every supported language.</p><p>Also, we added a button to change the source text with the target text, this is to swap the content to translate with the translated content.</p><p>There are two <code>textarea</code> controls to input the text to translate and to display the translation, below this, we have a notification to display some messages for example to input a valid text if the textarea is empty or to notify the user when a text is translated from a language and finally a button to execute the translation.</p><h2 id="add-the-code-to-the-indexrazor-file">Add the code to the Index.razor file</h2><pre><code class="language-csharp">@code {
    private string sourceLanguage;
    private string targetLanguage = &quot;en&quot;;
    private string sourceText;
    private string translatedText;
    private string notificationText;

    private Dictionary&lt;string, Language&gt; supportedLanguages = new Dictionary&lt;string, Language&gt;();

    protected override async Task OnInitializedAsync()
    {
        supportedLanguages = await GetSupportedLanguages();
    }

    private async Task&lt;Dictionary&lt;string, Language&gt;&gt; GetSupportedLanguages()
    =&gt; await client.GetSupportedLanguages();

    private async Task&lt;Language&gt; DetectLanguage(string input)
    =&gt; await client.DetectLanguage(input);

    private async Task Translate()
    {
        notificationText = string.Empty;
        if(string.IsNullOrEmpty(sourceText))
        {
            notificationText = &quot;Insert a valid text to translate&quot;;
        }
        else if (string.IsNullOrEmpty(sourceLanguage))
        {
            Language detectedLanguage = await DetectLanguage(sourceText);
            var translationResult = await client.Translate(sourceText, detectedLanguage.language, targetLanguage);
            translatedText = translationResult.translatedText;
            if (supportedLanguages.TryGetValue(detectedLanguage.language, out Language language))
            {
                notificationText = $&quot;Detected from {language.name}&quot;;
            }
        }
        else
        {
            var translationResult = await client.Translate(sourceText, sourceLanguage, targetLanguage);
            string decodedString = HttpUtility.HtmlDecode(translationResult.translatedText);
            translatedText = decodedString;
        }
    }

    private void ChangeSourceToTarget()
    {
        string tempSource = &quot;&quot;;
        string temptext = &quot;&quot;;

        tempSource = sourceLanguage;
        temptext = sourceText;

        if (string.IsNullOrEmpty(tempSource))
        {
            tempSource = &quot;en&quot;;
        }

        sourceLanguage = targetLanguage;
        sourceText = translatedText;

        targetLanguage = tempSource;
        translatedText = temptext;
    }
}
</code></pre><p>At the top, we define some fields to store the values of the select controls and text areas and we initialize a <code>SupportedLanguages</code> property and populate it in the life cycle method <code>OnInitializedAsync</code> with the aid of the <code>GetSupportedLanguages</code> method which as we remember returns a dictionary containing the supported languages.</p><p>The detect language method does a call to the client detect language method and returns the language code. Now the translate method is where almost all the magic happens, we set the <code>notificationText</code> field to empty as we want to clear any old messages then we check if the <code>sourceText</code> property is not empty (which is the text to translate), if it is then we display an error message then we proceed to check if the <code>sourceLanguage</code> is not empty (this is the language of the text we want to translate), but if it&#x2019;s empty then this means we want to detect the language so we call the detect language function and return the language in which it is written, then we proceed to translate the text now that we know the source language, decode the response as the response contains some HTML codes and finally, we check in the supported languages dictionary to look for the name of the detected language as the detect language function return the language code (eg. en, es, de, fr) but not the actual name, so once we know the language we print a notification displaying the language from which the text was translated. Following with the last case of the conditional statement if both the <code>sourceLanguage</code> and <code>sourceText</code> are not empty then we proceed to perform a normal translation without any additional tasks.</p><p>The final method is actually a utility method to swap the left side of the translate app with the right side so for that we define some temporary variables and start swapping values, we have a conditional statement checking if the select control from the left side was empty then we will change its value to &#x201C;en&#x201D; this is because we cannot send an empty value to the <code>targetLanguage</code> as this would cause an error because we need to know the target language always, then we continue with the swap and that&#x2019;s it.</p><h2 id="adding-styling-to-the-app">Adding styling to the app</h2><p>The app is ready to work and rock but it still looks ugly so we will start adding some styling. Let&#x2019;s begin by adding a style link in the <code>index.html</code> file to use font awesome to add some icons.</p><pre><code class="language-csharp">&lt;link rel=&quot;stylesheet&quot; href=&quot;&lt;https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css&gt;&quot; integrity=&quot;sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==&quot; crossorigin=&quot;anonymous&quot; referrerpolicy=&quot;no-referrer&quot; /&gt;
</code></pre><h3 id="add-styling-to-the-body-element-in-appcss">Add styling to the body element in app.css</h3><p>Let&#x2019;s go to our global CSS stylesheet and add a bit of styling.</p><pre><code class="language-css">body {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    background: #3A4454;
}
</code></pre><h3 id="style-the-indexrazor">Style the Index.razor</h3><p>Now let&#x2019;s add the main styling to our razor page for this, you need to create a new CSS file named <code>Index.razor.css</code> so once you did this you can add your scoped styling.</p><pre><code class="language-css">* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: &apos;Segoe UI&apos;, Tahoma, Geneva, Verdana, sans-serif;
}

.container {
    width: 100%;
    background: #fff;
    border-radius: 10px;
    padding: 30px;
    text-align: center;
}

.wrapper {
    border-radius: 5px;
    border: 1px solid #bbb;
}

.wrapper .text-input {
    display: flex;
}

.text-input .to-text {
    border-left: 1px solid #bbb;
    border-radius: 0px;
    background-color: #f7f7f7;
}

.text-input textarea {
    height: 250px;
    width: 100%;
    border: none;
    outline: none;
    resize: none;
    font-size: 30px;
    border-radius: 5px;
    background: none;
    padding: 10px 15px;
}

textarea::placeholder {
    font-size: 30px;
    color: #878787;
    font-weight: 400;
}

.controls , li{
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.controls, li, .icons , .icons i{
    display: flex;
    align-items: center;
    justify-content: space-around;
}

.controls {
    list-style: none;
    padding: 12px 15px;
    border-bottom: 1px solid #bbb;
}

.controls .row select {
    border: none;
    outline: none;
    font-size: 18px;
    background: none;
}

select {
    cursor: pointer;
}

.controls .exchange {
    color: #9f9f9f;
    font-size: 16px;
    cursor:pointer;
}

.exchange {
    border-radius: 50%;
    border: 1px solid #ddd;
    padding: 15px;
}

.detected-text {
    text-align: start;
    margin-left: 10px;
}

.container button {
    width: 100%;
    padding: 14px;
    margin-top: 20px;
    border: none;
    outline: none;
    cursor: pointer;
    border-radius: 5px;
    font-size: 17px;
    background-color: #007bff;
    color: #fff;
}
</code></pre><h2 id="ready-to-test-your-app">Ready to test your app </h2><p>This is it now you should have a fully working clone of Google Translate. As I told you at the beginning you can detect languages, get a collection of the languages supported by the API and translate sentences from one language to another, the app is not perfect and can have some improvements but <strong>I had tons of fun building it</strong> and I hope you did as well.</p><h2 id="check-out-the-repo-on-github">Check out the repo on GitHub </h2><p>If you had any trouble or I had a typo you can check out the repository on GitHub.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Osempu/GoogleTranslateClone?ref=unitcoding.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - Osempu/GoogleTranslateClone</div><div class="kg-bookmark-description">Contribute to Osempu/GoogleTranslateClone development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Build a Google Translate Clone with Blazor and .NET"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">Osempu</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/9bd86262bfa6992910720834895a7cc4ca49a3cada81daa384e2c1163b2cba6d/Osempu/GoogleTranslateClone" alt="Build a Google Translate Clone with Blazor and .NET"></div></a></figure><h2 id="check-out-the-live-version">Check out the live version </h2><p>There is also a live version of this app hosted for free as an Azure Static Web App you can check it out <a href="https://ambitious-dune-0cdb0b80f.3.azurestaticapps.net/?ref=unitcoding.com">here</a></p><h2 id="thanks-for-your-reading-and-for-your-support">Thanks for your reading and for your support! </h2><p>As always thanks for reading my post and for your kind words and support with your thumbs up. I had a great time coding this app and hope you enjoy it and it helped you to learn more about blazor and C#, when I was learning these were the kind of tutorials that I wish I had found that are fun to code and have a bunch of code to learn from. Keep posted as I will continue posting projects like these using ASP NET Core technologies (Blazor, MVC, razor pages, etc) that will be really cool as we progress and they will begin to get harder and harder as we go.</p><p>Remember to follow me on my blog <a href="https://www.notion.so/Devsamples-com-2f903e4d84fa4c09b703fe91ac532b21?ref=unitcoding.com">Unit Coding</a> and on my youtube channel under the same name <a href="https://www.youtube.com/@unitcoding6783?ref=unitcoding.com">Unit Coding</a> as I post content every week.</p><p>Thanks for everything guys I hope you have a great weekend and keep coding!</p>]]></content:encoded></item><item><title><![CDATA[The Power of Asynchronous Code in your web API]]></title><description><![CDATA[<p>Hello my fellow developers, on the last article I showed you <a href="https://unitcoding.com/validation-to-web-api/">how to add data validation</a> using the fluent validation Nuget package. We discussed the relevance of implementing data validation for our API and for many other kinds of projects and also we saw how easy it was to implement</p>]]></description><link>https://unitcoding.com/the-power-of-asynchronous-code-in-you-web-api/</link><guid isPermaLink="false">64407c616358ae04c7ec3968</guid><category><![CDATA[ASP NET Core]]></category><category><![CDATA[beginner]]></category><category><![CDATA[C#]]></category><category><![CDATA[REST API Development]]></category><category><![CDATA[Web API]]></category><dc:creator><![CDATA[Oscar Montenegro]]></dc:creator><pubDate>Wed, 19 Apr 2023 23:59:43 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1513346940221-6f673d962e97?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDUwfHxzdHJpbmdzJTIwYXJ0fGVufDB8fHx8MTY4MTk0ODE0MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1513346940221-6f673d962e97?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDUwfHxzdHJpbmdzJTIwYXJ0fGVufDB8fHx8MTY4MTk0ODE0MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="The Power of Asynchronous Code in your web API"><p>Hello my fellow developers, on the last article I showed you <a href="https://unitcoding.com/validation-to-web-api/">how to add data validation</a> using the fluent validation Nuget package. We discussed the relevance of implementing data validation for our API and for many other kinds of projects and also we saw how easy it was to implement yet the benefits are huge.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://unitcoding.com/validation-to-web-api/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Data validation with Fluent Validation for ASP NET Core</div><div class="kg-bookmark-description">Hello guys, welcome to another chapter of this series on API Development with ASP NET Core. In the last article, we talk about data mapping using auto mapper and I showed you how to implement data mapping from installing auto mapper to creating the mapping profiles and injecting auto mapper</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://unitcoding.com/content/images/size/w256h256/2023/03/Copy-of-Unit-1.png" alt="The Power of Asynchronous Code in your web API"><span class="kg-bookmark-author">Unit Coding</span><span class="kg-bookmark-publisher">Oscar Montenegro</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://images.unsplash.com/photo-1559131397-f94da358f7ca?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDZ8fGNoZWNrJTIwaW58ZW58MHx8fHwxNjgxNDIyNDcw&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="The Power of Asynchronous Code in your web API"></div></a></figure><p>Today I will teach you how you can implement asynchronous code for your web API, you will see how easy it is and how you will leverage the power of asynchronous code for your app. But before we can start coding we need to understand what is asynchronous programming and what uses it have. So without further ado let&#x2019;s get into today&#x2019;s article.</p><h2 id="what-is-asynchronous-programming">What is asynchronous programming?</h2><p>Software development has two primary paradigms when it comes to handling tasks: synchronous and asynchronous programming. Synchronous programming executes tasks one after the other, in a predetermined order. On the other hand, asynchronous programming enables the execution of multiple tasks simultaneously, without waiting for the previous task to finish. This article will dive deeper into asynchronous programming, its importance, and its various uses.</p><h2 id="why-is-asynchronous-programming-important">Why is Asynchronous Programming Important?</h2><p>Asynchronous programming is essential for improving the performance and responsiveness of software applications. It is particularly useful for applications that require heavy data processing or network communication. By allowing multiple tasks to execute simultaneously, applications can run more efficiently and effectively. It is beneficial because it eliminates the need to wait for each task to complete before moving on to the next one.</p><p>Another advantage of asynchronous programming is its ability to handle long-running tasks without blocking the application&apos;s main thread. When a task takes a long time to complete, synchronous programming can cause the application to become unresponsive or even crash. Asynchronous programming enables applications to keep functioning normally while long-running tasks are processed in the background, thereby improving the overall user experience.</p><h2 id="what-uses-does-asynchronous-programming-have">What Uses Does Asynchronous Programming Have?</h2><p>Asynchronous programming has a wide range of uses in software development. One of its primary uses is in web development, where it handles requests and responses from servers. By using asynchronous programming, web applications can process multiple requests simultaneously, improving the overall performance and user experience.</p><p>Mobile app development is another area where asynchronous programming is commonly used. It handles tasks such as data synchronization, database access, and network communication. As a result, mobile apps can continue to function smoothly and responsively even when performing complex tasks in the background.</p><p>Asynchronous programming is also useful in gaming, artificial intelligence, and machine learning. These applications require the processing of multiple tasks simultaneously, which can be achieved through asynchronous programming. It helps to improve the performance and efficiency of these applications, leading to better overall results.</p><h2 id="clone-the-repo-on-github">Clone the repo on GitHub</h2><p>Before starting if you want to follow along with this tutorial you can clone the GitHub repository and make sure you get the code from the <code>FluentValidation</code> branch which contains the latest code changes up to this point.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Osempu/BlogAPI/tree/FluentValidation?ref=unitcoding.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - Osempu/BlogAPI at FluentValidation</div><div class="kg-bookmark-description">Contribute to Osempu/BlogAPI development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="The Power of Asynchronous Code in your web API"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">Osempu</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/7fe47e63175141a289a69b3d9dba70dfa3a4e46465250cdb8a8ae97328c5192f/Osempu/BlogAPI" alt="The Power of Asynchronous Code in your web API"></div></a></figure><h2 id="update-the-ipostrepository-interface">Update the IPostRepository interface</h2><p>We need to update the post repository class to access the database asynchronously but before we can do that we actually need to update the <code>IPostRepository</code> interface as it defines the contract the repository class needs to comply.</p><pre><code class="language-csharp">public interface IPostRepository 
{
    Task&lt;IEnumerable&lt;Post&gt;&gt; GetPostAsync();
    Task&lt;Post&gt; GetPostAsync(int id);
    Task AddAsync(Post post);
    Task EditAsync(Post post);
    Task DeleteAsync(int id);
}
</code></pre><p>We need to return a <code>Task&lt;T&gt;</code> so for the <code>Get</code> methods we will wrap the return type inside a task and for the <code>Add</code>, <code>Edit</code>, and <code>Delete</code> we will simply return a Task as we cannot return void on an async method and also we will update the name of every function as they will now work asynchronously we will append the <code>Async</code> word.</p><h2 id="update-postrepository-class">Update PostRepository class </h2><p>Now we should be getting an error because we changes the return type for every method defined in the <code>IPostRepository</code> interface so we need to update our <code>PostRepository</code> as well to make sure we comply with what our interface states.</p><pre><code class="language-csharp">public class PostRepository : IPostRepository
{
    private readonly BlogDbContext context;
    public PostRepository(BlogDbContext context)
    {
        this.context = context;
    }

    public async Task AddAsync(Post post)
    {
        context.Add(post);
        await context.SaveChangesAsync();
    }

    public async Task DeleteAsync(int id)
    {
        var post = context.Posts.Find(id);
        context.Remove(post);
        await context.SaveChangesAsync();
    }

    public async Task EditAsync(Post post)
    {
        context.Entry(post).State = EntityState.Modified;
        await context.SaveChangesAsync();
    }

    public async Task&lt;IEnumerable&lt;Post&gt;&gt; GetPostAsync()
    {
        var allPosts = await context.Posts.ToListAsync();
        return allPosts;
    }

    public async Task&lt;Post&gt; GetPostAsync(int id)
    {
        var post = await context.Posts.FindAsync(id);
        return post;
    }
}
</code></pre><p>Let&#x2019;s begin by changing the names of all the methods and append the <code>Async</code> word as they will now be working asynchronously, then add the async keyword and change the return type for every method to fully comply with the method signature defined by our interface.</p><p>Now the last step is to call <code>SaveChangesAsync</code> method in our <code>Add</code>, <code>Edit</code>, and <code>Delete</code> methods. For the <code>Get</code> method that retrieves all the posts we need to change the <code>ToList()</code> to <code>ToListAsync</code> and that would be enough, we need to do the same for the Get method that retrieves a single post but instead of using <code>ToListAsync</code> we will replace the <code>Find</code> method for its async version <code>FindAsync</code> and there you go now the repository class is calling the database asynchronously.</p><h2 id="making-the-post-controller-async">Making the Post Controller Async </h2><p>Now all that is left is to update our controller endpoints to make them work asynchronously.</p><pre><code class="language-csharp">**[HttpGet]
public async Task&lt;IActionResult&gt; GetPost()
{
    var posts = await repository.GetPostAsync();
    var postsDto = mapper.Map&lt;IEnumerable&lt;PostResponseDTO&gt;&gt;(posts);
    logger.LogDebug($&quot;Get method called, got {postsDto.Count()} results&quot;);
    return Ok(postsDto);
}

[HttpGet(&quot;{id:int}&quot;)]
public async Task&lt;IActionResult&gt; GetPost(int id)
{
    try
    {
        var post = await repository.GetPostAsync(id);
        var postDto = mapper.Map&lt;PostResponseDTO&gt;(post);

        return Ok(postDto);
    }
    catch (Exception ex)
    {
        logger.LogError(ex, $&quot;Error getting post with id {id}&quot;);
        throw;
    }
}

[HttpPost]
public async Task&lt;IActionResult&gt; CreatePost(AddPostDTO addPostDTO)
{
    try
    {
        if (!ModelState.IsValid)
        {
            return BadRequest();
        }

        var newPost = mapper.Map&lt;AddPostDTO, Post&gt;(addPostDTO);
        newPost.CreatedDate = DateTime.Now;
        await repository.AddAsync(newPost);
        return CreatedAtAction(nameof(GetPost), new { id = newPost.Id }, null);
    }
    catch (Exception ex)
    {
        logger.LogError(ex, &quot;Unexpected error on Post method&quot;);
        throw;
    }
}

[HttpPut]
public async Task&lt;IActionResult&gt; EditPost([FromBody] EditPostDTO editPostDto)
{
    try
    {
        if (!ModelState.IsValid)
        {
            return BadRequest();
        }
        var post = mapper.Map&lt;EditPostDTO, Post&gt;(editPostDto);

        post.LastUpdated = DateTime.Now;
        await repository.EditAsync(post);
        return NoContent();
    }
    catch (Exception ex)
    {
        logger.LogError(ex, &quot;Unexpected error on Put(Edit) Method&quot;);
        throw;
    }
}

[HttpDelete(&quot;{id:int}&quot;)]
public async Task&lt;IActionResult&gt; DeletePost(int id)
{
    try
    {
        await repository.DeleteAsync(id);

        return NoContent();
    }
    catch (Exception ex)
    {
        logger.LogError(ex, $&quot;Unexpected error on Delete method trying to delete post with Id {id}&quot;);
        throw;
    }
}**
</code></pre><p>Here what we did is that in every endpoint we added the <code>async</code> keyword and set the return type to <code>Task&lt;IActionResult&gt;</code>. Also, we now call the async version of the repository methods <code>AddAsync</code>, <code>EditAsync</code>, <code>DeleteAsync</code>, and <code>GetAsync</code>.</p><h2 id="test-the-api">Test the API </h2><p>Now you can proceed to test the API, you will notice no change as it will run as before but now behind the scenes, it can take requests asynchronously and also the interaction with the database is asynchronous.</p><h2 id="conclusion">Conclusion </h2><p>Asynchronous programming is an essential paradigm in software development, providing a wide range of uses and benefits. It enables the execution of multiple tasks simultaneously, leading to more efficient and effective software applications. It also enables long-running tasks to be processed without blocking the main thread, improving the overall user experience. As such, it is a critical tool for developers looking to create high-performance software applications. By embracing asynchronous programming, developers can create faster, more efficient, and more responsive applications, leading to better overall user experiences.</p><p>As always thanks for reading and considering supporting me on my blog <a href="https://unitcoding.com/">Unit Coding</a> and on my youtube channel under the same name <a href="https://www.youtube.com/watch?v=HVbUyOK7wxU&amp;t=29s&amp;ab_channel=unitcoding&amp;ref=unitcoding.com">Unit Coding</a>. Keep posted for my future articles on web API development and also for cool projects using ASP NET Core.</p>]]></content:encoded></item><item><title><![CDATA[Data validation with Fluent Validation for ASP NET Core]]></title><description><![CDATA[<p>Hello guys, welcome to another chapter of this series on API Development with ASP NET Core. <a href="https://unitcoding.com/data-transfer-objects-and-mapping-in-asp-net-core/">In the last article</a>, we talk about data mapping using auto mapper and I showed you how to implement data mapping from installing auto mapper to creating the mapping profiles and injecting auto mapper</p>]]></description><link>https://unitcoding.com/validation-to-web-api/</link><guid isPermaLink="false">643878716358ae04c7ec392a</guid><category><![CDATA[REST API Development]]></category><category><![CDATA[ASP NET Core]]></category><category><![CDATA[beginner]]></category><category><![CDATA[C#]]></category><category><![CDATA[Web API]]></category><category><![CDATA[Software Development]]></category><dc:creator><![CDATA[Oscar Montenegro]]></dc:creator><pubDate>Thu, 13 Apr 2023 21:56:55 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1559131397-f94da358f7ca?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDZ8fGNoZWNrJTIwaW58ZW58MHx8fHwxNjgxNDIyNDcw&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1559131397-f94da358f7ca?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDZ8fGNoZWNrJTIwaW58ZW58MHx8fHwxNjgxNDIyNDcw&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Data validation with Fluent Validation for ASP NET Core"><p>Hello guys, welcome to another chapter of this series on API Development with ASP NET Core. <a href="https://unitcoding.com/data-transfer-objects-and-mapping-in-asp-net-core/">In the last article</a>, we talk about data mapping using auto mapper and I showed you how to implement data mapping from installing auto mapper to creating the mapping profiles and injecting auto mapper in our controller to perform the model mapping to data transfer object.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://unitcoding.com/data-transfer-objects-and-mapping-in-asp-net-core/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Data transfer objects and mapping in asp net core</div><div class="kg-bookmark-description">Hello guys, I&#x2019;m so glad to be back after a short rest. I took some time for myself to plan what&#x2019;s coming next for my personal and professional life and to be honest, I&#x2019;m still thinking about that but definitely, I feel more energic and enthusiastic about</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://unitcoding.com/content/images/size/w256h256/2023/03/Copy-of-Unit-1.png" alt="Data validation with Fluent Validation for ASP NET Core"><span class="kg-bookmark-author">Unit Coding</span><span class="kg-bookmark-publisher">Oscar Montenegro</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://images.unsplash.com/photo-1452421822248-d4c2b47f0c81?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDEwfHxtYXB8ZW58MHx8fHwxNjgwODk2OTQw&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Data validation with Fluent Validation for ASP NET Core"></div></a></figure><p>Today we will be talking about data validation using a very popular Nuget package called &#x201C;Fluent Validation&#x201D;. One of the coolest things about this Nuget package is that it uses a fluent interface to configure and initialize the data validators such as the fluent builder that we implemented for our <a href="https://unitcoding.com/image-generator/">Image Generator</a> project some weeks ago, the fluent interface makes the initialization of complex objects more simple and readable and therefore it becomes more maintainable. Taking into consideration that this article is for very beginners we will touch on some basic topics on data validation.</p><h2 id="what-this-article-will-cover">What this article will cover? </h2><p>The topics that we will cover in this article are the following.</p><ol><li>Data validation</li><li>What is fluent validation?</li><li>Why se fluent validation</li><li>Installing fluent validation nuget package</li><li>Create a custom validator</li></ol><h2 id="data-validation">Data validation </h2><p>Data validation is an essential aspect of software development. It ensures that the data being processed is correct and consistent, leading to better performance, reliability, and security of the application. However, traditional methods of data validation can be time-consuming and error-prone. This is where Fluent Validation comes in. Fluent Validation is a library for .NET that simplifies the process of validating data in your application. In this article, we&apos;ll explore the benefits of Fluent Validation and how it can make your life as a developer easier.</p><h2 id="what-is-fluent-validation">What is Fluent Validation ?</h2><p>Fluent Validation is an open-source library for .NET that makes it easy to define and execute validation rules. It provides a fluent interface for defining validation rules, making it easy to read and maintain. Fluent Validation can be used to validate any object, including complex objects, lists, and arrays.</p><h2 id="why-use-fluent-validation">Why use Fluent Validation ?</h2><p>Fluent Validation provides a number of benefits over traditional validation methods, including:</p><ol><li>Increased readability and maintainability of validation code: The fluent interface provided by Fluent Validation makes it easy to read and maintain validation code. This is especially true for complex validation rules.</li><li>Improved testability: Fluent Validation makes it easy to unit test validation rules. This ensures that your validation rules are working as expected and that any changes you make to the rules do not break existing functionality.</li><li>Increased productivity: By simplifying the validation process, Fluent Validation can help you write code more quickly and with fewer errors. This can save you time and reduce the likelihood of bugs.</li><li>Better error reporting: Fluent Validation provides detailed error messages that make it easy to understand what went wrong during validation. This can help you quickly identify and fix issues.</li></ol><p>Now that you know what data validation is and why you should consider it for complex projects like this API we can move on to actually put our hands on some code taking as a starting point the installation of the fluent validation nuget package into our project.</p><h2 id="clone-the-repo-from-github">Clone the repo from Github</h2><p>To follow along with this article make sure you the repo from GitHub and make sure you get the code from the <code>DtosAndMapping</code> branch which contains the changes up to this article.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Osempu/BlogAPI/tree/DtosAndMapping?ref=unitcoding.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - Osempu/BlogAPI at DtosAndMapping</div><div class="kg-bookmark-description">Contribute to Osempu/BlogAPI development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Data validation with Fluent Validation for ASP NET Core"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">Osempu</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/7fe47e63175141a289a69b3d9dba70dfa3a4e46465250cdb8a8ae97328c5192f/Osempu/BlogAPI" alt="Data validation with Fluent Validation for ASP NET Core"></div></a></figure><h2 id="install-fluentvalidationaspnetcore-nuget-package">Install FluentValidation.AspNetCore nuget package </h2><p>Let&#x2019;s start implementing data validation installing the nuget package into our project using the dotnet cli or you could use the nuget package manager.</p><p><code>dotnet add package FluentValidation.AspNetCore</code></p><p>This command will install the needed nuget package for us to use fluent validation into our API and now we can start creating the validators for our <code>Post</code> model.</p><h2 id="add-new-data-transfer-objects">Add new Data Transfer Objects </h2><p>In the last article we discussed what are DTOs and why are they used for on software development and we created one dto just for demonstration purposes. Now to create more meaningful validators we will create some more meaningful dtos as well, we will create a dto for when a user wants to create a new post when a new post is being updated and also a dto to return the posts which is the one that we already have but we will use &#x201C;records&#x201D;.</p><p>A <code>Record</code> is a reference type that provides a built-in functionality for encapsulating data and its properties are immutable which is just what we need for a dto.</p><h3 id="add-new-post-dto">Add new post DTO</h3><p>Create a new record called <code>AddPostDTO</code>. When we need to create a new post we do not need to provide an Id so it becomes redundant to have the Id propertie as a requirement to create a post. So in this dto we only take the title, body and author of the post to be able to create it and then entity framework takes charge of passing the id to the database.</p><pre><code class="language-csharp">namespace BlogAPI.DTOs
{
    public record AddPostDTO(string Title, string Body, string Author);
}
</code></pre><h3 id="edit-post-dto">Edit post DTO</h3><p>To update a post we do need its Id to know which post we will update.</p><pre><code class="language-csharp">namespace BlogAPI.DTOs
{
    public record EditPostDTO(int Id, string Title, string Body, string Author);
}
</code></pre><h3 id="update-the-postdto-to-postresponsedto">Update the PostDTO to PostResponseDTO</h3><p>We created a PostDTO in the data mapping article to return a post without displaying the created date property and last updated date property so now we will only make this a record to be consistent with all our dtos being records and change the name to <code>PostResponseDTO</code> to make it more meaningful and distinguishing between this dto and the <code>EditPostDTO</code> as they both hold the same properties.</p><pre><code class="language-csharp">namespace BlogAPI.DTOs
{
    public record PostResponseDTO(int Id, string Author, string Title, string Body);
}
</code></pre><h3 id="isn%E2%80%99t-this-code-duplication">Isn&#x2019;t this code duplication? </h3><p>You could argue that both <code>EditPostDTO</code> and <code>PostResponseDTO</code> are the same record as they hold the same properties and I did point that out a second ago but if you think it&#x2019;s a good idea to use just one dto for the response and the edit as they hold the same properties right now that could be a big mistake, just think that if in the future our main <code>Post</code> model changes or our project needs changes and now I want to display the <code>CreatedDate</code> property when I return a Post I would update my dto that is used to edit and to return data but it makes no sense for the user to pass the <code>CreatedDate</code> value whenever he wants to edit the post and we would be forced to again build separate dtos for editing and to return the post. For that matter its important that we have separate dtos for that cases.</p><h2 id="add-new-mapping-profiles">Add new mapping profiles </h2><p>As we addded new dtos and updated our old dto we have to add new mapping profiles and update our <code>PostProfiles</code> file.</p><pre><code class="language-csharp">public class PostProfiles : Profile
{
    public PostProfiles()
    {
        CreateMap&lt;AddPostDTO, Post&gt;();
        CreateMap&lt;EditPostDTO, Post&gt;();
        CreateMap&lt;Post, PostResponseDTO&gt;();
    }
}
</code></pre><p>Your <code>PostProfiles</code> class should look like this and also if you renamed your <code>PostDTO</code> to <code>PostResponseDTO</code> like me you will have to update the controller class as well but we will take a look on that in just a minute.</p><h2 id="create-a-custom-validator">Create a custom validator </h2><p>Let&#x2019;s create validators for our <code>AddPostDTO</code> and <code>EditPostDTO</code>.</p><blockquote>To define a set of validation rules for a particular object, you will need to create a class that inherits from <code>AbstractValidator&lt;T&gt;</code>, where <code>T</code> is the type of class that you wish to validate.</blockquote><ul><li>Fluent validation documentation.</li></ul><h3 id="add-post-validator">Add Post validator</h3><pre><code class="language-csharp">public class AddPostValidator : AbstractValidator&lt;AddPostDTO&gt;
{
    public AddPostValidator()
    {
        RuleFor(x =&gt; x.Title)
                .NotEmpty()
                .MaximumLength(100)
                .WithMessage(&quot;Title cannot exceed 100 characters&quot;);

        RuleFor(x =&gt; x.Body)
                .NotEmpty()
                .MaximumLength(500)
                .WithMessage(&quot;The body of the post cannot exceed 500 characters&quot;);

        RuleFor(x =&gt; x.Author)
                .NotEmpty()
                .MaximumLength(100)
                .WithMessage(&quot;The name of the author cannot exceed 100 characters&quot;);
    }
}
</code></pre><p>First we need to create a class called <code>AddPostValidator</code> that inherits from the AbstractValidator&lt;T&gt; interface being T our <code>AddPostDTO</code> dto.</p><p>Then we can see fluent validation in action creating the first rule for the title property using the <code>RuleFor</code> method using a lambda expression to select the title property and chaining the <code>NotEmpty</code> method that states that the property should not be null nor empty, afther that we call the <code>MaximumLength</code> method and specify the max length that our title can have and last but not least we specify an error message to be displayed if the rule is not met. Then we apply the same rules for the body and author properties as our dto is not that complex yet we do not need to specify complex rules.</p><h3 id="edit-post-validator">Edit Post validator</h3><pre><code class="language-csharp">public class EditPostValidator : AbstractValidator&lt;EditPostDTO&gt;
{
    public EditPostValidator()
    {
        RuleFor(x =&gt; x.Id)
                .NotEmpty()
                .WithMessage(&quot;Id cannot be null or empty&quot;);

        RuleFor(x =&gt; x.Title)
                .NotEmpty()
                .MaximumLength(100)
                .WithMessage(&quot;Title cannot exceed 100 characters&quot;);

        RuleFor(x =&gt; x.Body)
                .NotEmpty()
                .MaximumLength(500)
                .WithMessage(&quot;The body of the post cannot exceed 500 characters&quot;);

        RuleFor(x =&gt; x.Author)
                .NotEmpty()
                .MaximumLength(100)
                .WithMessage(&quot;The name of the author cannot exceed 100 characters&quot;);
    }
}
</code></pre><p>For our <code>EditPostDTO</code> dto we will apply the same rules as for the <code>AddPostDTO</code> except that we will ad the Id and we will specify that it cannot be empty nor bull and the error message to display if this rule is not met.</p><h2 id="register-fluent-validation-in-programcs">Register Fluent Validation in Program.cs</h2><p>Let&#x2019;s register the fluent validation nuget package as a service in the <code>Program</code> file below <code>AddAutomapper</code> let&#x2019;s add these two lines to proceed to update the <code>PostsController</code>.</p><pre><code class="language-csharp">builder.Services.AddFluentValidationAutoValidation();
builder.Services.AddValidatorsFromAssemblyContaining&lt;Program&gt;();
</code></pre><h2 id="update-the-controllers-using-the-new-dtos-and-validation-the-models">Update the controllers using the new DTOs and validation the models</h2><p>Now all that is left is to update our <code>PostsController</code> to add our newly added DTOs and to validate the models that the client is sending to our API so let&#x2019;s begin with the <code>CreatePost</code> action.</p><pre><code class="language-csharp">[HttpPost]
public IActionResult CreatePost(AddPostDTO addPostDTO)
{
    try
    {
        if (!ModelState.IsValid)
        {
            return BadRequest();
        }

        var newPost = mapper.Map&lt;AddPostDTO, Post&gt;(addPostDTO);
				newPost.CreatedDate = DateTime.Now;
        repository.Add(newPost);
        return CreatedAtAction(nameof(GetPost), new { id = newPost.Id }, null);
    }
    catch (Exception ex)
    {
        logger.LogError(ex, &quot;Unexpected error on Post method&quot;);
        throw;
    }
}
</code></pre><p>you can see that we added an if statement to check whether the model state is valid and if not then we will return a bad request response to let the client know that he did a bas request and then asp net core will return the error messages that fluent validation provides by default and also the ones that we added in the validation classes. Also, we added a line to set the CreatedDate property to the moment we are creating the post.</p><h3 id="edit-post-endpoints">Edit post endpoints</h3><pre><code class="language-csharp">[HttpPut]
public IActionResult EditPost([FromBody] EditPostDTO editPostDto)
{
    try
    {
        if (!ModelState.IsValid)
        {
            return BadRequest();
        }
        var post = mapper.Map&lt;EditPostDTO, Post&gt;(editPostDto);

        post.LastUpdated = DateTime.Now;
        repository.Edit(post);
        return NoContent();
    }
    catch (Exception ex)
    {
        logger.LogError(ex, &quot;Unexpected error on Put(Edit) Method&quot;);
        throw;
    }
}
</code></pre><p>This is the second and last endpoint that we will update to support validation and to add our new dtos that works for the edit action. As in the last endpoint we added an if statement to check if the model state is valid this means that there is no error in the data that was sent to the API and then we map the <code>EditPostDTO</code> to the former <code>Post</code> model to edit it and if you pay attention we added a line to update the <code>LastUpdated</code> property so that every time that we update a post this property is updated automatically to that corresponding post.</p><h2 id="test-your-api">Test your API </h2><p>If you test the API and pass some invalid data then the response should look something like this.</p><pre><code class="language-json">{
  &quot;type&quot;: &quot;&lt;https://tools.ietf.org/html/rfc7231#section-6.5.1&gt;&quot;,
  &quot;title&quot;: &quot;One or more validation errors occurred.&quot;,
  &quot;status&quot;: 400,
  &quot;traceId&quot;: &quot;00-df250c99457dff70b0defd6d812b941f-7313f895506c9c22-00&quot;,
  &quot;errors&quot;: {
    &quot;Title&quot;: [
      &quot;Title cannot exceed 100 characters&quot;
    ],
    &quot;Author&quot;: [
      &quot;The name of the author cannot exceed 100 characters&quot;
    ]
  }
}
</code></pre><p>We are getting a <code>400 BadRequest</code> response message and an array called <code>errors</code> with the rules we are breaking being these the title rule and author rule as we are exceeding the limit of characters that we set on our validator class. Pretty satisfying don&#x2019;t you think? Now you will avoid your API being full of invalid data and incomplete data so now we made it more resilient.</p><h2 id="conclusion">Conclusion </h2><p>Data validation is essential for software development just imagine if anybody could insert any data into your API, that could be a mess. With data validation, we are making sure that only consistent and meaningful data is going into our database. Fluent validation is an excellent library that simplifies the process of data validation in our applications.</p><h2 id="thanks-for-your-support-it-means-the-world-to-me">Thanks for your support, it means the world to me!</h2><p>I always take a space at the end of every post to ask you to support me and follow me on my blog and youtube channel but today I want to thank you all for supporting me because the reason that I keep writing is that there are people like you that take some time and dedicate a special space to read whatever I&#x2019;m writing and that means a lot to me it keeps me motivated and helps me to think that somebody in the world in the other side of this bright and clear screen is reading it and it&#x2019;s being of use for him/she.</p><p> Thanks, everybody I will continue this API Development series until I feel that every basic aspect is covered and only then I will move on to another series. Also, tomorrow is friday and you know what that means, yay API Friday!!! I have been working on something special for you guys, nothing complex just something that you can build to have a good time and by the way if you want to know what was the last project for API Friday it was an image generator using the lorem picsum API and Blazor so check it out, I know you will have lots of fun coding it.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://unitcoding.com/image-generator/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Image Generator with Blazor</div><div class="kg-bookmark-description">Hello guys, happy Friday! Today I will inaugurate a new section that will be called &#x201C;API Friday&#x201D;. What will this API Friday be about? well, basically every Friday(or every two Fridays) I will post a .net project(blazor, asp net MVC, web API, etc.) made using a cool web</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://unitcoding.com/content/images/size/w256h256/2023/03/Copy-of-Unit-1.png" alt="Data validation with Fluent Validation for ASP NET Core"><span class="kg-bookmark-author">Unit Coding</span><span class="kg-bookmark-publisher">Oscar Montenegro</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://unitcoding.com/content/images/2023/03/appDemo-1.png" alt="Data validation with Fluent Validation for ASP NET Core"></div></a></figure><p>So that would be it for today I have to prepare everything for tomorrow so again thanks for your support and see you on my next post!</p>]]></content:encoded></item></channel></rss>