<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[web API with ASP.NET Core]]></title><description><![CDATA[web API with ASP.NET Core]]></description><link>https://web-api.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Fri, 09 Oct 2026 15:19:40 GMT</lastBuildDate><atom:link href="https://web-api.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[A controller-based web API with ASP.NET Core]]></title><description><![CDATA[This tutorial teaches the basics of building a controller-based web API that uses a database.You will embark on a journey to create a fully functional API for managing "to-do" items, featuring GET, POST, PUT, and DELETE endpoints. This practical guid...]]></description><link>https://web-api.hashnode.dev/a-controller-based-web-api-with-aspnet-core</link><guid isPermaLink="true">https://web-api.hashnode.dev/a-controller-based-web-api-with-aspnet-core</guid><category><![CDATA[C#]]></category><category><![CDATA[Web API]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[Backend Development]]></category><category><![CDATA[entity framework]]></category><category><![CDATA[REST API]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[software development]]></category><category><![CDATA[asp.net core]]></category><dc:creator><![CDATA[Shivam Saini]]></dc:creator><pubDate>Wed, 03 Sep 2025 16:42:53 GMT</pubDate><content:encoded><![CDATA[<hr />
<p>This tutorial teaches the basics of building a controller-based web API that uses a database.<br />You will embark on a journey to create a fully functional API for managing "to-do" items, featuring GET, POST, PUT, and DELETE endpoints. This practical guide will lead you through the process of setting up controllers, routing, models, and database connectivity, establishing a strong foundation for further exploration.</p>
<h2 id="heading-overview">overview</h2>
<hr />
<p>This tutorial builds the following API:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>API</strong></td><td>Description</td><td>Request body</td><td>Response body</td></tr>
</thead>
<tbody>
<tr>
<td><code>GET /api/todoitems</code></td><td>Get all to-do items</td><td>None</td><td>Array of to-do items</td></tr>
<tr>
<td><code>GET /api/todoitems/{id}</code></td><td>Get an item by ID</td><td>None</td><td>To-do item</td></tr>
<tr>
<td><code>POST /api/todoitems</code></td><td>Add a new item</td><td>To-do item</td><td>To-do item</td></tr>
<tr>
<td><code>PUT /api/todoitems/{id}</code></td><td>Update an existing item</td><td>To-do item</td><td>None</td></tr>
<tr>
<td><code>DELETE /api/todoitems/{id}</code></td><td>Delete an item</td><td>None</td><td>None</td></tr>
</tbody>
</table>
</div><p>The following diagram shows the design of the app.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757348094473/7fb22252-2df3-4ccd-b7af-010e3c04767c.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<hr />
<ul>
<li><p>Visual Studio Code</p>
</li>
<li><p>C# Dev Kit for Visual Studio Code</p>
</li>
<li><p>.NET 9 SDK</p>
</li>
</ul>
<h2 id="heading-create-a-web-api-project"><strong>Create a Web API project</strong></h2>
<hr />
<ul>
<li><p>Change directories to the folder that will contain the project folder in the terminal &amp; run the following command.</p>
<pre><code class="lang-bash">  dotnet new webapi --use-controllers -o TodoApi
  <span class="hljs-built_in">cd</span> TodoApi
  dotnet add package Microsoft.EntityFrameworkCore.InMemory
</code></pre>
</li>
</ul>
<p>these commands:</p>
<p>◦ Create a new web API project. ◦ Add a NuGet package that is needed.</p>
<ul>
<li>If Visual Studio Code doesn't offer to add build and debug assets, do it from <strong>Command Palette.</strong></li>
</ul>
<h2 id="heading-run-the-project"><strong>Run the project</strong></h2>
<hr />
<p>The project template creates a <code>WeatherForecast</code> API</p>
<ul>
<li>Trust the HTTPS development certificate by running the following command:</li>
</ul>
<pre><code class="lang-bash">dotnet dev-certs https --trust
</code></pre>
<ul>
<li>Run the following command to start the app on the <code>https</code> profile:</li>
</ul>
<pre><code class="lang-bash">dotnet run --launch-profile https
</code></pre>
<ul>
<li><p>The default browser is launched to <code>https://localhost:&lt;port&gt;</code>, where <code>&lt;port&gt;</code> is the randomly chosen port number displayed in the output. There's no endpoint at <code>https://localhost:&lt;port&gt;</code>, so the browser returns <a target="_blank" href="https://developer.mozilla.org/docs/Web/HTTP/Status/404">HTTP 404 Not Found</a>.</p>
</li>
<li><p>Append <code>/weatherforecast</code> to the URL to test the WeatherForecast API.</p>
</li>
</ul>
<h2 id="heading-test-the-project"><strong>Test the project</strong></h2>
<hr />
<h3 id="heading-create-api-testing-ui-with-swagger"><strong>Create API testing UI with Swagger</strong></h3>
<p>We will utilizes the .NET package NSwag.AspNetCore, which integrates Swagger tools for generating a testing UI adhering to the OpenAPI specification:</p>
<ul>
<li><p>NSwag: A .NET library that integrates Swagger directly into <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core applications, providing middleware and configuration.</p>
</li>
<li><p>Swagger: A set of open-source tools such as OpenAPIGenerator and SwaggerUI that generate API testing pages that follow the OpenAPI specification.</p>
</li>
<li><p>OpenAPI specification: A document that describes the capabilities of the API, based on the XML and attribute annotations within the controllers and models.</p>
</li>
</ul>
<p><strong>Install Swagger tooling</strong></p>
<ul>
<li>Run the following command:</li>
</ul>
<pre><code class="lang-bash">dotnet add package NSwag.AspNetCore
</code></pre>
<p>This command adds the NSwag.AspNetCore package, which contains tools to generate Swagger documents and UI. Because our project is using OpenAPI, we only use the NSwag package to generate the Swagger UI.</p>
<h3 id="heading-configure-swagger-middleware"><strong>Configure Swagger middleware</strong></h3>
<ul>
<li>In <code>Program.cs</code>, add the following highlighted code:</li>
</ul>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> app = builder.Build();

<span class="hljs-keyword">if</span> (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
    app.UseSwaggerUi(options =&gt;
    {
        options.DocumentPath = <span class="hljs-string">"/openapi/v1.json"</span>;
    });
}
</code></pre>
<p>The code provided activates the Swagger middleware, allowing the generated JSON document to be served via the Swagger UI. It is important to note that Swagger is exclusively enabled in a development environment; enabling it in a production environment may risk exposing sensitive information regarding the API’s structure and implementation.</p>
<p>The application utilizes the OpenAPI document, which is generated by OpenApi and can be found at /openapi/v1.json, to create the user interface. To view the generated OpenAPI specification for the WeatherForecast API while the project is operational, navigate to <a target="_blank" href="https://localhost:%3Cport%3E/openapi/v1.json">https://localhost:&lt;port&gt;/openapi/v1.json</a> in your web browser.</p>
<p>The OpenAPI specification is a JSON formatted document that outlines the structure and capabilities of your API, detailing endpoints, request and response formats, parameters, and more. It serves as a comprehensive blueprint for your API, facilitating interaction with various tools.</p>
<p><strong>Add a model class</strong></p>
<hr />
<p>A <em>model</em> is a set of classes that represent the data that the app manages. The model for this app is the <code>TodoItem</code> class.</p>
<ul>
<li><p>Add a folder named <code>Models</code>.</p>
</li>
<li><p>Add a <code>TodoItem.cs</code> file to the <code>Models</code> folder with the following code:</p>
</li>
</ul>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">TodoApi.Models</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TodoItem</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">long</span> Id { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span>? Name { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span> IsComplete { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
</code></pre>
<p>The <code>Id</code> property functions as the unique key in a relational database.</p>
<p>Model classes can go anywhere in the project, but the <code>Models</code> folder is used by convention.</p>
<h2 id="heading-add-a-database-context"><strong>Add a database context</strong></h2>
<hr />
<p>The <em>database context</em> is the main class that coordinates Entity Framework functionality for a data model. This class is created by deriving from the Microsoft.EntityFrameworkCore.DbContext class.</p>
<ul>
<li><p>Add a <code>TodoContext.cs</code> file to the <code>Models</code> folder.</p>
</li>
<li><p>Enter the following code:</p>
</li>
</ul>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Microsoft.EntityFrameworkCore;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">TodoApi.Models</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TodoContext</span> : <span class="hljs-title">DbContext</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">TodoContext</span>(<span class="hljs-params">DbContextOptions&lt;TodoContext&gt; options</span>)
        : <span class="hljs-title">base</span>(<span class="hljs-params">options</span>)</span>
    {
    }

    <span class="hljs-keyword">public</span> DbSet&lt;TodoItem&gt; TodoItems { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; } = <span class="hljs-literal">null</span>!;
}
</code></pre>
<h2 id="heading-register-the-database-context"><strong>Register the database context</strong></h2>
<hr />
<p>In ASP.NET Core, services such as the DB context must be registered with the dependency injection (DI) container. The container provides the service to controllers.Update <code>Program.cs</code> with the following code:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Microsoft.EntityFrameworkCore;
<span class="hljs-keyword">using</span> TodoApi.Models;

<span class="hljs-keyword">var</span> builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddOpenApi();
builder.Services.AddDbContext&lt;TodoContext&gt;(opt =&gt;
    opt.UseInMemoryDatabase(<span class="hljs-string">"TodoList"</span>));

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

<span class="hljs-keyword">if</span> (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();
</code></pre>
<p>The preceding code:</p>
<ul>
<li><p>Adds <code>using</code> directives.</p>
</li>
<li><p>Adds the database context to the DI container.</p>
</li>
<li><p>Specifies that the database context will use an in-memory database.</p>
</li>
</ul>
<h2 id="heading-scaffold-a-controller"><strong>Scaffold a controller</strong></h2>
<hr />
<p>Make sure that all of your changes so far are saved.</p>
<ul>
<li>In terminal opens at the <code>TodoAPI</code> project folder. Run the following commands:</li>
</ul>
<pre><code class="lang-bash">dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet tool uninstall -g dotnet-aspnet-codegenerator
dotnet tool install -g dotnet-aspnet-codegenerator
dotnet tool update -g dotnet-aspnet-codegenerator
</code></pre>
<p>The preceding commands:</p>
<ul>
<li><p>Add NuGet packages required for scaffolding.</p>
</li>
<li><p>Install the scaffolding engine (<code>dotnet-aspnet-codegenerator</code>) after uninstalling any possible previous version.</p>
</li>
</ul>
<p><strong>Build the project.</strong></p>
<p>Run the following command:</p>
<pre><code class="lang-bash">dotnet aspnet-codegenerator controller -name TodoItemsController -async -api -m TodoItem -dc TodoContext -outDir Controllers
</code></pre>
<p>The preceding command scaffolds the <code>TodoItemsController</code>.</p>
<p>The generated code performs several key functions:</p>
<p>1. <strong>ApiController Attribute</strong>: It marks the class with the <code>[ApiController]</code> attribute, which signifies that the controller is designed to handle web API requests. For detailed information about the specific behaviors this attribute enables, refer to the guide on creating web APIs with <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core.</p>
<p>2. <strong>Dependency Injection (DI)</strong>: The code utilizes dependency injection to incorporate the database context (`TodoContext`) into the controller. This context is essential for performing all CRUD operations within the controller methods.</p>
<p>3. <strong>Route Template Differences</strong>:</p>
<p>• For <strong>Controllers with Views</strong>, the route template includes the <code>[action]</code> token.</p>
<p>• For <strong>API Controllers</strong>, the route template does not include the <code>[action]</code> token.</p>
<p>When the <code>[action]</code> token is absent from the route template, the action name (method name) is excluded from the endpoint. This means that the method name associated with the action is not utilized in route matching.</p>
<h2 id="heading-update-the-posttodoitem-create-method"><strong>Update the PostTodoItem create method</strong></h2>
<hr />
<p>Refactor the <code>PostTodoItem</code> return statement to use the <code>nameof</code> operator for improved clarity and maintainability.</p>
<pre><code class="lang-csharp">[<span class="hljs-meta">HttpPost</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;ActionResult&lt;TodoItem&gt;&gt; PostTodoItem(TodoItem todoItem)
{
    _context.TodoItems.Add(todoItem);
    <span class="hljs-keyword">await</span> _context.SaveChangesAsync();

    <span class="hljs-comment">//    return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);</span>
    <span class="hljs-keyword">return</span> CreatedAtAction(<span class="hljs-keyword">nameof</span>(GetTodoItem), <span class="hljs-keyword">new</span> { id = todoItem.Id }, todoItem);
}
</code></pre>
<p>The code shown above represents an HTTP <strong>POST</strong> method, identified by the <code>[HttpPost]</code> attribute. This method reads the <code>TodoItem</code> object from the body of the incoming HTTP request.<br /><em>(See: Attribute routing with Http[Verb] attributes for details.)</em></p>
<p>The <code>CreatedAtAction</code> method plays a key role here:</p>
<ul>
<li><p>Returns an <strong>HTTP 201 (Created)</strong> status code when the operation succeeds — the standard response for creating a new resource.</p>
</li>
<li><p>Adds a <strong>Location header</strong> to the response, which points to the URI of the newly created to-do item.</p>
</li>
<li><p>Uses the <code>GetTodoItem</code> action to generate that URI. By applying the C# <code>nameof</code> operator, we avoid hard-coding the action name, improving maintainability and reducing errors.</p>
</li>
</ul>
<h3 id="heading-test-posttodoitem"><strong>Test PostTodoItem</strong></h3>
<ul>
<li><p>With the app still running, in the browser, navigate to <a target="_blank" href="https://localhost:%3Cport%3E/swagger"><code>https://localhost:&lt;port&gt;/swagger</code></a> to display the API testing page generated by Swagger. Click on <strong>TodoItems</strong> to expand the operations.</p>
</li>
<li><p>On the Swagger API testing page, select <strong>Post /api/todoitems</strong> &gt; <strong>Try it out</strong>.</p>
</li>
<li><p>Note that the <strong>Request body</strong> field contains a generated example format reflecting the parameters for the API.</p>
</li>
<li><p>n the request body, provide the JSON for a to-do item, leaving out the optional <code>id</code> field.</p>
</li>
</ul>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Sex on the beach"</span>,
  <span class="hljs-attr">"isComplete"</span>: <span class="hljs-literal">true</span>
}
</code></pre>
<ul>
<li><p>Select <strong>Execute</strong>.</p>
</li>
<li><p>Swagger provides a <strong>Responses</strong> pane below the <strong>Execute</strong> button.</p>
</li>
</ul>
<p>A few useful details to note:</p>
<ul>
<li><p><strong>cURL</strong>: Swagger generates an example cURL command in Unix/Linux syntax. On macOS, you can run this directly in the <strong>Terminal</strong> (or any shell that supports Unix commands, such as Git Bash).</p>
</li>
<li><p><strong>Request URL</strong>: Shows a simplified version of the HTTP request made by Swagger UI. Real requests may also include headers, query parameters, and a request body.</p>
</li>
<li><p><strong>Server Response</strong>: Displays both the response body and headers. In this case, the body shows the <code>id</code> field set to <code>1</code>.</p>
</li>
<li><p><strong>Response Code</strong>: Returns <strong>201 Created</strong>, which means the request succeeded and a new resource was created on the server.</p>
</li>
</ul>
<p><strong>Test the location header URI</strong></p>
<p>Test the app by calling the endpoints from a browser or Swagger.</p>
<ul>
<li><p>In Swagger select <strong>GET /api/todoitems</strong> &gt; <strong>Try it out</strong> &gt; <strong>Execute</strong>.</p>
</li>
<li><p>Alternatively, call <strong>GET /api/todoitems</strong> from a browser by entering the URI <a target="_blank" href="https://localhost:%3Cport%3E/api/todoitems"><code>https://localhost:&lt;port&gt;/api/todoitems</code></a>. For example, <a target="_blank" href="https://localhost:7260/api/todoitems"><code>https://localhost:7260/api/todoitems</code></a></p>
</li>
</ul>
<h3 id="heading-exploring-the-get-methods">Exploring the GET methods</h3>
<p>This API provides two <strong>GET</strong> endpoints:</p>
<ul>
<li><p><code>GET /api/todoitems</code> – retrieves all to-do items.</p>
</li>
<li><p><code>GET /api/todoitems/{id}</code> – retrieves a single to-do item by its ID.</p>
</li>
</ul>
<p>Earlier, we looked at an example of the <code>GET /api/todoitems/{id}</code> route.</p>
<p>Now, try adding another to-do item by following the <strong>POST</strong> instructions. Once it’s created, test the <code>GET /api/todoitems</code>endpoint in Swagger to see the full list of items.</p>
<p>⚠️ <strong>Note:</strong> This project uses an <strong>in-memory database</strong>. That means whenever the app is stopped and restarted, the stored data is lost. If your <code>GET</code> request doesn’t return any items, simply use the <strong>POST</strong> endpoint again to add new data before testing.</p>
<h2 id="heading-return-values"><strong>Return values</strong></h2>
<hr />
<p>The <code>GetTodoItems</code> and <code>GetTodoItem</code> methods return an <code>ActionResult&lt;T&gt;</code> type in <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core. This means that the framework automatically converts the returned object into JSON and sends it as part of the response body.</p>
<p>When everything goes smoothly and there are no unhandled exceptions, the response will have a status code of 200 OK. However, if there are any unhandled exceptions, the response will instead show a 5xx error code.</p>
<p>The <code>ActionResult</code> type can represent different HTTP status codes, allowing for flexibility in response handling. For example, the <code>GetTodoItem</code> method can produce two possible outcomes:</p>
<p>• If there is no item that matches the requested ID, the method responds with a 404 Not Found error.</p>
<p>• If an item is successfully found, it returns a 200 status code along with a JSON response body containing the details of the item.</p>
<p><strong>Prevent over-posting</strong></p>
<hr />
<p>Currently the sample app exposes the entire <code>TodoItem</code> object. Production apps typically limit the data that's input and returned using a subset of the model. There are multiple reasons behind this, and security is a major one. The subset of a model is usually referred to as a Data Transfer Object (DTO), input model, or view model. <strong>DTO</strong> is used in this tutorial.</p>
<p>A DTO may be used to:</p>
<ul>
<li><p>Prevent over-posting.</p>
</li>
<li><p>Hide properties that clients are not supposed to view.</p>
</li>
<li><p>Omit some properties in order to reduce payload size.</p>
</li>
<li><p>Flatten object graphs that contain nested objects. Flattened object graphs can be more convenient for clients.</p>
</li>
</ul>
<p>To demonstrate the DTO approach, update the <code>TodoItem</code> class to include a secret field:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">TodoApi.Models</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TodoItem</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">long</span> Id { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span>? Name { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span> IsComplete { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span>? Secret { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
</code></pre>
<p>The secret field needs to be hidden from this app, but an administrative app could choose to expose it.</p>
<p>Verify you can post and get the secret field.</p>
<p>Create a DTO model in a <strong>Models/TodoItemsDTO.cs</strong> file</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">TodoApi.Models</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TodoItemDTO</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">long</span> Id { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span>? Name { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span> IsComplete { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
</code></pre>
<p>Update the <code>TodoItemsController</code> to use <code>TodoItemDTO</code>:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Microsoft.AspNetCore.Mvc;
<span class="hljs-keyword">using</span> Microsoft.EntityFrameworkCore;
<span class="hljs-keyword">using</span> TodoApi.Models;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">TodoApi.Controllers</span>;

[<span class="hljs-meta">Route(<span class="hljs-meta-string">"api/[controller]"</span>)</span>]
[<span class="hljs-meta">ApiController</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TodoItemsController</span> : <span class="hljs-title">ControllerBase</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> TodoContext _context;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">TodoItemsController</span>(<span class="hljs-params">TodoContext context</span>)</span>
    {
        _context = context;
    }

    <span class="hljs-comment">// GET: api/TodoItems</span>
    [<span class="hljs-meta">HttpGet</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;ActionResult&lt;IEnumerable&lt;TodoItemDTO&gt;&gt;&gt; GetTodoItems()
    {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> _context.TodoItems
            .Select(x =&gt; ItemToDTO(x))
            .ToListAsync();
    }

    <span class="hljs-comment">// GET: api/TodoItems/5</span>
    <span class="hljs-comment">// &lt;snippet_GetByID&gt;</span>
    [<span class="hljs-meta">HttpGet(<span class="hljs-meta-string">"{id}"</span>)</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;ActionResult&lt;TodoItemDTO&gt;&gt; GetTodoItem(<span class="hljs-keyword">long</span> id)
    {
        <span class="hljs-keyword">var</span> todoItem = <span class="hljs-keyword">await</span> _context.TodoItems.FindAsync(id);

        <span class="hljs-keyword">if</span> (todoItem == <span class="hljs-literal">null</span>)
        {
            <span class="hljs-keyword">return</span> NotFound();
        }

        <span class="hljs-keyword">return</span> ItemToDTO(todoItem);
    }
    <span class="hljs-comment">// &lt;/snippet_GetByID&gt;</span>

    <span class="hljs-comment">// PUT: api/TodoItems/5</span>
    <span class="hljs-comment">// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754</span>
    <span class="hljs-comment">// &lt;snippet_Update&gt;</span>
    [<span class="hljs-meta">HttpPut(<span class="hljs-meta-string">"{id}"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;IActionResult&gt; <span class="hljs-title">PutTodoItem</span>(<span class="hljs-params"><span class="hljs-keyword">long</span> id, TodoItemDTO todoDTO</span>)</span>
    {
        <span class="hljs-keyword">if</span> (id != todoDTO.Id)
        {
            <span class="hljs-keyword">return</span> BadRequest();
        }

        <span class="hljs-keyword">var</span> todoItem = <span class="hljs-keyword">await</span> _context.TodoItems.FindAsync(id);
        <span class="hljs-keyword">if</span> (todoItem == <span class="hljs-literal">null</span>)
        {
            <span class="hljs-keyword">return</span> NotFound();
        }

        todoItem.Name = todoDTO.Name;
        todoItem.IsComplete = todoDTO.IsComplete;

        <span class="hljs-keyword">try</span>
        {
            <span class="hljs-keyword">await</span> _context.SaveChangesAsync();
        }
        <span class="hljs-keyword">catch</span> (DbUpdateConcurrencyException) <span class="hljs-keyword">when</span> (!TodoItemExists(id))
        {
            <span class="hljs-keyword">return</span> NotFound();
        }

        <span class="hljs-keyword">return</span> NoContent();
    }
    <span class="hljs-comment">// &lt;/snippet_Update&gt;</span>

    <span class="hljs-comment">// POST: api/TodoItems</span>
    <span class="hljs-comment">// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754</span>
    <span class="hljs-comment">// &lt;snippet_Create&gt;</span>
    [<span class="hljs-meta">HttpPost</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;ActionResult&lt;TodoItemDTO&gt;&gt; PostTodoItem(TodoItemDTO todoDTO)
    {
        <span class="hljs-keyword">var</span> todoItem = <span class="hljs-keyword">new</span> TodoItem
        {
            IsComplete = todoDTO.IsComplete,
            Name = todoDTO.Name
        };

        _context.TodoItems.Add(todoItem);
        <span class="hljs-keyword">await</span> _context.SaveChangesAsync();

        <span class="hljs-keyword">return</span> CreatedAtAction(
            <span class="hljs-keyword">nameof</span>(GetTodoItem),
            <span class="hljs-keyword">new</span> { id = todoItem.Id },
            ItemToDTO(todoItem));
    }
    <span class="hljs-comment">// &lt;/snippet_Create&gt;</span>

    <span class="hljs-comment">// DELETE: api/TodoItems/5</span>
    [<span class="hljs-meta">HttpDelete(<span class="hljs-meta-string">"{id}"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;IActionResult&gt; <span class="hljs-title">DeleteTodoItem</span>(<span class="hljs-params"><span class="hljs-keyword">long</span> id</span>)</span>
    {
        <span class="hljs-keyword">var</span> todoItem = <span class="hljs-keyword">await</span> _context.TodoItems.FindAsync(id);
        <span class="hljs-keyword">if</span> (todoItem == <span class="hljs-literal">null</span>)
        {
            <span class="hljs-keyword">return</span> NotFound();
        }

        _context.TodoItems.Remove(todoItem);
        <span class="hljs-keyword">await</span> _context.SaveChangesAsync();

        <span class="hljs-keyword">return</span> NoContent();
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">TodoItemExists</span>(<span class="hljs-params"><span class="hljs-keyword">long</span> id</span>)</span>
    {
        <span class="hljs-keyword">return</span> _context.TodoItems.Any(e =&gt; e.Id == id);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> TodoItemDTO <span class="hljs-title">ItemToDTO</span>(<span class="hljs-params">TodoItem todoItem</span>)</span> =&gt;
       <span class="hljs-keyword">new</span> TodoItemDTO
       {
           Id = todoItem.Id,
           Name = todoItem.Name,
           IsComplete = todoItem.IsComplete
       };
}
</code></pre>
<h2 id="heading-add-authentication-support-to-a-web-api"><strong>Add authentication support to a web API</strong></h2>
<hr />
<p>refer <a target="_blank" href="https://www.c-sharpcorner.com/article/basic-authentication-in-web-api/">https://www.c-sharpcorner.com/article/basic-authentication-in-web-api/</a></p>
<p><strong>Publish to Azure</strong></p>
<hr />
<p>refer <a target="_blank" href="https://learn.microsoft.com/en-us/azure/?product=popular">https://learn.microsoft.com/en-us/azure/?product=popular</a></p>
]]></content:encoded></item></channel></rss>