Chuyển tới nội dung
Home » Web Api In Mvc | Update The Posttodoitem Create Method

Web Api In Mvc | Update The Posttodoitem Create Method

How To Consume WEB API in ASP.NET Core MVC | ASP.NET Web API | Read Data

Test with http-repl, Postman, or curl

http-repl, Postman, and curl are often used to test API’s. Swagger uses

curl

and shows the

curl

command it submitted.

For instructions on these tools, see the following links:

For more information on

http-repl

, see Test web APIs with the HttpRepl.

The DeleteTodoItem method

Examine the

DeleteTodoItem

method:


[HttpDelete("{id}")] public async Task

DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); }

Test the DeleteTodoItem method

Use the Swagger UI to delete the

TodoItem

that has Id = 1. Note the response is

HTTP 204 No Content

.

How To Consume WEB API in ASP.NET Core MVC | ASP.NET Web API | Read Data
How To Consume WEB API in ASP.NET Core MVC | ASP.NET Web API | Read Data

Prevent over-posting

Currently the sample app exposes the entire

TodoItem

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. DTO is used in this tutorial.

A DTO may be used to:

  • Prevent over-posting.
  • Hide properties that clients are not supposed to view.
  • Omit some properties in order to reduce payload size.
  • Flatten object graphs that contain nested objects. Flattened object graphs can be more convenient for clients.

To demonstrate the DTO approach, update the

TodoItem

class to include a secret field:


namespace TodoApi.Models { public class TodoItem { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } public string? Secret { get; set; } } }

The secret field needs to be hidden from this app, but an administrative app could choose to expose it.

Verify you can post and get the secret field.

Create a DTO model:


namespace TodoApi.Models; public class TodoItemDTO { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } }

Update the

TodoItemsController

to use

TodoItemDTO

:


using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using TodoApi.Models; namespace TodoApi.Controllers; [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase { private readonly TodoContext _context; public TodoItemsController(TodoContext context) { _context = context; } // GET: api/TodoItems [HttpGet] public async Task

>> GetTodoItems() { return await _context.TodoItems .Select(x => ItemToDTO(x)) .ToListAsync(); } // GET: api/TodoItems/5 //

[HttpGet("{id}")] public async Task

> GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return ItemToDTO(todoItem); } //


// PUT: api/TodoItems/5 // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 //

[HttpPut("{id}")] public async Task

PutTodoItem(long id, TodoItemDTO todoDTO) { if (id != todoDTO.Id) { return BadRequest(); } var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } todoItem.Name = todoDTO.Name; todoItem.IsComplete = todoDTO.IsComplete; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) when (!TodoItemExists(id)) { return NotFound(); } return NoContent(); } //


// POST: api/TodoItems // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 //

[HttpPost] public async Task

> PostTodoItem(TodoItemDTO todoDTO) { var todoItem = new TodoItem { IsComplete = todoDTO.IsComplete, Name = todoDTO.Name }; _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); return CreatedAtAction( nameof(GetTodoItem), new { id = todoItem.Id }, ItemToDTO(todoItem)); } //


// DELETE: api/TodoItems/5 [HttpDelete("{id}")] public async Task

DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); } private bool TodoItemExists(long id) { return _context.TodoItems.Any(e => e.Id == id); } private static TodoItemDTO ItemToDTO(TodoItem todoItem) => new TodoItemDTO { Id = todoItem.Id, Name = todoItem.Name, IsComplete = todoItem.IsComplete }; }


Verify you can’t post or get the secret field.

Add a database context

The database context 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.

Add NuGet packages

  • From the Tools menu, select NuGet Package Manager > Manage NuGet Packages for Solution.
  • Select the Browse tab, and then enter

    Microsoft.EntityFrameworkCore.InMemory

    in the search box.
  • Select

    Microsoft.EntityFrameworkCore.InMemory

    in the left pane.
  • Select the Project checkbox in the right pane and then select Install.
(#70) Web API in MVC 5 project | mvc tutorial for beginners in .net c# | MVC By Nitish
(#70) Web API in MVC 5 project | mvc tutorial for beginners in .net c# | MVC By Nitish

Routing and URL paths

The

[HttpGet]

attribute denotes a method that responds to an

HTTP GET

request. The URL path for each method is constructed as follows:

  • Start with the template string in the controller’s


    Route

    attribute:

    [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase

  • Replace


    [controller]

    with the name of the controller, which by convention is the controller class name minus the “Controller” suffix. For this sample, the controller class name is TodoItemsController, so the controller name is “TodoItems”. ASP.NET Core routing is case insensitive.

  • If the


    [HttpGet]

    attribute has a route template (for example,

    [HttpGet("products")]

    ), append that to the path. This sample doesn’t use a template. For more information, see Attribute routing with Http[Verb] attributes.

In the following

GetTodoItem

method,

"{id}"

is a placeholder variable for the unique identifier of the to-do item. When

GetTodoItem

is invoked, the value of

"{id}"

in the URL is provided to the method in its

id

parameter.


[HttpGet("{id}")] public async Task

> GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; }

Add a model class

A model is a set of classes that represent the data that the app manages. The model for this app is the

TodoItem

class.

  • In Solution Explorer, right-click the project. Select Add > New Folder. Name the folder

    Models

    .
  • Right-click the

    Models

    folder and select Add > Class. Name the class TodoItem and select Add.
  • Replace the template code with the following:


namespace TodoApi.Models; public class TodoItem { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } }

The

Id

property functions as the unique key in a relational database.

Model classes can go anywhere in the project, but the

Models

folder is used by convention.

How To Consume WEB API in ASP.NET MVC
How To Consume WEB API in ASP.NET MVC

Prevent over-posting

Currently the sample app exposes the entire

TodoItem

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. DTO is used in this article.

A DTO may be used to:

  • Prevent over-posting.
  • Hide properties that clients are not supposed to view.
  • Omit some properties in order to reduce payload size.
  • Flatten object graphs that contain nested objects. Flattened object graphs can be more convenient for clients.

To demonstrate the DTO approach, update the

TodoItem

class to include a secret field:


namespace TodoApi.Models { public class TodoItem { public long Id { get; set; } public string Name { get; set; } public bool IsComplete { get; set; } public string Secret { get; set; } } }

The secret field needs to be hidden from this app, but an administrative app could choose to expose it.

Verify you can post and get the secret field.

Create a DTO model:


public class TodoItemDTO { public long Id { get; set; } public string Name { get; set; } public bool IsComplete { get; set; } }

Update the

TodoItemsController

to use

TodoItemDTO

:


// GET: api/TodoItems [HttpGet] public async Task

>> GetTodoItems() { return await _context.TodoItems .Select(x => ItemToDTO(x)) .ToListAsync(); } [HttpGet("{id}")] public async Task

> GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return ItemToDTO(todoItem); } [HttpPut("{id}")] public async Task

UpdateTodoItem(long id, TodoItemDTO todoItemDTO) { if (id != todoItemDTO.Id) { return BadRequest(); } var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } todoItem.Name = todoItemDTO.Name; todoItem.IsComplete = todoItemDTO.IsComplete; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) when (!TodoItemExists(id)) { return NotFound(); } return NoContent(); } [HttpPost] public async Task

> CreateTodoItem(TodoItemDTO todoItemDTO) { var todoItem = new TodoItem { IsComplete = todoItemDTO.IsComplete, Name = todoItemDTO.Name }; _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); return CreatedAtAction( nameof(GetTodoItem), new { id = todoItem.Id }, ItemToDTO(todoItem)); } [HttpDelete("{id}")] public async Task

DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); } private bool TodoItemExists(long id) => _context.TodoItems.Any(e => e.Id == id); private static TodoItemDTO ItemToDTO(TodoItem todoItem) => new TodoItemDTO { Id = todoItem.Id, Name = todoItem.Name, IsComplete = todoItem.IsComplete };





Verify you can’t post or get the secret field.

The PutTodoItem method

Examine the

PutTodoItem

method:


[HttpPut("{id}")] public async Task

PutTodoItem(long id, TodoItem todoItem) { if (id != todoItem.Id) { return BadRequest(); } _context.Entry(todoItem).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!TodoItemExists(id)) { return NotFound(); } else { throw; } } return NoContent(); }


PutTodoItem

is similar to

PostTodoItem

, except it uses

HTTP PUT

. The response is 204 (No Content). According to the HTTP specification, a

PUT

request requires the client to send the entire updated entity, not just the changes. To support partial updates, use HTTP PATCH.

Test the PutTodoItem method

This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PUT call. Call GET to ensure there’s an item in the database before making a PUT call.

Using the Swagger UI, use the PUT button to update the

TodoItem

that has Id = 1 and set its name to

"feed fish"

. Note the response is

HTTP 204 No Content

.

What is the difference between Web API and MVC Controller?
What is the difference between Web API and MVC Controller?

The DeleteTodoItem method

Examine the

DeleteTodoItem

method:


// DELETE: api/TodoItems/5 [HttpDelete("{id}")] public async Task

> DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return todoItem; }

Test the DeleteTodoItem method

Use Postman to delete a to-do item:

  • Set the method to

    DELETE

    .
  • Set the URI of the object to delete (for example

    https://localhost:5001/api/todoitems/1

    ).
  • Select Send.

Create a web project

  • From the File menu, select New > Project.
  • Select the ASP.NET Core Web Application template and click Next.
  • Name the project TodoApi and click Create.
  • In the Create a new ASP.NET Core Web Application dialog, confirm that .NET Core and ASP.NET Core 3.1 are selected. Select the API template and click Create.

Note

For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.

Test the API

The project template creates a

WeatherForecast

API. Call the

Get

method from a browser to test the app.

Press Ctrl+F5 to run the app. Visual Studio launches a browser and navigates to

https://localhost: /weatherforecast

, where is a randomly chosen port number.

If you get a dialog box that asks if you should trust the IIS Express certificate, select Yes. In the Security Warning dialog that appears next, select Yes.

JSON similar to the following is returned:


[ { "date": "2019-07-16T19:04:05.7257911-06:00", "temperatureC": 52, "temperatureF": 125, "summary": "Mild" }, { "date": "2019-07-17T19:04:05.7258461-06:00", "temperatureC": 36, "temperatureF": 96, "summary": "Warm" }, { "date": "2019-07-18T19:04:05.7258467-06:00", "temperatureC": 39, "temperatureF": 102, "summary": "Cool" }, { "date": "2019-07-19T19:04:05.7258471-06:00", "temperatureC": 10, "temperatureF": 49, "summary": "Bracing" }, { "date": "2019-07-20T19:04:05.7258474-06:00", "temperatureC": -1, "temperatureF": 31, "summary": "Chilly" } ]

Full CRUD Operations | How To Consume WEB API in ASP.NET Core MVC | Consuming Web API
Full CRUD Operations | How To Consume WEB API in ASP.NET Core MVC | Consuming Web API

Prevent over-posting

Currently the sample app exposes the entire

TodoItem

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. DTO is used in this tutorial.

A DTO may be used to:

  • Prevent over-posting.
  • Hide properties that clients are not supposed to view.
  • Omit some properties in order to reduce payload size.
  • Flatten object graphs that contain nested objects. Flattened object graphs can be more convenient for clients.

To demonstrate the DTO approach, update the

TodoItem

class to include a secret field:


namespace TodoApi.Models { public class TodoItem { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } public string? Secret { get; set; } } }

The secret field needs to be hidden from this app, but an administrative app could choose to expose it.

Verify you can post and get the secret field.

Create a DTO model:


namespace TodoApi.Models; public class TodoItemDTO { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } }

Update the

TodoItemsController

to use

TodoItemDTO

:


using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using TodoApi.Models; namespace TodoApi.Controllers; [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase { private readonly TodoContext _context; public TodoItemsController(TodoContext context) { _context = context; } // GET: api/TodoItems [HttpGet] public async Task

>> GetTodoItems() { return await _context.TodoItems .Select(x => ItemToDTO(x)) .ToListAsync(); } // GET: api/TodoItems/5 //

[HttpGet("{id}")] public async Task

> GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return ItemToDTO(todoItem); } //


// PUT: api/TodoItems/5 // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 //

[HttpPut("{id}")] public async Task

PutTodoItem(long id, TodoItemDTO todoDTO) { if (id != todoDTO.Id) { return BadRequest(); } var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } todoItem.Name = todoDTO.Name; todoItem.IsComplete = todoDTO.IsComplete; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) when (!TodoItemExists(id)) { return NotFound(); } return NoContent(); } //


// POST: api/TodoItems // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 //

[HttpPost] public async Task

> PostTodoItem(TodoItemDTO todoDTO) { var todoItem = new TodoItem { IsComplete = todoDTO.IsComplete, Name = todoDTO.Name }; _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); return CreatedAtAction( nameof(GetTodoItem), new { id = todoItem.Id }, ItemToDTO(todoItem)); } //


// DELETE: api/TodoItems/5 [HttpDelete("{id}")] public async Task

DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); } private bool TodoItemExists(long id) { return _context.TodoItems.Any(e => e.Id == id); } private static TodoItemDTO ItemToDTO(TodoItem todoItem) => new TodoItemDTO { Id = todoItem.Id, Name = todoItem.Name, IsComplete = todoItem.IsComplete }; }


Verify you can’t post or get the secret field.

Return values

The return type of the

GetTodoItems

and

GetTodoItem

methods is ActionResult

type. ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. The response code for this return type is 200 OK, assuming there are no unhandled exceptions. Unhandled exceptions are translated into 5xx errors.


ActionResult

return types can represent a wide range of HTTP status codes. For example,

GetTodoItem

can return two different status values:

  • If no item matches the requested ID, the method returns a 404 status NotFound error code.
  • Otherwise, the method returns 200 with a JSON response body. Returning

    item

    results in an

    HTTP 200

    response.
Nhận định thị trường chứng khoán hàng ngày | Phân tích vnindex, cổ phiếu tiềm năng hôm nay
Nhận định thị trường chứng khoán hàng ngày | Phân tích vnindex, cổ phiếu tiềm năng hôm nay

Register the database context

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

Program.cs

with the following code:


using Microsoft.EntityFrameworkCore; using TodoApi.Models; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddDbContext

(opt => opt.UseInMemoryDatabase("TodoList")); //builder.Services.AddSwaggerGen(c => //{ // c.SwaggerDoc("v1", new() { Title = "TodoApi", Version = "v1" }); //}); var app = builder.Build(); // Configure the HTTP request pipeline. if (builder.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); //app.UseSwagger(); //app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TodoApi v1")); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();

The preceding code:

  • Removes the Swagger calls.
  • Removes unused

    using

    directives.
  • Adds the database context to the DI container.
  • Specifies that the database context will use an in-memory database.

The DeleteTodoItem method

Examine the

DeleteTodoItem

method:


[HttpDelete("{id}")] public async Task

DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); }

Test the DeleteTodoItem method

Delete the to-do item that has Id = 1:


connect https://localhost:5001/api/todoitems/1 delete

Here’s an example of the output from the command:


HTTP/1.1 204 No Content Date: Tue, 07 Sep 2021 21:43:00 GMT Server: Kestrel

Cổ phiếu top 2 mai tăng: VGS, TLH, DIG, DXG Cảnh giá vùng 1200 | Nhận định thị trường chứng khoán
Cổ phiếu top 2 mai tăng: VGS, TLH, DIG, DXG Cảnh giá vùng 1200 | Nhận định thị trường chứng khoán

Update the PostTodoItem create method

Update the return statement in the

PostTodoItem

to use the nameof operator:


[HttpPost] public async Task

> PostTodoItem(TodoItem todoItem) { _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); // return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem); return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem); }

The preceding code is an

HTTP POST

method, as indicated by the

[HttpPost]

attribute. The method gets the value of the

TodoItem

from the body of the HTTP request.

For more information, see Attribute routing with Http[Verb] attributes.

The CreatedAtAction method:

  • Returns an HTTP 201 status code if successful.

    HTTP 201

    is the standard response for an

    HTTP POST

    method that creates a new resource on the server.
  • Adds a Location header to the response. The

    Location

    header specifies the URI of the newly created to-do item. For more information, see 10.2.2 201 Created.
  • References the

    GetTodoItem

    action to create the

    Location

    header’s URI. The C#

    nameof

    keyword is used to avoid hard-coding the action name in the

    CreatedAtAction

    call.

Test PostTodoItem

  • Press Ctrl+F5 to run the app.

  • In the Swagger browser window, select POST /api/TodoItems, and then select Try it out.

  • In the Request body input window, update the JSON. For example,


    { "name": "walk dog", "isComplete": true }

  • Select Execute

Test the location header URI

In the preceding POST, the Swagger UI shows the location header under Response headers. For example,

location: https://localhost:7260/api/TodoItems/1

. The location header shows the URI to the created resource.

To test the location header:

  • In the Swagger browser window, select GET /api/TodoItems/{id}, and then select Try it out.

  • Enter

    in the

    id

    input box, and then select Execute.

Return values

The return type of the

GetTodoItems

and

GetTodoItem

methods is ActionResult

type. ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. The response code for this return type is 200 OK, assuming there are no unhandled exceptions. Unhandled exceptions are translated into 5xx errors.


ActionResult

return types can represent a wide range of HTTP status codes. For example,

GetTodoItem

can return two different status values:

  • If no item matches the requested ID, the method returns a 404 status NotFound error code.
  • Otherwise, the method returns 200 with a JSON response body. Returning

    item

    results in an HTTP 200 response.
Full Course - Learn ASP.NET Core MVC in .NET 8 | CRUD Operations | EntityFramework | MVC Tutorial
Full Course – Learn ASP.NET Core MVC in .NET 8 | CRUD Operations | EntityFramework | MVC Tutorial

Create a web project

  • From the File menu, select New > Project.
  • Enter Web API in the search box.
  • Select the ASP.NET Core Web API template and select Next.
  • In the Configure your new project dialog, name the project TodoApi and select Next.
  • In the Additional information dialog:

    • Confirm the Framework is .NET 7.0 (or later).
    • Confirm the checkbox for Use controllers(uncheck to use minimal APIs) is checked.
    • Select Create.

Note

For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.

Test the project

The project template creates a

WeatherForecast

API with support for Swagger.

Press Ctrl+F5 to run without the debugger.

Visual Studio displays the following dialog when a project is not yet configured to use SSL:

Select Yes if you trust the IIS Express SSL certificate.

The following dialog is displayed:

Select Yes if you agree to trust the development certificate.

For information on trusting the Firefox browser, see Firefox SEC_ERROR_INADEQUATE_KEY_USAGE certificate error.

Visual Studio launches the default browser and navigates to

https://localhost: /swagger/index.html

, where is a randomly chosen port number.

The Swagger page

/swagger/index.html

is displayed. Select GET > Try it out > Execute. The page displays:

  • The Curl command to test the WeatherForecast API.
  • The URL to test the WeatherForecast API.
  • The response code, body, and headers.
  • A drop-down list box with media types and the example value and schema.

If the Swagger page doesn’t appear, see this GitHub issue.

Swagger is used to generate useful documentation and help pages for web APIs. This tutorial focuses on creating a web API. For more information on Swagger, see ASP.NET Core web API documentation with Swagger / OpenAPI.

Copy and paste the Request URL in the browser:

https://localhost: /weatherforecast

JSON similar to the following example is returned:


[ { "date": "2019-07-16T19:04:05.7257911-06:00", "temperatureC": 52, "temperatureF": 125, "summary": "Mild" }, { "date": "2019-07-17T19:04:05.7258461-06:00", "temperatureC": 36, "temperatureF": 96, "summary": "Warm" }, { "date": "2019-07-18T19:04:05.7258467-06:00", "temperatureC": 39, "temperatureF": 102, "summary": "Cool" }, { "date": "2019-07-19T19:04:05.7258471-06:00", "temperatureC": 10, "temperatureF": 49, "summary": "Bracing" }, { "date": "2019-07-20T19:04:05.7258474-06:00", "temperatureC": -1, "temperatureF": 31, "summary": "Chilly" } ]

Return values

The return type of the

GetTodoItems

and

GetTodoItem

methods is ActionResult

type. ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. The response code for this return type is 200, assuming there are no unhandled exceptions. Unhandled exceptions are translated into 5xx errors.


ActionResult

return types can represent a wide range of HTTP status codes. For example,

GetTodoItem

can return two different status values:

  • If no item matches the requested ID, the method returns a 404 NotFound error code.
  • Otherwise, the method returns 200 with a JSON response body. Returning

    item

    results in an HTTP 200 response.
Difference Between REST API vs Web API vs SOAP API Explained
Difference Between REST API vs Web API vs SOAP API Explained

Web API with MVC Project

Visual Studio (2019/2022) includes Web API template which creates a new Web API project with ASP.NET MVC application and includes all the necessary references to get started.

For this, open Visual Studio and click on File menu and click on New Project. This will open New Project popup as below.

In the New Project popup, expand Visual C# and select Web node in the left pane. Select ASP.NET Web Application template in the middle pane and enter the name of a project and click OK. (ASP.NET Web Application (.NET Framework) template in Visual Studio 2017.)

This will open New ASP.NET Project popup as shown below.

Select Web API in the above popup. Notice that this has selected and disabled MVC and Web API checkboxes. It means that it will add necessary folders and references for both MVC and Web API.

Click Ok to create a new Web API + MVC project as shown below.

This project is same as default MVC project with two specific files for Web API, WebApiConfig.cs in App_Start folder and ValuesController.cs in Controllers folder as shown below.

The WebApiConfig.cs is configuration file for Web API. You can configure routes and other things for web API, same like RouteConfig.cs is used to configure MVC routes. It also creates Web API controller ValuesController.cs by default. You will learn about WebApiConfig and Controller in the next section.

Thus, you can create Web API project with MVC to get started on your application.

Add a model class

A model is a set of classes that represent the data that the app manages. The model for this app is the

TodoItem

class.

  • In Solution Explorer, right-click the project. Select Add > New Folder. Name the folder

    Models

    .
  • Right-click the

    Models

    folder and select Add > Class. Name the class TodoItem and select Add.
  • Replace the template code with the following:


namespace TodoApi.Models; public class TodoItem { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } }

The

Id

property functions as the unique key in a relational database.

Model classes can go anywhere in the project, but the

Models

folder is used by convention.

JSON Web Tokens (JWT) in .NET 6 Web API 🔒 - User Registration / Login / Authentication
JSON Web Tokens (JWT) in .NET 6 Web API 🔒 – User Registration / Login / Authentication

Create a web project

  • From the File menu, select New > Project.
  • Enter Web API in the search box.
  • Select the ASP.NET Core Web API template and select Next.
  • In the Configure your new project dialog, name the project TodoApi and select Next.
  • In the Additional information dialog:

    • Confirm the Framework is .NET 6.0 (Long-term support).
    • Confirm the checkbox for Use controllers(uncheck to use minimal APIs) is checked.
    • Select Create.

Note

For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.

Test the project

The project template creates a

WeatherForecast

API with support for Swagger.

Press Ctrl+F5 to run without the debugger.

Visual Studio displays the following dialog when a project is not yet configured to use SSL:

Select Yes if you trust the IIS Express SSL certificate.

The following dialog is displayed:

Select Yes if you agree to trust the development certificate.

For information on trusting the Firefox browser, see Firefox SEC_ERROR_INADEQUATE_KEY_USAGE certificate error.

Visual Studio launches the default browser and navigates to

https://localhost: /swagger/index.html

, where is a randomly chosen port number.

The Swagger page

/swagger/index.html

is displayed. Select GET > Try it out > Execute. The page displays:

  • The Curl command to test the WeatherForecast API.
  • The URL to test the WeatherForecast API.
  • The response code, body, and headers.
  • A drop-down list box with media types and the example value and schema.

If the Swagger page doesn’t appear, see this GitHub issue.

Swagger is used to generate useful documentation and help pages for web APIs. This tutorial focuses on creating a web API. For more information on Swagger, see ASP.NET Core web API documentation with Swagger / OpenAPI.

Copy and paste the Request URL in the browser:

https://localhost: /weatherforecast

JSON similar to the following example is returned:


[ { "date": "2019-07-16T19:04:05.7257911-06:00", "temperatureC": 52, "temperatureF": 125, "summary": "Mild" }, { "date": "2019-07-17T19:04:05.7258461-06:00", "temperatureC": 36, "temperatureF": 96, "summary": "Warm" }, { "date": "2019-07-18T19:04:05.7258467-06:00", "temperatureC": 39, "temperatureF": 102, "summary": "Cool" }, { "date": "2019-07-19T19:04:05.7258471-06:00", "temperatureC": 10, "temperatureF": 49, "summary": "Bracing" }, { "date": "2019-07-20T19:04:05.7258474-06:00", "temperatureC": -1, "temperatureF": 31, "summary": "Chilly" } ]

Update the launchUrl

In Properties\launchSettings.json, update

launchUrl

from

"swagger"

to

"api/todoitems"

:


"launchUrl": "api/todoitems",

Because Swagger will be removed, the preceding markup changes the URL that is launched to the GET method of the controller added in the following sections.

Examine the GET methods

These methods implement two GET endpoints:


  • GET /api/todoitems

  • GET /api/todoitems/{id}

Test the app by calling the two endpoints from a browser or Postman. For example:


  • https://localhost:5001/api/todoitems

  • https://localhost:5001/api/todoitems/1

A response similar to the following is produced by the call to

GetTodoItems

:


[ { "id": 1, "name": "Item1", "isComplete": false } ]

Test Get with Postman

  • Create a new request.
  • Set the HTTP method to GET.
  • Set the request URI to

    https://localhost: /api/todoitems

    . For example,

    https://localhost:5001/api/todoitems

    .
  • Set Two pane view in Postman.
  • Select Send.

This app uses an in-memory database. If the app is stopped and started, the preceding GET request will not return any data. If no data is returned, POST data to the app.

Image handling in .NET Core Web API | Image upload with single & multiple files in Server path & DB
Image handling in .NET Core Web API | Image upload with single & multiple files in Server path & DB

Update the PostTodoItem create method

Update the return statement in the

PostTodoItem

to use the nameof operator:


[HttpPost] public async Task

> PostTodoItem(TodoItem todoItem) { _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); // return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem); return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem); }

The preceding code is an

HTTP POST

method, as indicated by the

[HttpPost]

attribute. The method gets the value of the

TodoItem

from the body of the HTTP request.

For more information, see Attribute routing with Http[Verb] attributes.

The CreatedAtAction method:

  • Returns an HTTP 201 status code if successful.

    HTTP 201

    is the standard response for an

    HTTP POST

    method that creates a new resource on the server.
  • Adds a Location header to the response. The

    Location

    header specifies the URI of the newly created to-do item. For more information, see 10.2.2 201 Created.
  • References the

    GetTodoItem

    action to create the

    Location

    header’s URI. The C#

    nameof

    keyword is used to avoid hard-coding the action name in the

    CreatedAtAction

    call.

Test PostTodoItem

  • Press Ctrl+F5 to run the app.

  • In the Swagger browser window, select POST /api/TodoItems, and then select Try it out.

  • In the Request body input window, update the JSON. For example,


    { "name": "walk dog", "isComplete": true }

  • Select Execute

Test the location header URI

In the preceding POST, the Swagger UI shows the location header under Response headers. For example,

location: https://localhost:7260/api/TodoItems/1

. The location header shows the URI to the created resource.

To test the location header:

  • In the Swagger browser window, select GET /api/TodoItems/{id}, and then select Try it out.

  • Enter

    in the

    id

    input box, and then select Execute.

Register the database context

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

Program.cs

with the following code:


using Microsoft.EntityFrameworkCore; using TodoApi.Models; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddDbContext

(opt => opt.UseInMemoryDatabase("TodoList")); //builder.Services.AddSwaggerGen(c => //{ // c.SwaggerDoc("v1", new() { Title = "TodoApi", Version = "v1" }); //}); var app = builder.Build(); // Configure the HTTP request pipeline. if (builder.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); //app.UseSwagger(); //app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TodoApi v1")); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();

The preceding code:

  • Removes the Swagger calls.
  • Removes unused

    using

    directives.
  • Adds the database context to the DI container.
  • Specifies that the database context will use an in-memory database.
.NET 7.0 Web API Full course with CRUD actions, Authentication, FileHandling & IIS Deployment - 2023
.NET 7.0 Web API Full course with CRUD actions, Authentication, FileHandling & IIS Deployment – 2023

The PutTodoItem method

Examine the

PutTodoItem

method:


[HttpPut("{id}")] public async Task

PutTodoItem(long id, TodoItem todoItem) { if (id != todoItem.Id) { return BadRequest(); } _context.Entry(todoItem).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!TodoItemExists(id)) { return NotFound(); } else { throw; } } return NoContent(); }


PutTodoItem

is similar to

PostTodoItem

, except it uses

HTTP PUT

. The response is 204 (No Content). According to the HTTP specification, a

PUT

request requires the client to send the entire updated entity, not just the changes. To support partial updates, use HTTP PATCH.

Test the PutTodoItem method

This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PUT call. Call GET to ensure there’s an item in the database before making a PUT call.

Using the Swagger UI, use the PUT button to update the

TodoItem

that has Id = 1 and set its name to

"feed fish"

. Note the response is

HTTP 204 No Content

.

Add a database context

The database context 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.

Add NuGet packages

  • From the Tools menu, select NuGet Package Manager > Manage NuGet Packages for Solution.
  • Select the Browse tab, and then enter

    Microsoft.EntityFrameworkCore.InMemory

    in the search box.
  • Select

    Microsoft.EntityFrameworkCore.InMemory

    in the left pane.
  • Select the Project checkbox in the right pane and then select Install.
Part 9 Routing in Web/REST api #1 || Asp.Net Core Web API Tutorials C#
Part 9 Routing in Web/REST api #1 || Asp.Net Core Web API Tutorials C#

Add authentication support to a web API

ASP.NET Core Identity adds user interface (UI) login functionality to ASP.NET Core web apps. To secure web APIs and SPAs, use one of the following:

  • Microsoft Entra ID
  • Azure Active Directory B2C (Azure AD B2C)
  • Duende Identity Server

Duende Identity Server is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core. Duende Identity Server enables the following security features:

  • Authentication as a Service (AaaS)
  • Single sign-on/off (SSO) over multiple application types
  • Access control for APIs
  • Federation Gateway

Important

Duende Software might require you to pay a license fee for production use of Duende Identity Server. For more information, see Migrate from ASP.NET Core 5.0 to 6.0.

For more information, see the Duende Identity Server documentation (Duende Software website).

Return values

The return type of the

GetTodoItems

and

GetTodoItem

methods is ActionResult

type. ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. The response code for this return type is 200 OK, assuming there are no unhandled exceptions. Unhandled exceptions are translated into 5xx errors.


ActionResult

return types can represent a wide range of HTTP status codes. For example,

GetTodoItem

can return two different status values:

  • If no item matches the requested ID, the method returns a 404 status NotFound error code.
  • Otherwise, the method returns 200 with a JSON response body. Returning

    item

    results in an

    HTTP 200

    response.
.NET Core 3.1 MVC REST API - Full Course
.NET Core 3.1 MVC REST API – Full Course

Update the PostTodoItem create method

Update the return statement in the

PostTodoItem

to use the nameof operator:


[HttpPost] public async Task

> PostTodoItem(TodoItem todoItem) { _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); //return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem); return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem); }

The preceding code is an HTTP POST method, as indicated by the

[HttpPost]

attribute. The method gets the value of the to-do item from the body of the HTTP request.

For more information, see Attribute routing with Http[Verb] attributes.

The CreatedAtAction method:

  • Returns an HTTP 201 status code if successful. HTTP 201 is the standard response for an HTTP POST method that creates a new resource on the server.
  • Adds a Location header to the response. The

    Location

    header specifies the URI of the newly created to-do item. For more information, see 10.2.2 201 Created.
  • References the

    GetTodoItem

    action to create the

    Location

    header’s URI. The C#

    nameof

    keyword is used to avoid hard-coding the action name in the

    CreatedAtAction

    call.

Install http-repl

This tutorial uses http-repl to test the web API.

  • Run the following command at a command prompt:


    dotnet tool install -g Microsoft.dotnet-httprepl

    Note

    By default the architecture of the .NET binaries to install represents the currently running OS architecture. To specify a different OS architecture, see dotnet tool install, –arch option. For more information, see GitHub issue dotnet/AspNetCore.Docs #29262.

  • If you don’t have the .NET 6.0 SDK or runtime installed, install the .NET 6.0 runtime.

Test PostTodoItem

  • Press Ctrl+F5 to run the app.

  • Open a new terminal window, and run the following commands. If your app uses a different port number, replace 5001 in the httprepl command with your port number.


    httprepl https://localhost:5001/api/todoitems post -h Content-Type=application/json -c "{"name":"walk dog","isComplete":true}"

    Here’s an example of the output from the command:


    HTTP/1.1 201 Created Content-Type: application/json; charset=utf-8 Date: Tue, 07 Sep 2021 20:39:47 GMT Location: https://localhost:5001/api/TodoItems/1 Server: Kestrel Transfer-Encoding: chunked { "id": 1, "name": "walk dog", "isComplete": true }

Test the location header URI

To test the location header, copy and paste it into an httprepl

get

command.

The following example assumes that you’re still in an httprepl session. If you ended the previous httprepl session, replace

connect

with

httprepl

in the following commands:


connect https://localhost:5001/api/todoitems/1 get

Here’s an example of the output from the command:


HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Tue, 07 Sep 2021 20:48:10 GMT Server: Kestrel Transfer-Encoding: chunked { "id": 1, "name": "walk dog", "isComplete": true }

Additional resources

View or download sample code for this tutorial. See how to download.

For more information, see the following resources:

  • Create web APIs with ASP.NET Core
  • Tutorial: Create a minimal API with ASP.NET Core
  • ASP.NET Core web API documentation with Swagger / OpenAPI
  • Razor Pages with Entity Framework Core in ASP.NET Core – Tutorial 1 of 8
  • Routing to controller actions in ASP.NET Core
  • Controller action return types in ASP.NET Core web API
  • Deploy ASP.NET Core apps to Azure App Service
  • Host and deploy ASP.NET Core
  • Create a web API with ASP.NET Core

This tutorial teaches the basics of building a controller-based web API that uses a database. Another approach to creating APIs in ASP.NET Core is to create minimal APIs. For help in choosing between minimal APIs and controller-based APIs, see APIs overview. For a tutorial on creating a minimal API, see Tutorial: Create a minimal API with ASP.NET Core.

In this tutorial, you learn how to:

  • Create a web API project.
  • Add a model class and a database context.
  • Scaffold a controller with CRUD methods.
  • Configure routing, URL paths, and return values.
  • Call the web API with Postman.

At the end, you have a web API that can manage “to-do” items stored in a database.

Project mẫu: ASP.Net Core MVC API
Project mẫu: ASP.Net Core MVC API

Why to use the Web API

Currently most mobile devices, browsers and tablets are the medium for accessing most of the internet and in this also people are using mobile apps the most and to provide data to apps we are now going to use the Microsoft new technology called Web API.

When to use it

If you want to expose the data/information of your application to your clients and other people then that other people can use your data and interact with the data/information you expose to them.

For example, a mobile application requires a service.

HTML 5 requires a service.

Desktop PC and tablets require services.

Currently most device apps require Web API services.

The ASP.Net Framework leverages both web standards such as HTTP, JSON and XML and it provides a simple way to build and expose REST based data services.

Some core concepts of ASP.Net MVC are similar to the ASP.Net Web API such as routing and controllers.

Requirements

We are using Visual Studio 2012 for a demo application.

Examine the GET methods

Two GET endpoints are implemented:


  • GET /api/todoitems

  • GET /api/todoitems/{id}

The previous section showed an example of the

/api/todoitems/{id}

route.

Follow the POST instructions to add another todo item, and then test the

/api/todoitems

route using Swagger.

This app uses an in-memory database. If the app is stopped and started, the preceding GET request will not return any data. If no data is returned, POST data to the app.

Consuming Web API In ASP.NET MVC | CRUD Operations In ASP.NET MVC with Web API
Consuming Web API In ASP.NET MVC | CRUD Operations In ASP.NET MVC with Web API

The PutTodoItem method

Examine the

PutTodoItem

method:


[HttpPut("{id}")] public async Task

PutTodoItem(long id, TodoItem todoItem) { if (id != todoItem.Id) { return BadRequest(); } _context.Entry(todoItem).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!TodoItemExists(id)) { return NotFound(); } else { throw; } } return NoContent(); }


PutTodoItem

is similar to

PostTodoItem

, except it uses HTTP PUT. The response is 204 (No Content). According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. To support partial updates, use HTTP PATCH.

If you get an error calling

PutTodoItem

in the following section, call

GET

to ensure there’s an item in the database.

Test the PutTodoItem method

This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PUT call. Call GET to ensure there’s an item in the database before making a PUT call.

Update the to-do item that has Id = 1 and set its name to

"feed fish"

:


connect https://localhost:5001/api/todoitems/1 put -h Content-Type=application/json -c "{"id":1,"name":"feed fish","isComplete":true}"

Here’s an example of the output from the command:


HTTP/1.1 204 No Content Date: Tue, 07 Sep 2021 21:20:47 GMT Server: Kestrel

Additional resources

View or download sample code for this tutorial. See how to download.

For more information, see the following resources:

  • Create web APIs with ASP.NET Core
  • Tutorial: Create a minimal API with ASP.NET Core
  • ASP.NET Core web API documentation with Swagger / OpenAPI
  • Razor Pages with Entity Framework Core in ASP.NET Core – Tutorial 1 of 8
  • Routing to controller actions in ASP.NET Core
  • Controller action return types in ASP.NET Core web API
  • Deploy ASP.NET Core apps to Azure App Service
  • Host and deploy ASP.NET Core
  • Create a web API with ASP.NET Core

This tutorial teaches the basics of building a controller-based web API that uses a database. Another approach to creating APIs in ASP.NET Core is to create minimal APIs. For help in choosing between minimal APIs and controller-based APIs, see APIs overview. For a tutorial on creating a minimal API, see Tutorial: Create a minimal API with ASP.NET Core.

In this tutorial, you learn how to:

  • Create a web API project.
  • Add a model class and a database context.
  • Scaffold a controller with CRUD methods.
  • Configure routing, URL paths, and return values.
  • Call the web API with Postman.

At the end, you have a web API that can manage “to-do” items stored in a database.

Web API CRUD Operations Using Asp Net MVC and Entity Framework
Web API CRUD Operations Using Asp Net MVC and Entity Framework

Routing and URL paths

The

[HttpGet]

attribute denotes a method that responds to an HTTP GET request. The URL path for each method is constructed as follows:

  • Start with the template string in the controller’s


    Route

    attribute:

    [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase { private readonly TodoContext _context; public TodoItemsController(TodoContext context) { _context = context; }

  • Replace


    [controller]

    with the name of the controller, which by convention is the controller class name minus the “Controller” suffix. For this sample, the controller class name is TodoItemsController, so the controller name is “TodoItems”. ASP.NET Core routing is case insensitive.

  • If the


    [HttpGet]

    attribute has a route template (for example,

    [HttpGet("products")]

    ), append that to the path. This sample doesn’t use a template. For more information, see Attribute routing with Http[Verb] attributes.

In the following

GetTodoItem

method,

"{id}"

is a placeholder variable for the unique identifier of the to-do item. When

GetTodoItem

is invoked, the value of

"{id}"

in the URL is provided to the method in its

id

parameter.


// GET: api/TodoItems/5 [HttpGet("{id}")] public async Task

> GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; }

The DeleteTodoItem method

Examine the

DeleteTodoItem

method:


[HttpDelete("{id}")] public async Task

DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); }

Test the DeleteTodoItem method

Use the Swagger UI to delete the

TodoItem

that has Id = 1. Note the response is

HTTP 204 No Content

.

how to create web api in asp.net mvc
how to create web api in asp.net mvc

Examine the GET methods

Two GET endpoints are implemented:


  • GET /api/todoitems

  • GET /api/todoitems/{id}

The previous section showed an example of the

/api/todoitems/{id}

route.

Follow the POST instructions to add another todo item, and then test the

/api/todoitems

route using Swagger.

This app uses an in-memory database. If the app is stopped and started, the preceding GET request will not return any data. If no data is returned, POST data to the app.

Add a database context

The database context 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.

  • Right-click the

    Models

    folder and select Add > Class. Name the class TodoContext and click Add.
  • Enter the following code:


    using Microsoft.EntityFrameworkCore; namespace TodoApi.Models; public class TodoContext : DbContext { public TodoContext(DbContextOptions

    options) : base(options) { } public DbSet

    TodoItems { get; set; } = null!; }


ASP.NET MVC Web API - Truy vấn dòng thông qua Web API & Ajax
ASP.NET MVC Web API – Truy vấn dòng thông qua Web API & Ajax

Scaffold a controller

  • Right-click the Controllers folder.

  • Select Add > New Scaffolded Item.

  • Select API Controller with actions, using Entity Framework, and then select Add.

  • In the Add API Controller with actions, using Entity Framework dialog:

    • Select TodoItem (TodoApi.Models) in the Model class.
    • Select TodoContext (TodoApi.Models) in the Data context class.
    • Select Add.

The generated code:

  • Marks the class with the

    [ApiController]

    attribute. This attribute indicates that the controller responds to web API requests. For information about specific behaviors that the attribute enables, see Create web APIs with ASP.NET Core.
  • Uses DI to inject the database context (

    TodoContext

    ) into the controller. The database context is used in each of the CRUD methods in the controller.

The ASP.NET Core templates for:

  • Controllers with views include

    [action]

    in the route template.
  • API controllers don’t include

    [action]

    in the route template.

When the

[action]

token isn’t in the route template, the action name is excluded from the route. That is, the action’s associated method name isn’t used in the matching route.

Register the database context

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

Program.cs

with the following highlighted code:


using Microsoft.EntityFrameworkCore; using TodoApi.Models; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddDbContext

(opt => opt.UseInMemoryDatabase("TodoList")); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();

The preceding code:

  • Adds

    using

    directives.
  • Adds the database context to the DI container.
  • Specifies that the database context will use an in-memory database.
[WebAPI-NET5] #1 - Tạo API đầu tiên
[WebAPI-NET5] #1 – Tạo API đầu tiên

Add authentication support to a web API

ASP.NET Core Identity adds user interface (UI) login functionality to ASP.NET Core web apps. To secure web APIs and SPAs, use one of the following:

  • Microsoft Entra ID
  • Azure Active Directory B2C (Azure AD B2C)
  • Duende Identity Server

Duende Identity Server is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core. Duende Identity Server enables the following security features:

  • Authentication as a Service (AaaS)
  • Single sign-on/off (SSO) over multiple application types
  • Access control for APIs
  • Federation Gateway

Important

Duende Software might require you to pay a license fee for production use of Duende Identity Server. For more information, see Migrate from ASP.NET Core 5.0 to 6.0.

For more information, see the Duende Identity Server documentation (Duende Software website).

Prevent over-posting

Currently the sample app exposes the entire

TodoItem

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. DTO is used in this article.

A DTO may be used to:

  • Prevent over-posting.
  • Hide properties that clients are not supposed to view.
  • Omit some properties in order to reduce payload size.
  • Flatten object graphs that contain nested objects. Flattened object graphs can be more convenient for clients.

To demonstrate the DTO approach, update the

TodoItem

class to include a secret field:


public class TodoItem { public long Id { get; set; } public string Name { get; set; } public bool IsComplete { get; set; } public string Secret { get; set; } }

The secret field needs to be hidden from this app, but an administrative app could choose to expose it.

Verify you can post and get the secret field.

Create a DTO model:


public class TodoItemDTO { public long Id { get; set; } public string Name { get; set; } public bool IsComplete { get; set; } }

Update the

TodoItemsController

to use

TodoItemDTO

:


[HttpGet] public async Task

>> GetTodoItems() { return await _context.TodoItems .Select(x => ItemToDTO(x)) .ToListAsync(); } [HttpGet("{id}")] public async Task

> GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return ItemToDTO(todoItem); } [HttpPut("{id}")] public async Task

UpdateTodoItem(long id, TodoItemDTO todoItemDTO) { if (id != todoItemDTO.Id) { return BadRequest(); } var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } todoItem.Name = todoItemDTO.Name; todoItem.IsComplete = todoItemDTO.IsComplete; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) when (!TodoItemExists(id)) { return NotFound(); } return NoContent(); } [HttpPost] public async Task

> CreateTodoItem(TodoItemDTO todoItemDTO) { var todoItem = new TodoItem { IsComplete = todoItemDTO.IsComplete, Name = todoItemDTO.Name }; _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); return CreatedAtAction( nameof(GetTodoItem), new { id = todoItem.Id }, ItemToDTO(todoItem)); } [HttpDelete("{id}")] public async Task

DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); } private bool TodoItemExists(long id) => _context.TodoItems.Any(e => e.Id == id); private static TodoItemDTO ItemToDTO(TodoItem todoItem) => new TodoItemDTO { Id = todoItem.Id, Name = todoItem.Name, IsComplete = todoItem.IsComplete }; }





Verify you can’t post or get the secret field.

Add a model class

A model is a set of classes that represent the data that the app manages. The model for this app is a single

TodoItem

class.

  • In Solution Explorer, right-click the project. Select Add > New Folder. Name the folder


    Models

    .

  • Right-click the


    Models

    folder and select Add > Class. Name the class TodoItem and select Add.

  • Replace the template code with the following:


namespace TodoApi.Models { public class TodoItem { public long Id { get; set; } public string Name { get; set; } public bool IsComplete { get; set; } } }

The

Id

property functions as the unique key in a relational database.

Model classes can go anywhere in the project, but the

Models

folder is used by convention.

The PutTodoItem method

Examine the

PutTodoItem

method:


// PUT: api/TodoItems/5 [HttpPut("{id}")] public async Task

PutTodoItem(long id, TodoItem todoItem) { if (id != todoItem.Id) { return BadRequest(); } _context.Entry(todoItem).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!TodoItemExists(id)) { return NotFound(); } else { throw; } } return NoContent(); }


PutTodoItem

is similar to

PostTodoItem

, except it uses HTTP PUT. The response is 204 (No Content). According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. To support partial updates, use HTTP PATCH.

If you get an error calling

PutTodoItem

, call

GET

to ensure there’s an item in the database.

Test the PutTodoItem method

This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PUT call. Call GET to ensure there’s an item in the database before making a PUT call.

Update the to-do item that has Id = 1 and set its name to “feed fish”:


{ "id":1, "name":"feed fish", "isComplete":true }

The following image shows the Postman update:

Examine the GET methods

Two GET endpoints are implemented:


  • GET /api/todoitems

  • GET /api/todoitems/{id}

The previous section showed an example of the

/api/todoitems/{id}

route.

Follow the POST instructions to add another todo item, and then test the

/api/todoitems

route using Swagger.

This app uses an in-memory database. If the app is stopped and started, the preceding GET request will not return any data. If no data is returned, POST data to the app.

The DeleteTodoItem method

Examine the

DeleteTodoItem

method:


// DELETE: api/TodoItems/5 [HttpDelete("{id}")] public async Task

DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); }

Test the DeleteTodoItem method

Use Postman to delete a to-do item:

  • Set the method to

    DELETE

    .
  • Set the URI of the object to delete (for example

    https://localhost:5001/api/todoitems/1

    ).
  • Select Send.

Create a web project

  • From the File menu, select New > Project.
  • Enter Web API in the search box.
  • Select the ASP.NET Core Web API template and select Next.
  • In the Configure your new project dialog, name the project TodoApi and select Next.
  • In the Additional information dialog:

    • Confirm the Framework is .NET 8.0 (Long Term Support).
    • Confirm the checkbox for Use controllers(uncheck to use minimal APIs) is checked.
    • Confirm the checkbox for Enable OpenAPI support is checked.
    • Select Create.

Additional resources

View or download sample code for this tutorial. See how to download.

For more information, see the following resources:

  • Create web APIs with ASP.NET Core
  • Tutorial: Create a minimal API with ASP.NET Core
  • ASP.NET Core web API documentation with Swagger / OpenAPI
  • Razor Pages with Entity Framework Core in ASP.NET Core – Tutorial 1 of 8
  • Routing to controller actions in ASP.NET Core
  • Controller action return types in ASP.NET Core web API
  • Deploy ASP.NET Core apps to Azure App Service
  • Host and deploy ASP.NET Core
  • Create a web API with ASP.NET Core

This tutorial teaches the basics of building a controller-based web API that uses a database. Another approach to creating APIs in ASP.NET Core is to create minimal APIs. For help in choosing between minimal APIs and controller-based APIs, see APIs overview. For a tutorial on creating a minimal API, see Tutorial: Create a minimal API with ASP.NET Core.

In this tutorial, you learn how to:

  • Create a web API project.
  • Add a model class and a database context.
  • Scaffold a controller with CRUD methods.
  • Configure routing, URL paths, and return values.
  • Call the web API with Postman.

At the end, you have a web API that can manage “to-do” items stored in a database.

Register the database context

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

Startup.cs

with the following highlighted code:


// Unused usings removed using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.EntityFrameworkCore; using TodoApi.Models; namespace TodoApi { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddDbContext

(opt => opt.UseInMemoryDatabase("TodoList")); services.AddControllers(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } }

The preceding code:

  • Removes unused

    using

    declarations.
  • Adds the database context to the DI container.
  • Specifies that the database context will use an in-memory database.

Add authentication support to a web API

ASP.NET Core Identity adds user interface (UI) login functionality to ASP.NET Core web apps. To secure web APIs and SPAs, use one of the following:

  • Microsoft Entra ID
  • Azure Active Directory B2C (Azure AD B2C)
  • Duende Identity Server

Duende Identity Server is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core. Duende Identity Server enables the following security features:

  • Authentication as a Service (AaaS)
  • Single sign-on/off (SSO) over multiple application types
  • Access control for APIs
  • Federation Gateway

Important

Duende Software might require you to pay a license fee for production use of Duende Identity Server. For more information, see Migrate from ASP.NET Core 5.0 to 6.0.

For more information, see the Duende Identity Server documentation (Duende Software website).

Add a database context

The database context 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.

Add NuGet packages

  • From the Tools menu, select NuGet Package Manager > Manage NuGet Packages for Solution.
  • Select the Browse tab, and then enter Microsoft.EntityFrameworkCore.InMemory in the search box.
  • Select Microsoft.EntityFrameworkCore.InMemory in the left pane.
  • Select the Project checkbox in the right pane and then select Install.

Update the PostTodoItem create method

Update the return statement in the

PostTodoItem

to use the nameof operator:


[HttpPost] public async Task

> PostTodoItem(TodoItem todoItem) { _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); // return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem); return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem); }

The preceding code is an

HTTP POST

method, as indicated by the

[HttpPost]

attribute. The method gets the value of the

TodoItem

from the body of the HTTP request.

For more information, see Attribute routing with Http[Verb] attributes.

The CreatedAtAction method:

  • Returns an HTTP 201 status code if successful.

    HTTP 201

    is the standard response for an

    HTTP POST

    method that creates a new resource on the server.
  • Adds a Location header to the response. The

    Location

    header specifies the URI of the newly created to-do item. For more information, see 10.2.2 201 Created.
  • References the

    GetTodoItem

    action to create the

    Location

    header’s URI. The C#

    nameof

    keyword is used to avoid hard-coding the action name in the

    CreatedAtAction

    call.

Test PostTodoItem

  • Press Ctrl+F5 to run the app.

  • In the Swagger browser window, select POST /api/TodoItems, and then select Try it out.

  • In the Request body input window, update the JSON. For example,


    { "name": "walk dog", "isComplete": true }

  • Select Execute

Test the location header URI

In the preceding POST, the Swagger UI shows the location header under Response headers. For example,

location: https://localhost:7260/api/TodoItems/1

. The location header shows the URI to the created resource.

To test the location header:

  • In the Swagger browser window, select GET /api/TodoItems/{id}, and then select Try it out.

  • Enter

    in the

    id

    input box, and then select Execute.

Examine the PostTodoItem create method

Replace the return statement in the

PostTodoItem

to use the nameof operator:


// POST: api/TodoItems [HttpPost] public async Task

> PostTodoItem(TodoItem todoItem) { _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); //return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem); return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem); }

The preceding code is an HTTP POST method, as indicated by the

[HttpPost]

attribute. The method gets the value of the to-do item from the body of the HTTP request.

For more information, see Attribute routing with Http[Verb] attributes.

The CreatedAtAction method:

  • Returns an HTTP 201 status code if successful. HTTP 201 is the standard response for an HTTP POST method that creates a new resource on the server.
  • Adds a Location header to the response. The

    Location

    header specifies the URI of the newly created to-do item. For more information, see 201 Created.
  • References the

    GetTodoItem

    action to create the

    Location

    header’s URI. The C#

    nameof

    keyword is used to avoid hard-coding the action name in the

    CreatedAtAction

    call.

Install Postman

This tutorial uses Postman to test the web API.

  • Install Postman
  • Start the web app.
  • Start Postman.
  • Disable SSL certificate verification:

    • Postman for Windows: Postman for Windows File > Settings (General tab), disable SSL certificate verification.
    • Postman for macOS: Postman for Windows Postman > Settings (General tab), disable SSL certificate verification.

      Warning

      Re-enable SSL certificate verification after testing the controller.

Test PostTodoItem with Postman

  • Create a new request.

  • Set the HTTP method to


    POST

    .

  • Set the URI to


    https://localhost: /api/todoitems

    . For example,

    https://localhost:5001/api/todoitems

    .

  • Select the Body tab.

  • Select the raw radio button.

  • Set the type to JSON (application/json).

  • In the request body enter JSON for a to-do item:


    { "name":"walk dog", "isComplete":true }

  • Select Send.

Test the location header URI with Postman

  • Select the Headers tab in the Response pane.

  • Copy the Location header value:

  • Set the HTTP method to


    GET

    .

  • Set the URI to


    https://localhost: /api/todoitems/1

    . For example,

    https://localhost:5001/api/todoitems/1

    .

  • Select Send.

The PutTodoItem method

Examine the

PutTodoItem

method:


// PUT: api/TodoItems/5 [HttpPut("{id}")] public async Task

PutTodoItem(long id, TodoItem todoItem) { if (id != todoItem.Id) { return BadRequest(); } _context.Entry(todoItem).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!TodoItemExists(id)) { return NotFound(); } else { throw; } } return NoContent(); }


PutTodoItem

is similar to

PostTodoItem

, except it uses HTTP PUT. The response is 204 (No Content). According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. To support partial updates, use HTTP PATCH.

If you get an error calling

PutTodoItem

, call

GET

to ensure there’s an item in the database.

Test the PutTodoItem method

This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PUT call. Call GET to ensure there’s an item in the database before making a PUT call.

Update the to-do item that has Id = 1 and set its name to

"feed fish"

:


{ "Id":1, "name":"feed fish", "isComplete":true }

The following image shows the Postman update:

Additional resources

View or download sample code for this tutorial. See how to download.

For more information, see the following resources:

  • Create web APIs with ASP.NET Core
  • Tutorial: Create a minimal API with ASP.NET Core
  • ASP.NET Core web API documentation with Swagger / OpenAPI
  • Razor Pages with Entity Framework Core in ASP.NET Core – Tutorial 1 of 8
  • Routing to controller actions in ASP.NET Core
  • Controller action return types in ASP.NET Core web API
  • Deploy ASP.NET Core apps to Azure App Service
  • Host and deploy ASP.NET Core
  • Create a web API with ASP.NET Core

This tutorial teaches the basics of building a controller-based web API that uses a database. Another approach to creating APIs in ASP.NET Core is to create minimal APIs. For help in choosing between minimal APIs and controller-based APIs, see APIs overview. For a tutorial on creating a minimal API, see Tutorial: Create a minimal API with ASP.NET Core.

Overview

This tutorial creates the following API:

API Description Request body Response body
Get all to-do items None Array of to-do items
Get an item by ID None To-do item
Add a new item To-do item To-do item
Update an existing item To-do item None
Delete an item None None

The following diagram shows the design of the app.

Add authentication support to a web API

ASP.NET Core Identity adds user interface (UI) login functionality to ASP.NET Core web apps. To secure web APIs and SPAs, use one of the following:

  • Microsoft Entra ID
  • Azure Active Directory B2C (Azure AD B2C)
  • Duende Identity Server

Duende Identity Server is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core. Duende Identity Server enables the following security features:

  • Authentication as a Service (AaaS)
  • Single sign-on/off (SSO) over multiple application types
  • Access control for APIs
  • Federation Gateway

Important

Duende Software might require you to pay a license fee for production use of Duende Identity Server. For more information, see Migrate from ASP.NET Core 5.0 to 6.0.

For more information, see the Duende Identity Server documentation (Duende Software website).

Add a database context

The database context 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.

Add NuGet packages

  • From the Tools menu, select NuGet Package Manager > Manage NuGet Packages for Solution.
  • Select the Browse tab, and then enter

    Microsoft.EntityFrameworkCore.InMemory

    in the search box.
  • Select

    Microsoft.EntityFrameworkCore.InMemory

    in the left pane.
  • Select the Project checkbox in the right pane and then select Install.

Register the database context

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

Startup.cs

with the following highlighted code:


// Unused usings removed using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.EntityFrameworkCore; using TodoApi.Models; namespace TodoApi { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddDbContext

(opt => opt.UseInMemoryDatabase("TodoList")); services.AddControllers(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } }

The preceding code:

  • Removes unused

    using

    declarations.
  • Adds the database context to the DI container.
  • Specifies that the database context will use an in-memory database.

Update the PostTodoItem create method

Update the return statement in the

PostTodoItem

to use the nameof operator:


[HttpPost] public async Task

> PostTodoItem(TodoItem todoItem) { _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); // return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem); return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem); }

The preceding code is an

HTTP POST

method, as indicated by the

[HttpPost]

attribute. The method gets the value of the

TodoItem

from the body of the HTTP request.

For more information, see Attribute routing with Http[Verb] attributes.

The CreatedAtAction method:

  • Returns an HTTP 201 status code if successful.

    HTTP 201

    is the standard response for an

    HTTP POST

    method that creates a new resource on the server.
  • Adds a Location header to the response. The

    Location

    header specifies the URI of the newly created to-do item. For more information, see 10.2.2 201 Created.
  • References the

    GetTodoItem

    action to create the

    Location

    header’s URI. The C#

    nameof

    keyword is used to avoid hard-coding the action name in the

    CreatedAtAction

    call.

Test PostTodoItem

  • Press Ctrl+F5 to run the app.

  • In the Swagger browser window, select POST /api/TodoItems, and then select Try it out.

  • In the Request body input window, update the JSON. For example,


    { "name": "walk dog", "isComplete": true }

  • Select Execute

Test the location header URI

In the preceding POST, the Swagger UI shows the location header under Response headers. For example,

location: https://localhost:7260/api/TodoItems/1

. The location header shows the URI to the created resource.

To test the location header:

  • In the Swagger browser window, select GET /api/TodoItems/{id}, and then select Try it out.

  • Enter

    in the

    id

    input box, and then select Execute.

Scaffold a controller

  • Right-click the Controllers folder.

  • Select Add > New Scaffolded Item.

  • Select API Controller with actions, using Entity Framework, and then select Add.

  • In the Add API Controller with actions, using Entity Framework dialog:

    • Select TodoItem (TodoApi.Models) in the Model class.
    • Select TodoContext (TodoApi.Models) in the Data context class.
    • Select Add.

    If the scaffolding operation fails, select Add to try scaffolding a second time.

The generated code:

  • Marks the class with the

    [ApiController]

    attribute. This attribute indicates that the controller responds to web API requests. For information about specific behaviors that the attribute enables, see Create web APIs with ASP.NET Core.
  • Uses DI to inject the database context (

    TodoContext

    ) into the controller. The database context is used in each of the CRUD methods in the controller.

The ASP.NET Core templates for:

  • Controllers with views include

    [action]

    in the route template.
  • API controllers don’t include

    [action]

    in the route template.

When the

[action]

token isn’t in the route template, the action name (method name) isn’t included in the endpoint. That is, the action’s associated method name isn’t used in the matching route.

Add authentication support to a web API

ASP.NET Core Identity adds user interface (UI) login functionality to ASP.NET Core web apps. To secure web APIs and SPAs, use one of the following:

  • Microsoft Entra ID
  • Azure Active Directory B2C (Azure AD B2C)
  • Duende Identity Server

Duende Identity Server is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core. Duende Identity Server enables the following security features:

  • Authentication as a Service (AaaS)
  • Single sign-on/off (SSO) over multiple application types
  • Access control for APIs
  • Federation Gateway

Important

Duende Software might require you to pay a license fee for production use of Duende Identity Server. For more information, see Migrate from ASP.NET Core 5.0 to 6.0.

For more information, see the Duende Identity Server documentation (Duende Software website).

Routing and URL paths

The

[HttpGet]

attribute denotes a method that responds to an

HTTP GET

request. The URL path for each method is constructed as follows:

  • Start with the template string in the controller’s


    Route

    attribute:

    [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase

  • Replace


    [controller]

    with the name of the controller, which by convention is the controller class name minus the “Controller” suffix. For this sample, the controller class name is TodoItemsController, so the controller name is “TodoItems”. ASP.NET Core routing is case insensitive.

  • If the


    [HttpGet]

    attribute has a route template (for example,

    [HttpGet("products")]

    ), append that to the path. This sample doesn’t use a template. For more information, see Attribute routing with Http[Verb] attributes.

In the following

GetTodoItem

method,

"{id}"

is a placeholder variable for the unique identifier of the to-do item. When

GetTodoItem

is invoked, the value of

"{id}"

in the URL is provided to the method in its

id

parameter.


[HttpGet("{id}")] public async Task

> GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; }

Add authentication support to a web API

ASP.NET Core Identity adds user interface (UI) login functionality to ASP.NET Core web apps. To secure web APIs and SPAs, use one of the following:

  • Microsoft Entra ID
  • Azure Active Directory B2C (Azure AD B2C)
  • Duende Identity Server

Duende Identity Server is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core. Duende Identity Server enables the following security features:

  • Authentication as a Service (AaaS)
  • Single sign-on/off (SSO) over multiple application types
  • Access control for APIs
  • Federation Gateway

Important

Duende Software might require you to pay a license fee for production use of Duende Identity Server. For more information, see Migrate from ASP.NET Core 5.0 to 6.0.

For more information, see the Duende Identity Server documentation (Duende Software website).

Examine the GET methods

Two GET endpoints are implemented:


  • GET /api/todoitems

  • GET /api/todoitems/{id}

The previous section showed an example of the

/api/todoitems/{id}

route.

Follow the POST instructions to add another todo item, and then test the

/api/todoitems

route using Swagger.

This app uses an in-memory database. If the app is stopped and started, the preceding GET request will not return any data. If no data is returned, POST data to the app.

Add authentication support to a web API

ASP.NET Core Identity adds user interface (UI) login functionality to ASP.NET Core web apps. To secure web APIs and SPAs, use one of the following:

  • Microsoft Entra ID
  • Azure Active Directory B2C (Azure AD B2C)
  • Duende Identity Server

Duende Identity Server is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core. Duende Identity Server enables the following security features:

  • Authentication as a Service (AaaS)
  • Single sign-on/off (SSO) over multiple application types
  • Access control for APIs
  • Federation Gateway

Important

Duende Software might require you to pay a license fee for production use of Duende Identity Server. For more information, see Migrate from ASP.NET Core 5.0 to 6.0.

For more information, see the Duende Identity Server documentation (Duende Software website).

Add a model class

A model is a set of classes that represent the data that the app manages. The model for this app is the

TodoItem

class.

  • In Solution Explorer, right-click the project. Select Add > New Folder. Name the folder

    Models

    .
  • Right-click the

    Models

    folder and select Add > Class. Name the class TodoItem and select Add.
  • Replace the template code with the following:


namespace TodoApi.Models; public class TodoItem { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } }

The

Id

property functions as the unique key in a relational database.

Model classes can go anywhere in the project, but the

Models

folder is used by convention.

Scaffold a controller

  • Right-click the Controllers folder.

  • Select Add > New Scaffolded Item.

  • Select API Controller with actions, using Entity Framework, and then select Add.

  • In the Add API Controller with actions, using Entity Framework dialog:

    • Select TodoItem (TodoApi.Models) in the Model class.
    • Select TodoContext (TodoApi.Models) in the Data context class.
    • Select Add.

    If the scaffolding operation fails, select Add to try scaffolding a second time.

The generated code:

  • Marks the class with the

    [ApiController]

    attribute. This attribute indicates that the controller responds to web API requests. For information about specific behaviors that the attribute enables, see Create web APIs with ASP.NET Core.
  • Uses DI to inject the database context (

    TodoContext

    ) into the controller. The database context is used in each of the CRUD methods in the controller.

The ASP.NET Core templates for:

  • Controllers with views include

    [action]

    in the route template.
  • API controllers don’t include

    [action]

    in the route template.

When the

[action]

token isn’t in the route template, the action name is excluded from the route. That is, the action’s associated method name isn’t used in the matching route.

Overview

This tutorial creates the following API:

API Description Request body Response body
Get all to-do items None Array of to-do items
Get an item by ID None To-do item
Add a new item To-do item To-do item
Update an existing item To-do item None
Delete an item None None

The following diagram shows the design of the app.

Update the PostTodoItem create method

Update the return statement in the

PostTodoItem

to use the nameof operator:


// POST: api/TodoItems [HttpPost] public async Task

> PostTodoItem(TodoItem todoItem) { _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); //return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem); return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem); }

The preceding code is an HTTP POST method, as indicated by the

[HttpPost]

attribute. The method gets the value of the to-do item from the body of the HTTP request.

For more information, see Attribute routing with Http[Verb] attributes.

The CreatedAtAction method:

  • Returns an HTTP 201 status code if successful. HTTP 201 is the standard response for an HTTP POST method that creates a new resource on the server.
  • Adds a Location header to the response. The

    Location

    header specifies the URI of the newly created to-do item. For more information, see 201 Created.
  • References the

    GetTodoItem

    action to create the

    Location

    header’s URI. The C#

    nameof

    keyword is used to avoid hard-coding the action name in the

    CreatedAtAction

    call.

Install Postman

This tutorial uses Postman to test the web API.

  • Install Postman
  • Start the web app.
  • Start Postman.
  • Disable SSL certificate verification:

    • Postman for Windows: Select File > Settings (General tab), disable SSL certificate verification.
    • Postman for macOS: Select Postman > Settings (General tab), disable SSL certificate verification.

      Warning

      Re-enable SSL certificate verification after testing the controller.

Test PostTodoItem with Postman

  • Create a new request.

  • Set the HTTP method to


    POST

    .

  • Set the URI to


    https://localhost: /api/todoitems

    . For example,

    https://localhost:5001/api/todoitems

    .

  • Select the Body tab.

  • Select the raw radio button.

  • Set the type to JSON (application/json).

  • In the request body enter JSON for a to-do item:


    { "name":"walk dog", "isComplete":true }

  • Select Send.

Test the location header URI

The location header URI can be tested in the browser. Copy and paste the location header URI into the browser.

To test in Postman:

  • Select the Headers tab in the Response pane.

  • Copy the Location header value:

  • Set the HTTP method to


    GET

    .

  • Set the URI to


    https://localhost: /api/todoitems/1

    . For example,

    https://localhost:5001/api/todoitems/1

    .

  • Select Send.

Add a NuGet package

A NuGet package must be added to support the database used in this tutorial.

  • From the Tools menu, select NuGet Package Manager > Manage NuGet Packages for Solution.
  • Select the Browse tab.
  • Enter Microsoft.EntityFrameworkCore.InMemory in the search box, and then select

    Microsoft.EntityFrameworkCore.InMemory

    .
  • Select the Project checkbox in the right pane and then select Install.

Note

For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.

Test the project

The project template creates a

WeatherForecast

API with support for Swagger.

Press Ctrl+F5 to run without the debugger.

Visual Studio displays the following dialog when a project is not yet configured to use SSL:

Select Yes if you trust the IIS Express SSL certificate.

The following dialog is displayed:

Select Yes if you agree to trust the development certificate.

For information on trusting the Firefox browser, see Firefox SEC_ERROR_INADEQUATE_KEY_USAGE certificate error.

Visual Studio launches the default browser and navigates to

https://localhost: /swagger/index.html

, where is a randomly chosen port number set at the project creation.

The Swagger page

/swagger/index.html

is displayed. Select GET > Try it out > Execute. The page displays:

  • The Curl command to test the WeatherForecast API.
  • The URL to test the WeatherForecast API.
  • The response code, body, and headers.
  • A drop-down list box with media types and the example value and schema.

If the Swagger page doesn’t appear, see this GitHub issue.

Swagger is used to generate useful documentation and help pages for web APIs. This tutorial uses Swagger to test the app. For more information on Swagger, see ASP.NET Core web API documentation with Swagger / OpenAPI.

Copy and paste the Request URL in the browser:

https://localhost: /weatherforecast

JSON similar to the following example is returned:


[ { "date": "2019-07-16T19:04:05.7257911-06:00", "temperatureC": 52, "temperatureF": 125, "summary": "Mild" }, { "date": "2019-07-17T19:04:05.7258461-06:00", "temperatureC": 36, "temperatureF": 96, "summary": "Warm" }, { "date": "2019-07-18T19:04:05.7258467-06:00", "temperatureC": 39, "temperatureF": 102, "summary": "Cool" }, { "date": "2019-07-19T19:04:05.7258471-06:00", "temperatureC": 10, "temperatureF": 49, "summary": "Bracing" }, { "date": "2019-07-20T19:04:05.7258474-06:00", "temperatureC": -1, "temperatureF": 31, "summary": "Chilly" } ]

Update the PostTodoItem create method

Update the return statement in the

PostTodoItem

to use the nameof operator:


[HttpPost] public async Task

> PostTodoItem(TodoItem todoItem) { _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); //return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem); return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem); }

The preceding code is an HTTP POST method, as indicated by the

[HttpPost]

attribute. The method gets the value of the to-do item from the body of the HTTP request.

For more information, see Attribute routing with Http[Verb] attributes.

The CreatedAtAction method:

  • Returns an HTTP 201 status code if successful. HTTP 201 is the standard response for an HTTP POST method that creates a new resource on the server.
  • Adds a Location header to the response. The

    Location

    header specifies the URI of the newly created to-do item. For more information, see 10.2.2 201 Created.
  • References the

    GetTodoItem

    action to create the

    Location

    header’s URI. The C#

    nameof

    keyword is used to avoid hard-coding the action name in the

    CreatedAtAction

    call.

Install http-repl

This tutorial uses http-repl to test the web API.

  • Run the following command at a command prompt:


    dotnet tool install -g Microsoft.dotnet-httprepl

    Note

    By default the architecture of the .NET binaries to install represents the currently running OS architecture. To specify a different OS architecture, see dotnet tool install, –arch option. For more information, see GitHub issue dotnet/AspNetCore.Docs #29262.

  • If you don’t have the .NET 6.0 SDK or runtime installed, install the .NET 6.0 runtime.

Test PostTodoItem

  • Press Ctrl+F5 to run the app.

  • Open a new terminal window, and run the following commands. If your app uses a different port number, replace 5001 in the httprepl command with your port number.


    httprepl https://localhost:5001/api/todoitems post -h Content-Type=application/json -c "{"name":"walk dog","isComplete":true}"

    Here’s an example of the output from the command:


    HTTP/1.1 201 Created Content-Type: application/json; charset=utf-8 Date: Tue, 07 Sep 2021 20:39:47 GMT Location: https://localhost:5001/api/TodoItems/1 Server: Kestrel Transfer-Encoding: chunked { "id": 1, "name": "walk dog", "isComplete": true }

Test the location header URI

To test the location header, copy and paste it into an httprepl

get

command.

The following example assumes that you’re still in an httprepl session. If you ended the previous httprepl session, replace

connect

with

httprepl

in the following commands:


connect https://localhost:5001/api/todoitems/1 get

Here’s an example of the output from the command:


HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Tue, 07 Sep 2021 20:48:10 GMT Server: Kestrel Transfer-Encoding: chunked { "id": 1, "name": "walk dog", "isComplete": true }

Examine the GET methods

Two GET endpoints are implemented:


  • GET /api/todoitems

  • GET /api/todoitems/{id}

You just saw an example of the

/api/todoitems/{id}

route. Test the

/api/todoitems

route:


connect https://localhost:5001/api/todoitems get

Here’s an example of the output from the command:


HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Tue, 07 Sep 2021 20:59:21 GMT Server: Kestrel Transfer-Encoding: chunked [ { "id": 1, "name": "walk dog", "isComplete": true } ]

This time, the JSON returned is an array of one item.

This app uses an in-memory database. If the app is stopped and started, the preceding GET request will not return any data. If no data is returned, POST data to the app.

Add a model class

A model is a set of classes that represent the data that the app manages. The model for this app is a single

TodoItem

class.

  • In Solution Explorer, right-click the project. Select Add > New Folder. Name the folder


    Models

    .

  • Right-click the


    Models

    folder and select Add > Class. Name the class TodoItem and select Add.

  • Replace the template code with the following:


namespace TodoApi.Models { public class TodoItem { public long Id { get; set; } public string Name { get; set; } public bool IsComplete { get; set; } } }

The

Id

property functions as the unique key in a relational database.

Model classes can go anywhere in the project, but the

Models

folder is used by convention.

Add authentication support to a web API

ASP.NET Core Identity adds user interface (UI) login functionality to ASP.NET Core web apps. To secure web APIs and SPAs, use one of the following:

  • Microsoft Entra ID
  • Azure Active Directory B2C (Azure AD B2C)
  • Duende Identity Server

Duende Identity Server is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core. Duende Identity Server enables the following security features:

  • Authentication as a Service (AaaS)
  • Single sign-on/off (SSO) over multiple application types
  • Access control for APIs
  • Federation Gateway

Important

Duende Software might require you to pay a license fee for production use of Duende Identity Server. For more information, see Migrate from ASP.NET Core 5.0 to 6.0.

For more information, see the Duende Identity Server documentation (Duende Software website).

Add the TodoContext database context

  • Right-click the

    Models

    folder and select Add > Class. Name the class TodoContext and click Add.
  • Enter the following code:


    using Microsoft.EntityFrameworkCore; namespace TodoApi.Models { public class TodoContext : DbContext { public TodoContext(DbContextOptions

    options) : base(options) { } public DbSet

    TodoItems { get; set; } } }


Create a web project

  • From the File menu, select New > Project.
  • Enter Web API in the search box.
  • Select the ASP.NET Core Web API template and select Next.
  • In the Configure your new project dialog, name the project TodoApi and select Next.
  • In the Additional information dialog:

    • Confirm the Framework is .NET 6.0 (Long-term support).
    • Confirm the checkbox for Use controllers(uncheck to use minimal APIs) is checked.
    • Select Create.

Note

For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.

Test the project

The project template creates a

WeatherForecast

API with support for Swagger.

Press Ctrl+F5 to run without the debugger.

Visual Studio displays the following dialog when a project is not yet configured to use SSL:

Select Yes if you trust the IIS Express SSL certificate.

The following dialog is displayed:

Select Yes if you agree to trust the development certificate.

For information on trusting the Firefox browser, see Firefox SEC_ERROR_INADEQUATE_KEY_USAGE certificate error.

Visual Studio launches the default browser and navigates to

https://localhost: /swagger/index.html

, where is a randomly chosen port number.

The Swagger page

/swagger/index.html

is displayed. Select GET > Try it out > Execute. The page displays:

  • The Curl command to test the WeatherForecast API.
  • The URL to test the WeatherForecast API.
  • The response code, body, and headers.
  • A drop-down list box with media types and the example value and schema.

If the Swagger page doesn’t appear, see this GitHub issue.

Swagger is used to generate useful documentation and help pages for web APIs. This tutorial focuses on creating a web API. For more information on Swagger, see ASP.NET Core web API documentation with Swagger / OpenAPI.

Copy and paste the Request URL in the browser:

https://localhost: /weatherforecast

JSON similar to the following example is returned:


[ { "date": "2019-07-16T19:04:05.7257911-06:00", "temperatureC": 52, "temperatureF": 125, "summary": "Mild" }, { "date": "2019-07-17T19:04:05.7258461-06:00", "temperatureC": 36, "temperatureF": 96, "summary": "Warm" }, { "date": "2019-07-18T19:04:05.7258467-06:00", "temperatureC": 39, "temperatureF": 102, "summary": "Cool" }, { "date": "2019-07-19T19:04:05.7258471-06:00", "temperatureC": 10, "temperatureF": 49, "summary": "Bracing" }, { "date": "2019-07-20T19:04:05.7258474-06:00", "temperatureC": -1, "temperatureF": 31, "summary": "Chilly" } ]

Update the launchUrl

In Properties\launchSettings.json, update

launchUrl

from

"swagger"

to

"api/todoitems"

:


"launchUrl": "api/todoitems",

Because Swagger will be removed, the preceding markup changes the URL that is launched to the GET method of the controller added in the following sections.

Create a web project

  • From the File menu, select New > Project.
  • Select the ASP.NET Core Web API template and click Next.
  • Name the project TodoApi and click Create.
  • In the Create a new ASP.NET Core Web Application dialog, confirm that .NET Core and ASP.NET Core 5.0 are selected. Select the API template and click Create.

Note

For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.

Test the project

The project template creates a

WeatherForecast

API with support for Swagger.

Press Ctrl+F5 to run without the debugger.

Visual Studio displays the following dialog when a project is not yet configured to use SSL:

Select Yes if you trust the IIS Express SSL certificate.

The following dialog is displayed:

Select Yes if you agree to trust the development certificate.

For information on trusting the Firefox browser, see Firefox SEC_ERROR_INADEQUATE_KEY_USAGE certificate error.

Visual Studio launches:

  • The IIS Express web server.
  • The default browser and navigates to

    https://localhost: /swagger/index.html

    , whereis a randomly chosen port number.

The Swagger page

/swagger/index.html

is displayed. Select GET > Try it out > Execute. The page displays:

  • The Curl command to test the WeatherForecast API.
  • The URL to test the WeatherForecast API.
  • The response code, body, and headers.
  • A drop down list box with media types and the example value and schema.

If the Swagger page doesn’t appear, see this GitHub issue.

Swagger is used to generate useful documentation and help pages for web APIs. This tutorial focuses on creating a web API. For more information on Swagger, see ASP.NET Core web API documentation with Swagger / OpenAPI.

Copy and paste the Request URL in the browser:

https://localhost: /weatherforecast

JSON similar to the following is returned:


[ { "date": "2019-07-16T19:04:05.7257911-06:00", "temperatureC": 52, "temperatureF": 125, "summary": "Mild" }, { "date": "2019-07-17T19:04:05.7258461-06:00", "temperatureC": 36, "temperatureF": 96, "summary": "Warm" }, { "date": "2019-07-18T19:04:05.7258467-06:00", "temperatureC": 39, "temperatureF": 102, "summary": "Cool" }, { "date": "2019-07-19T19:04:05.7258471-06:00", "temperatureC": 10, "temperatureF": 49, "summary": "Bracing" }, { "date": "2019-07-20T19:04:05.7258474-06:00", "temperatureC": -1, "temperatureF": 31, "summary": "Chilly" } ]

Update the launchUrl

In Properties\launchSettings.json, update

launchUrl

from

"swagger"

to

"api/todoitems"

:


"launchUrl": "api/todoitems",

Because Swagger will be removed, the preceding markup changes the URL that is launched to the GET method of the controller added in the following sections.

Search by ID




There are several ways to get jQuery. In this example, I used the Microsoft Ajax CDN. You can also download it from http://jquery.com/, and the ASP.NET “Web API” project template includes jQuery as well.

Getting a List of Products

To get a list of products, send an HTTP GET request to “/api/products”.

The jQuery getJSON function sends an AJAX request. The response contains array of JSON objects. The

done

function specifies a callback that is called if the request succeeds. In the callback, we update the DOM with the product information.


$(document).ready(function () { // Send an AJAX request $.getJSON(apiUrl) .done(function (data) { // On success, 'data' contains a list of products. $.each(data, function (key, item) { // Add a list item for the product. $('

  • ', { text: formatItem(item) }).appendTo($('#products')); }); }); });
  • Getting a Product By ID

    To get a product by ID, send an HTTP GET request to “/api/products/id”, where id is the product ID.


    function find() { var id = $('#prodId').val(); $.getJSON(apiUrl + '/' + id) .done(function (data) { $('#product').text(formatItem(data)); }) .fail(function (jqXHR, textStatus, err) { $('#product').text('Error: ' + err); }); }

    We still call

    getJSON

    to send the AJAX request, but this time we put the ID in the request URI. The response from this request is a JSON representation of a single product.

    Return values

    The return type of the

    GetTodoItems

    and

    GetTodoItem

    methods is ActionResult

    type. ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. The response code for this return type is 200, assuming there are no unhandled exceptions. Unhandled exceptions are translated into 5xx errors.


    ActionResult

    return types can represent a wide range of HTTP status codes. For example,

    GetTodoItem

    can return two different status values:

    • If no item matches the requested ID, the method returns a 404 NotFound error code.
    • Otherwise, the method returns 200 with a JSON response body. Returning

      item

      results in an HTTP 200 response.

    Return values

    The return type of the

    GetTodoItems

    and

    GetTodoItem

    methods is ActionResult

    type. ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. The response code for this return type is 200 OK, assuming there are no unhandled exceptions. Unhandled exceptions are translated into 5xx errors.


    ActionResult

    return types can represent a wide range of HTTP status codes. For example,

    GetTodoItem

    can return two different status values:

    • If no item matches the requested ID, the method returns a 404 status NotFound error code.
    • Otherwise, the method returns 200 with a JSON response body. Returning

      item

      results in an HTTP 200 response.

    Add a database context

    The database context 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.

    Add NuGet packages

    • From the Tools menu, select NuGet Package Manager > Manage NuGet Packages for Solution.
    • Select the Browse tab, and then enter Microsoft.EntityFrameworkCore.InMemory in the search box.
    • Select Microsoft.EntityFrameworkCore.InMemory in the left pane.
    • Select the Project checkbox in the right pane and then select Install.

    Building a Web API

    Let’s start with creating a Web API project.

    Start Visual Studio and select New project from the Start page or from the File menu select “File” -> “New” -> “Project…”.

    In the template pane select Installed Templates and expand the Visual C# menu. Inside that Visual C# select Web. In the list of projects select ASP.Net MVC 4 Web Application.

    And name the project WebAPI_Basic.

    For reference see the following snapshot.

    After adding, a new dialog will pop-up.

    Inside the project template select Web API and in the view engine select Razor.

    A new project is created now.

    Scaffold a controller

    • Right-click the Controllers folder.

    • Select Add > New Scaffolded Item.

    • Select API Controller with actions, using Entity Framework, and then select Add.

    • In the Add API Controller with actions, using Entity Framework dialog:

      • Select TodoItem (TodoApi.Models) in the Model class.
      • Select TodoContext (TodoApi.Models) in the Data context class.
      • Select Add.

      If the scaffolding operation fails, select Add to try scaffolding a second time.

    The generated code:

    • Marks the class with the

      [ApiController]

      attribute. This attribute indicates that the controller responds to web API requests. For information about specific behaviors that the attribute enables, see Create web APIs with ASP.NET Core.
    • Uses DI to inject the database context (

      TodoContext

      ) into the controller. The database context is used in each of the CRUD methods in the controller.

    The ASP.NET Core templates for:

    • Controllers with views include

      [action]

      in the route template.
    • API controllers don’t include

      [action]

      in the route template.

    When the

    [action]

    token isn’t in the route template, the action name is excluded from the route. That is, the action’s associated method name isn’t used in the matching route.

    Additional resources

    View or download sample code for this tutorial. See how to download.

    For more information, see the following resources:

    • Create web APIs with ASP.NET Core
    • Tutorial: Create a minimal API with ASP.NET Core
    • ASP.NET Core web API documentation with Swagger / OpenAPI
    • Razor Pages with Entity Framework Core in ASP.NET Core – Tutorial 1 of 8
    • Routing to controller actions in ASP.NET Core
    • Controller action return types in ASP.NET Core web API
    • Deploy ASP.NET Core apps to Azure App Service
    • Host and deploy ASP.NET Core
    • Create a web API with ASP.NET Core

    Additional resources

    View or download sample code for this tutorial. See how to download.

    For more information, see the following resources:

    • Create web APIs with ASP.NET Core
    • Tutorial: Create a minimal API with ASP.NET Core
    • ASP.NET Core web API documentation with Swagger / OpenAPI
    • Razor Pages with Entity Framework Core in ASP.NET Core – Tutorial 1 of 8
    • Routing to controller actions in ASP.NET Core
    • Controller action return types in ASP.NET Core web API
    • Deploy ASP.NET Core apps to Azure App Service
    • Host and deploy ASP.NET Core
    • Create a web API with ASP.NET Core

    This tutorial teaches the basics of building a controller-based web API that uses a database. Another approach to creating APIs in ASP.NET Core is to create minimal APIs. For help in choosing between minimal APIs and controller-based APIs, see APIs overview. For a tutorial on creating a minimal API, see Tutorial: Create a minimal API with ASP.NET Core.

    In this tutorial, you learn how to:

    • Create a web API project.
    • Add a model class and a database context.
    • Scaffold a controller with CRUD methods.
    • Configure routing, URL paths, and return values.
    • Call the web API with Postman.

    At the end, you have a web API that can manage “to-do” items stored in a database.

    Routing and URL paths

    The

    [HttpGet]

    attribute denotes a method that responds to an HTTP GET request. The URL path for each method is constructed as follows:

    • Start with the template string in the controller’s


      Route

      attribute:

      [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase

    • Replace


      [controller]

      with the name of the controller, which by convention is the controller class name minus the “Controller” suffix. For this sample, the controller class name is TodoItemsController, so the controller name is “TodoItems”. ASP.NET Core routing is case insensitive.

    • If the


      [HttpGet]

      attribute has a route template (for example,

      [HttpGet("products")]

      ), append that to the path. This sample doesn’t use a template. For more information, see Attribute routing with Http[Verb] attributes.

    In the following

    GetTodoItem

    method,

    "{id}"

    is a placeholder variable for the unique identifier of the to-do item. When

    GetTodoItem

    is invoked, the value of

    "{id}"

    in the URL is provided to the method in its

    id

    parameter.


    [HttpGet("{id}")] public async Task

    > GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; }

    Adding a Model

    A model is an object that represents the data in your application. ASP.NET Web API can automatically serialize your model to JSON, XML, or some other format, and then write the serialized data into the body of the HTTP response message. As long as a client can read the serialization format, it can deserialize the object. Most clients can parse either XML or JSON. Moreover, the client can indicate which format it wants by setting the Accept header in the HTTP request message.

    Let’s start by creating a simple model that represents a product.

    If Solution Explorer is not already visible, click the View menu and select Solution Explorer. In Solution Explorer, right-click the Models folder. From the context menu, select Add then select Class.

    Name the class “Product”. Add the following properties to the

    Product

    class.


    namespace ProductsApp.Models { public class Product { public int Id { get; set; } public string Name { get; set; } public string Category { get; set; } public decimal Price { get; set; } } }

    Scaffold a controller

    • Right-click the Controllers folder.

    • Select Add > New Scaffolded Item.

    • Select API Controller with actions, using Entity Framework, and then select Add.

    • In the Add API Controller with actions, using Entity Framework dialog:

      • Select TodoItem (TodoApi.Models) in the Model class.
      • Select TodoContext (TodoApi.Models) in the Data context class.
      • Select Add.

      If the scaffolding operation fails, select Add to try scaffolding a second time.

    The generated code:

    • Marks the class with the

      [ApiController]

      attribute. This attribute indicates that the controller responds to web API requests. For information about specific behaviors that the attribute enables, see Create web APIs with ASP.NET Core.
    • Uses DI to inject the database context (

      TodoContext

      ) into the controller. The database context is used in each of the CRUD methods in the controller.

    The ASP.NET Core templates for:

    • Controllers with views include

      [action]

      in the route template.
    • API controllers don’t include

      [action]

      in the route template.

    When the

    [action]

    token isn’t in the route template, the action name (method name) isn’t included in the endpoint. That is, the action’s associated method name isn’t used in the matching route.

    Add a model class

    A model is a set of classes that represent the data that the app manages. The model for this app is a single

    TodoItem

    class.

    • In Solution Explorer, right-click the project. Select Add > New Folder. Name the folder


      Models

      .

    • Right-click the


      Models

      folder and select Add > Class. Name the class TodoItem and select Add.

    • Replace the template code with the following code:


    public class TodoItem { public long Id { get; set; } public string Name { get; set; } public bool IsComplete { get; set; } }

    The

    Id

    property functions as the unique key in a relational database.

    Model classes can go anywhere in the project, but the

    Models

    folder is used by convention.

    Create a web project

    • From the File menu, select New > Project.
    • Select the ASP.NET Core Web Application template and click Next.
    • Name the project TodoApi and click Create.
    • In the Create a new ASP.NET Core Web Application dialog, confirm that .NET Core and ASP.NET Core 3.1 are selected. Select the API template and click Create.

    Note

    For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.

    Test the API

    The project template creates a

    WeatherForecast

    API. Call the

    Get

    method from a browser to test the app.

    Press Ctrl+F5 to run the app. Visual Studio launches a browser and navigates to

    https://localhost: /weatherforecast

    , where is a randomly chosen port number.

    If you get a dialog box that asks if you should trust the IIS Express certificate, select Yes. In the Security Warning dialog that appears next, select Yes.

    JSON similar to the following is returned:


    [ { "date": "2019-07-16T19:04:05.7257911-06:00", "temperatureC": 52, "temperatureF": 125, "summary": "Mild" }, { "date": "2019-07-17T19:04:05.7258461-06:00", "temperatureC": 36, "temperatureF": 96, "summary": "Warm" }, { "date": "2019-07-18T19:04:05.7258467-06:00", "temperatureC": 39, "temperatureF": 102, "summary": "Cool" }, { "date": "2019-07-19T19:04:05.7258471-06:00", "temperatureC": 10, "temperatureF": 49, "summary": "Bracing" }, { "date": "2019-07-20T19:04:05.7258474-06:00", "temperatureC": -1, "temperatureF": 31, "summary": "Chilly" } ]

    The DeleteTodoItem method

    Examine the

    DeleteTodoItem

    method:


    [HttpDelete("{id}")] public async Task

    DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); }

    Test the DeleteTodoItem method

    Use the Swagger UI to delete the

    TodoItem

    that has Id = 1. Note the response is

    HTTP 204 No Content

    .

    Additional resources

    View or download sample code for this tutorial. See how to download.

    For more information, see the following resources:

    • Create web APIs with ASP.NET Core
    • Tutorial: Create a minimal API with ASP.NET Core
    • ASP.NET Core web API documentation with Swagger / OpenAPI
    • Razor Pages with Entity Framework Core in ASP.NET Core – Tutorial 1 of 8
    • Routing to controller actions in ASP.NET Core
    • Controller action return types in ASP.NET Core web API
    • Deploy ASP.NET Core apps to Azure App Service
    • Host and deploy ASP.NET Core
    • Create a web API with ASP.NET Core

    Add a database context

    The database context 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.

    Add NuGet packages

    • From the Tools menu, select NuGet Package Manager > Manage NuGet Packages for Solution.
    • Select the Browse tab, and then enter

      Microsoft.EntityFrameworkCore.InMemory

      in the search box.
    • Select

      Microsoft.EntityFrameworkCore.InMemory

      in the left pane.
    • Select the Project checkbox in the right pane and then select Install.

    Features of Web APIs

    • Helps in developing HTTP services (both RESTful and non-RESTful services) that process the request and return the data.
    • Web APIs return data in JSON, XML, or other formats.
    • System.Web.Http assembly has all the features defined by Web APIs.

    Advantages of using Web API

    • Lightweight architecture, along with having support for Routing.
    • Supports both model binding and data validation
    • We can perform HTTP terminologies like GET, POST, PUT, and DELETE for all CRUD operations
    • We can generate JSON and XML responses.

    Disadvantages of using Web API

    • It is a bit costlier & expensive for use.
    • Only JSON and XML are present in Web API unlike MVC where return views, action results, etc are present

    Components of Web API

    • Model: In WebAPI, models are objects that are used to retrieve and store the model state in the database.
    • Component Negotiation: Content negotiation is performed at the server-side to determine the media type formatted (i.e. whether it is a JSON or XML or another file) to be used based to return the response for an incoming request from the client-side

    The DeleteTodoItem method

    Examine the

    DeleteTodoItem

    method:


    [HttpDelete("{id}")] public async Task

    DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); }

    Test the DeleteTodoItem method

    Use the Swagger UI to delete the

    TodoItem

    that has Id = 1. Note the response is

    HTTP 204 No Content

    .

    Add the TodoContext database context

    • Right-click the

      Models

      folder and select Add > Class. Name the class TodoContext and click Add.
    • Enter the following code:


      using Microsoft.EntityFrameworkCore; using System.Diagnostics.CodeAnalysis; namespace TodoApi.Models { public class TodoContext : DbContext { public TodoContext(DbContextOptions

      options) : base(options) { } public DbSet

      TodoItems { get; set; } = null!; } }


    Create a web project

    • From the File menu, select New > Project.
    • Select the ASP.NET Core Web API template and click Next.
    • Name the project TodoApi and click Create.
    • In the Create a new ASP.NET Core Web Application dialog, confirm that .NET Core and ASP.NET Core 5.0 are selected. Select the API template and click Create.

    Note

    For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.

    Test the project

    The project template creates a

    WeatherForecast

    API with support for Swagger.

    Press Ctrl+F5 to run without the debugger.

    Visual Studio displays the following dialog when a project is not yet configured to use SSL:

    Select Yes if you trust the IIS Express SSL certificate.

    The following dialog is displayed:

    Select Yes if you agree to trust the development certificate.

    For information on trusting the Firefox browser, see Firefox SEC_ERROR_INADEQUATE_KEY_USAGE certificate error.

    Visual Studio launches:

    • The IIS Express web server.
    • The default browser and navigates to

      https://localhost: /swagger/index.html

      , whereis a randomly chosen port number.

    The Swagger page

    /swagger/index.html

    is displayed. Select GET > Try it out > Execute. The page displays:

    • The Curl command to test the WeatherForecast API.
    • The URL to test the WeatherForecast API.
    • The response code, body, and headers.
    • A drop down list box with media types and the example value and schema.

    If the Swagger page doesn’t appear, see this GitHub issue.

    Swagger is used to generate useful documentation and help pages for web APIs. This tutorial focuses on creating a web API. For more information on Swagger, see ASP.NET Core web API documentation with Swagger / OpenAPI.

    Copy and paste the Request URL in the browser:

    https://localhost: /weatherforecast

    JSON similar to the following is returned:


    [ { "date": "2019-07-16T19:04:05.7257911-06:00", "temperatureC": 52, "temperatureF": 125, "summary": "Mild" }, { "date": "2019-07-17T19:04:05.7258461-06:00", "temperatureC": 36, "temperatureF": 96, "summary": "Warm" }, { "date": "2019-07-18T19:04:05.7258467-06:00", "temperatureC": 39, "temperatureF": 102, "summary": "Cool" }, { "date": "2019-07-19T19:04:05.7258471-06:00", "temperatureC": 10, "temperatureF": 49, "summary": "Bracing" }, { "date": "2019-07-20T19:04:05.7258474-06:00", "temperatureC": -1, "temperatureF": 31, "summary": "Chilly" } ]

    Update the launchUrl

    In Properties\launchSettings.json, update

    launchUrl

    from

    "swagger"

    to

    "api/todoitems"

    :


    "launchUrl": "api/todoitems",

    Because Swagger will be removed, the preceding markup changes the URL that is launched to the GET method of the controller added in the following sections.

    Return values

    The return type of the

    GetTodoItems

    and

    GetTodoItem

    methods is ActionResult

    type. ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. The response code for this return type is 200 OK, assuming there are no unhandled exceptions. Unhandled exceptions are translated into 5xx errors.


    ActionResult

    return types can represent a wide range of HTTP status codes. For example,

    GetTodoItem

    can return two different status values:

    • If no item matches the requested ID, the method returns a 404 status NotFound error code.
    • Otherwise, the method returns 200 with a JSON response body. Returning

      item

      results in an HTTP 200 response.

    Scaffold a controller

    • Right-click the Controllers folder.

    • Select Add > New Scaffolded Item.

    • Select API Controller with actions, using Entity Framework, and then select Add.

    • In the Add API Controller with actions, using Entity Framework dialog:

      • Select TodoItem (TodoApi.Models) in the Model class.
      • Select TodoContext (TodoApi.Models) in the Data context class.
      • Select Add.

      If the scaffolding operation fails, select Add to try scaffolding a second time.

    The generated code:

    • Marks the class with the

      [ApiController]

      attribute. This attribute indicates that the controller responds to web API requests. For information about specific behaviors that the attribute enables, see Create web APIs with ASP.NET Core.
    • Uses DI to inject the database context (

      TodoContext

      ) into the controller. The database context is used in each of the CRUD methods in the controller.

    The ASP.NET Core templates for:

    • Controllers with views include

      [action]

      in the route template.
    • API controllers don’t include

      [action]

      in the route template.

    When the

    [action]

    token isn’t in the route template, the action name (method name) isn’t included in the endpoint. That is, the action’s associated method name isn’t used in the matching route.

    Prevent over-posting

    Currently the sample app exposes the entire

    TodoItem

    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. DTO is used in this article.

    A DTO may be used to:

    • Prevent over-posting.
    • Hide properties that clients are not supposed to view.
    • Omit some properties in order to reduce payload size.
    • Flatten object graphs that contain nested objects. Flattened object graphs can be more convenient for clients.

    To demonstrate the DTO approach, update the

    TodoItem

    class to include a secret field:


    namespace TodoApi.Models { public class TodoItem { public long Id { get; set; } public string Name { get; set; } public bool IsComplete { get; set; } public string Secret { get; set; } } }

    The secret field needs to be hidden from this app, but an administrative app could choose to expose it.

    Verify you can post and get the secret field.

    Create a DTO model:


    public class TodoItemDTO { public long Id { get; set; } public string Name { get; set; } public bool IsComplete { get; set; } }

    Update the

    TodoItemsController

    to use

    TodoItemDTO

    :


    // GET: api/TodoItems [HttpGet] public async Task

    >> GetTodoItems() { return await _context.TodoItems .Select(x => ItemToDTO(x)) .ToListAsync(); } [HttpGet("{id}")] public async Task

    > GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return ItemToDTO(todoItem); } [HttpPut("{id}")] public async Task

    UpdateTodoItem(long id, TodoItemDTO todoItemDTO) { if (id != todoItemDTO.Id) { return BadRequest(); } var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } todoItem.Name = todoItemDTO.Name; todoItem.IsComplete = todoItemDTO.IsComplete; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) when (!TodoItemExists(id)) { return NotFound(); } return NoContent(); } [HttpPost] public async Task

    > CreateTodoItem(TodoItemDTO todoItemDTO) { var todoItem = new TodoItem { IsComplete = todoItemDTO.IsComplete, Name = todoItemDTO.Name }; _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); return CreatedAtAction( nameof(GetTodoItem), new { id = todoItem.Id }, ItemToDTO(todoItem)); } [HttpDelete("{id}")] public async Task

    DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); } private bool TodoItemExists(long id) => _context.TodoItems.Any(e => e.Id == id); private static TodoItemDTO ItemToDTO(TodoItem todoItem) => new TodoItemDTO { Id = todoItem.Id, Name = todoItem.Name, IsComplete = todoItem.IsComplete };





    Verify you can’t post or get the secret field.

    Feedback

    Submit and view feedback for

    Tutorial: Create a web API with ASP.NET Core

    Note

    This isn’t the latest version of this article. For the current release, see the ASP.NET Core 8.0 version of this article.

    By Rick Anderson and Kirk Larkin

    This tutorial teaches the basics of building a controller-based web API that uses a database. Another approach to creating APIs in ASP.NET Core is to create minimal APIs. For help in choosing between minimal APIs and controller-based APIs, see APIs overview. For a tutorial on creating a minimal API, see Tutorial: Create a minimal API with ASP.NET Core.

    Add a database context

    The database context 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.

    • Right-click the

      Models

      folder and select Add > Class. Name the class TodoContext and click Add.
    • Enter the following code:


      using Microsoft.EntityFrameworkCore; namespace TodoApi.Models; public class TodoContext : DbContext { public TodoContext(DbContextOptions

      options) : base(options) { } public DbSet

      TodoItems { get; set; } = null!; }


    Return values

    The return type of the

    GetTodoItems

    and

    GetTodoItem

    methods is ActionResult

    type. ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. The response code for this return type is 200 OK, assuming there are no unhandled exceptions. Unhandled exceptions are translated into 5xx errors.


    ActionResult

    return types can represent a wide range of HTTP status codes. For example,

    GetTodoItem

    can return two different status values:

    • If no item matches the requested ID, the method returns a 404 status NotFound error code.
    • Otherwise, the method returns 200 with a JSON response body. Returning

      item

      results in an

      HTTP 200

      response.

    Add a model class

    A model is a set of classes that represent the data that the app manages. The model for this app is a single

    TodoItem

    class.

    • In Solution Explorer, right-click the project. Select Add > New Folder. Name the folder


      Models

      .

    • Right-click the


      Models

      folder and select Add > Class. Name the class TodoItem and select Add.

    • Replace the template code with the following:


    namespace TodoApi.Models { public class TodoItem { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } } }

    The

    Id

    property functions as the unique key in a relational database.

    Model classes can go anywhere in the project, but the

    Models

    folder is used by convention.

    Routing and URL paths

    The

    [HttpGet]

    attribute denotes a method that responds to an HTTP GET request. The URL path for each method is constructed as follows:

    • Start with the template string in the controller’s


      Route

      attribute:

      [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase { private readonly TodoContext _context; public TodoItemsController(TodoContext context) { _context = context; }

    • Replace


      [controller]

      with the name of the controller, which by convention is the controller class name minus the “Controller” suffix. For this sample, the controller class name is TodoItemsController, so the controller name is “TodoItems”. ASP.NET Core routing is case insensitive.

    • If the


      [HttpGet]

      attribute has a route template (for example,

      [HttpGet("products")]

      ), append that to the path. This sample doesn’t use a template. For more information, see Attribute routing with Http[Verb] attributes.

    In the following

    GetTodoItem

    method,

    "{id}"

    is a placeholder variable for the unique identifier of the to-do item. When

    GetTodoItem

    is invoked, the value of

    "{id}"

    in the URL is provided to the method in its

    id

    parameter.


    // GET: api/TodoItems/5 [HttpGet("{id}")] public async Task

    > GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; }

    Create a Web API Project

    In this tutorial, you will use ASP.NET Web API to create a web API that returns a list of products. The front-end web page uses jQuery to display the results.

    Start Visual Studio and select New Project from the Start page. Or, from the File menu, select New and then Project.

    In the Templates pane, select Installed Templates and expand the Visual C# node. Under Visual C#, select Web. In the list of project templates, select ASP.NET Web Application. Name the project “ProductsApp” and click OK.

    In the New ASP.NET Project dialog, select the Empty template. Under “Add folders and core references for”, check Web API. Click OK.

    Note

    You can also create a Web API project using the “Web API” template. The Web API template uses ASP.NET MVC to provide API help pages. I’m using the Empty template for this tutorial because I want to show Web API without MVC. In general, you don’t need to know ASP.NET MVC to use Web API.

    The DeleteTodoItem method

    Examine the

    DeleteTodoItem

    method:


    // DELETE: api/TodoItems/5 [HttpDelete("{id}")] public async Task

    > DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return todoItem; }

    Test the DeleteTodoItem method

    Use Postman to delete a to-do item:

    • Set the method to

      DELETE

      .
    • Set the URI of the object to delete (for example

      https://localhost:5001/api/todoitems/1

      ).
    • Select Send.

    Add the TodoContext database context

    • Right-click the

      Models

      folder and select Add > Class. Name the class TodoContext and click Add.
    • Enter the following code:


      using Microsoft.EntityFrameworkCore; using System.Diagnostics.CodeAnalysis; namespace TodoApi.Models { public class TodoContext : DbContext { public TodoContext(DbContextOptions

      options) : base(options) { } public DbSet

      TodoItems { get; set; } = null!; } }


    Examine the GET methods

    Two GET endpoints are implemented:


    • GET /api/todoitems

    • GET /api/todoitems/{id}

    Test the app by calling the two endpoints from a browser or Postman. For example:


    • https://localhost:5001/api/todoitems

    • https://localhost:5001/api/todoitems/1

    A response similar to the following is produced by the call to

    GetTodoItems

    :


    [ { "id": 1, "name": "Item1", "isComplete": false } ]

    Test Get with Postman

    • Create a new request.
    • Set the HTTP method to GET.
    • Set the request URI to

      https://localhost: /api/todoitems

      . For example,

      https://localhost:5001/api/todoitems

      .
    • Set Two pane view in Postman.
    • Select Send.

    This app uses an in-memory database. If the app is stopped and started, the preceding GET request will not return any data. If no data is returned, POST data to the app.

    Scaffold a controller

    • Right-click the Controllers folder.

    • Select Add > New Scaffolded Item.

    • Select API Controller with actions, using Entity Framework, and then select Add.

    • In the Add API Controller with actions, using Entity Framework dialog:

      • Select TodoItem (TodoApi.Models) in the Model class.
      • Select TodoContext (TodoApi.Models) in the Data context class.
      • Select Add.

    The generated code:

    • Marks the class with the

      [ApiController]

      attribute. This attribute indicates that the controller responds to web API requests. For information about specific behaviors that the attribute enables, see Create web APIs with ASP.NET Core.
    • Uses DI to inject the database context (

      TodoContext

      ) into the controller. The database context is used in each of the CRUD methods in the controller.

    The ASP.NET Core templates for:

    • Controllers with views include

      [action]

      in the route template.
    • API controllers don’t include

      [action]

      in the route template.

    When the

    [action]

    token isn’t in the route template, the action name is excluded from the route. That is, the action’s associated method name isn’t used in the matching route.

    Return values

    The return type of the

    GetTodoItems

    and

    GetTodoItem

    methods is ActionResult

    type. ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. The response code for this return type is 200 OK, assuming there are no unhandled exceptions. Unhandled exceptions are translated into 5xx errors.


    ActionResult

    return types can represent a wide range of HTTP status codes. For example,

    GetTodoItem

    can return two different status values:

    • If no item matches the requested ID, the method returns a 404 status NotFound error code.
    • Otherwise, the method returns 200 with a JSON response body. Returning

      item

      results in an HTTP 200 response.

    Add the TodoContext database context

    • Right-click the

      Models

      folder and select Add > Class. Name the class TodoContext and click Add.
    • Enter the following code:


      using Microsoft.EntityFrameworkCore; namespace TodoApi.Models { public class TodoContext : DbContext { public TodoContext(DbContextOptions

      options) : base(options) { } public DbSet

      TodoItems { get; set; } } }


    Routing and URL paths

    The

    [HttpGet]

    attribute denotes a method that responds to an

    HTTP GET

    request. The URL path for each method is constructed as follows:

    • Start with the template string in the controller’s


      Route

      attribute:

      [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase

    • Replace


      [controller]

      with the name of the controller, which by convention is the controller class name minus the “Controller” suffix. For this sample, the controller class name is TodoItemsController, so the controller name is “TodoItems”. ASP.NET Core routing is case insensitive.

    • If the


      [HttpGet]

      attribute has a route template (for example,

      [HttpGet("products")]

      ), append that to the path. This sample doesn’t use a template. For more information, see Attribute routing with Http[Verb] attributes.

    In the following

    GetTodoItem

    method,

    "{id}"

    is a placeholder variable for the unique identifier of the to-do item. When

    GetTodoItem

    is invoked, the value of

    "{id}"

    in the URL is provided to the method in its

    id

    parameter.


    [HttpGet("{id}")] public async Task

    > GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; }

    Additional resources

    View or download sample code for this tutorial. See how to download.

    For more information, see the following resources:

    • Create web APIs with ASP.NET Core
    • Tutorial: Create a minimal API with ASP.NET Core
    • ASP.NET Core web API documentation with Swagger / OpenAPI
    • Razor Pages with Entity Framework Core in ASP.NET Core – Tutorial 1 of 8
    • Routing to controller actions in ASP.NET Core
    • Controller action return types in ASP.NET Core web API
    • Deploy ASP.NET Core apps to Azure App Service
    • Host and deploy ASP.NET Core
    • Create a web API with ASP.NET Core

    This tutorial teaches the basics of building a controller-based web API that uses a database. Another approach to creating APIs in ASP.NET Core is to create minimal APIs. For help in choosing between minimal APIs and controller-based APIs, see APIs overview. For a tutorial on creating a minimal API, see Tutorial: Create a minimal API with ASP.NET Core.

    In this tutorial, you learn how to:

    • Create a web API project.
    • Add a model class and a database context.
    • Scaffold a controller with CRUD methods.
    • Configure routing, URL paths, and return values.
    • Call the web API with http-repl.

    At the end, you have a web API that can manage “to-do” items stored in a database.

    The PutTodoItem method

    Examine the

    PutTodoItem

    method:


    // PUT: api/TodoItems/5 [HttpPut("{id}")] public async Task

    PutTodoItem(long id, TodoItem todoItem) { if (id != todoItem.Id) { return BadRequest(); } _context.Entry(todoItem).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!TodoItemExists(id)) { return NotFound(); } else { throw; } } return NoContent(); }


    PutTodoItem

    is similar to

    PostTodoItem

    , except it uses HTTP PUT. The response is 204 (No Content). According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. To support partial updates, use HTTP PATCH.

    If you get an error calling

    PutTodoItem

    , call

    GET

    to ensure there’s an item in the database.

    Test the PutTodoItem method

    This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PUT call. Call GET to ensure there’s an item in the database before making a PUT call.

    Update the to-do item that has Id = 1 and set its name to

    "feed fish"

    :


    { "Id":1, "name":"feed fish", "isComplete":true }

    The following image shows the Postman update:

    Add the TodoContext database context

    • Right-click the

      Models

      folder and select Add > Class. Name the class TodoContext and click Add.
    • Enter the following code:


      using Microsoft.EntityFrameworkCore; namespace TodoApi.Models; public class TodoContext : DbContext { public TodoContext(DbContextOptions

      options) : base(options) { } public DbSet

      TodoItems { get; set; } = null!; }


    Overview

    This tutorial creates the following API:

    API Description Request body Response body
    Get all to-do items None Array of to-do items
    Get an item by ID None To-do item
    Add a new item To-do item To-do item
    Update an existing item To-do item None
    Delete an item None None

    The following diagram shows the design of the app.

    Return values

    The return type of the

    GetTodoItems

    and

    GetTodoItem

    methods is ActionResult

    type. ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. The response code for this return type is 200 OK, assuming there are no unhandled exceptions. Unhandled exceptions are translated into 5xx errors.


    ActionResult

    return types can represent a wide range of HTTP status codes. For example,

    GetTodoItem

    can return two different status values:

    • If no item matches the requested ID, the method returns a 404 status NotFound error code.
    • Otherwise, the method returns 200 with a JSON response body. Returning

      item

      results in an

      HTTP 200

      response.

    Add a model class

    A model is a set of classes that represent the data that the app manages. The model for this app is the

    TodoItem

    class.

    • In Solution Explorer, right-click the project. Select Add > New Folder. Name the folder

      Models

      .
    • Right-click the

      Models

      folder and select Add > Class. Name the class TodoItem and select Add.
    • Replace the template code with the following:


    namespace TodoApi.Models; public class TodoItem { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } }

    The

    Id

    property functions as the unique key in a relational database.

    Model classes can go anywhere in the project, but the

    Models

    folder is used by convention.

    Routing Tables

    In ASP.NET Web API, a controller is a class that handles HTTP requests. The public methods of the controller are called action methods or simply actions. When the Web API framework receives a request, it routes the request to an action.

    To determine which action to invoke, the framework uses a routing table. The Visual Studio project template for Web API creates a default route:


    routes.MapHttpRoute( name: "API Default", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } );

    This route is defined in the WebApiConfig.cs file, which is placed in the App_Start directory:

    For more information about the

    WebApiConfig

    class, see Configuring ASP.NET Web API.

    If you self-host Web API, you must set the routing table directly on the

    HttpSelfHostConfiguration

    object. For more information, see Self-Host a Web API.

    Each entry in the routing table contains a route template. The default route template for Web API is “api/{controller}/{id}”. In this template, “api” is a literal path segment, and {controller} and {id} are placeholder variables.

    When the Web API framework receives an HTTP request, it tries to match the URI against one of the route templates in the routing table. If no route matches, the client receives a 404 error. For example, the following URIs match the default route:

    • /api/contacts
    • /api/contacts/1
    • /api/products/gizmo1

    However, the following URI does not match, because it lacks the “api” segment:

    • /contacts/1

    Note

    The reason for using “api” in the route is to avoid collisions with ASP.NET MVC routing. That way, you can have “/contacts” go to an MVC controller, and “/api/contacts” go to a Web API controller. Of course, if you don’t like this convention, you can change the default route table.

    Once a matching route is found, Web API selects the controller and the action:

    • To find the controller, Web API adds “Controller” to the value of the {controller} variable.
    • To find the action, Web API looks at the HTTP verb, and then looks for an action whose name begins with that HTTP verb name. For example, with a GET request, Web API looks for an action prefixed with “Get”, such as “GetContact” or “GetAllContacts”. This convention applies only to GET, POST, PUT, DELETE, HEAD, OPTIONS, and PATCH verbs. You can enable other HTTP verbs by using attributes on your controller. We’ll see an example of that later.
    • Other placeholder variables in the route template, such as {id}, are mapped to action parameters.

    Let’s look at an example. Suppose that you define the following controller:


    public class ProductsController : ApiController { public IEnumerable GetAllProducts() { } public Product GetProductById(int id) { } public HttpResponseMessage DeleteProduct(int id){ } }

    Here are some possible HTTP requests, along with the action that gets invoked for each:

    HTTP Verb URI Path Action Parameter
    GET api/products GetAllProducts (none)
    GET api/products/4 GetProductById
    DELETE api/products/4 DeleteProduct
    POST api/products (no match)

    Notice that the {id} segment of the URI, if present, is mapped to the id parameter of the action. In this example, the controller defines two GET methods, one with an id parameter and one with no parameters.

    Also, note that the POST request will fail, because the controller does not define a “Post…” method.

    Prevent over-posting

    Currently the sample app exposes the entire

    TodoItem

    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. DTO is used in this tutorial.

    A DTO may be used to:

    • Prevent over-posting.
    • Hide properties that clients are not supposed to view.
    • Omit some properties in order to reduce payload size.
    • Flatten object graphs that contain nested objects. Flattened object graphs can be more convenient for clients.

    To demonstrate the DTO approach, update the

    TodoItem

    class to include a secret field:


    namespace TodoApi.Models { public class TodoItem { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } public string? Secret { get; set; } } }

    The secret field needs to be hidden from this app, but an administrative app could choose to expose it.

    Verify you can post and get the secret field.

    Create a DTO model:


    namespace TodoApi.Models; public class TodoItemDTO { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } }

    Update the

    TodoItemsController

    to use

    TodoItemDTO

    :


    using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using TodoApi.Models; namespace TodoApi.Controllers; [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase { private readonly TodoContext _context; public TodoItemsController(TodoContext context) { _context = context; } // GET: api/TodoItems [HttpGet] public async Task

    >> GetTodoItems() { return await _context.TodoItems .Select(x => ItemToDTO(x)) .ToListAsync(); } // GET: api/TodoItems/5 //

    [HttpGet("{id}")] public async Task

    > GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return ItemToDTO(todoItem); } //


    // PUT: api/TodoItems/5 // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 //

    [HttpPut("{id}")] public async Task

    PutTodoItem(long id, TodoItemDTO todoDTO) { if (id != todoDTO.Id) { return BadRequest(); } var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } todoItem.Name = todoDTO.Name; todoItem.IsComplete = todoDTO.IsComplete; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) when (!TodoItemExists(id)) { return NotFound(); } return NoContent(); } //


    // POST: api/TodoItems // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 //

    [HttpPost] public async Task

    > PostTodoItem(TodoItemDTO todoDTO) { var todoItem = new TodoItem { IsComplete = todoDTO.IsComplete, Name = todoDTO.Name }; _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); return CreatedAtAction( nameof(GetTodoItem), new { id = todoItem.Id }, ItemToDTO(todoItem)); } //


    // DELETE: api/TodoItems/5 [HttpDelete("{id}")] public async Task

    DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); } private bool TodoItemExists(long id) { return _context.TodoItems.Any(e => e.Id == id); } private static TodoItemDTO ItemToDTO(TodoItem todoItem) => new TodoItemDTO { Id = todoItem.Id, Name = todoItem.Name, IsComplete = todoItem.IsComplete }; }


    Verify you can’t post or get the secret field.

    Register the database context

    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

    Program.cs

    with the following highlighted code:


    using Microsoft.EntityFrameworkCore; using TodoApi.Models; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddDbContext

    (opt => opt.UseInMemoryDatabase("TodoList")); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();

    The preceding code:

    • Adds

      using

      directives.
    • Adds the database context to the DI container.
    • Specifies that the database context will use an in-memory database.

    Additional resources

    View or download sample code for this tutorial. See how to download.

    For more information, see the following resources:

    • Create web APIs with ASP.NET Core
    • Tutorial: Create a minimal API with ASP.NET Core
    • ASP.NET Core web API documentation with Swagger / OpenAPI
    • Razor Pages with Entity Framework Core in ASP.NET Core – Tutorial 1 of 8
    • Routing to controller actions in ASP.NET Core
    • Controller action return types in ASP.NET Core web API
    • Deploy ASP.NET Core apps to Azure App Service
    • Host and deploy ASP.NET Core
    • Create a web API with ASP.NET Core

    This tutorial teaches the basics of building a controller-based web API that uses a database. Another approach to creating APIs in ASP.NET Core is to create minimal APIs. For help in choosing between minimal APIs and controller-based APIs, see APIs overview. For a tutorial on creating a minimal API, see Tutorial: Create a minimal API with ASP.NET Core.

    In this tutorial, you learn how to:

    • Create a web API project.
    • Add a model class and a database context.
    • Scaffold a controller with CRUD methods.
    • Configure routing, URL paths, and return values.
    • Call the web API with http-repl.

    At the end, you have a web API that can manage “to-do” items stored in a database.

    Routing and URL paths

    The

    [HttpGet]

    attribute denotes a method that responds to an

    HTTP GET

    request. The URL path for each method is constructed as follows:

    • Start with the template string in the controller’s


      Route

      attribute:

      [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase

    • Replace


      [controller]

      with the name of the controller, which by convention is the controller class name minus the “Controller” suffix. For this sample, the controller class name is TodoItemsController, so the controller name is “TodoItems”. ASP.NET Core routing is case insensitive.

    • If the


      [HttpGet]

      attribute has a route template (for example,

      [HttpGet("products")]

      ), append that to the path. This sample doesn’t use a template. For more information, see Attribute routing with Http[Verb] attributes.

    In the following

    GetTodoItem

    method,

    "{id}"

    is a placeholder variable for the unique identifier of the to-do item. When

    GetTodoItem

    is invoked, the value of

    "{id}"

    in the URL is provided to the method in its

    id

    parameter.


    [HttpGet("{id}")] public async Task

    > GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; }

    Test with http-repl, Postman, or curl

    http-repl, Postman, and curl are often used to test API’s. Swagger uses

    curl

    and shows the

    curl

    command it submitted.

    For instructions on these tools, see the following links:

    For more information on

    http-repl

    , see Test web APIs with the HttpRepl.

    Features of MVC

    • MVC is helpful in developing web applications that process request and sends both views and data. It helps to understand the business logic & Ul logic separately from each other.
    • MVC represents resultant data in JSON format using JsonResult.
    • System.web.MVC has all features defined by MVC.
    • It is a powerful URL-mapping component that can be utilized to build applications that have comprehensible and searchable URLs.

    Advantages of using MVC

    • Helps in organizing Large scale web applications.
    • The development process is made much faster.
    • Ease of planning and better maintenance
    • MVC returns data without formatting.
    • It has extensive support for test-driven development.

    Disadvantages of using MVC

    • MVC is not suitable for small applications.
    • If the model keeps on going with frequent changes then the views could be overburdened sometimes with update requests.
    • Implementing MVC sometimes requires deep technical knowledge.

    MVC is used for Web application development. MVC returns both data and view of the data whereas, Web API returns only the HTTP services data i.e. only in form of data.

    NOTE : Web APIs are the services for any type of devices and any clients but MVC provides service only to it’s clients.

    The Web API is an API that can be accessed over the web using the HTTP protocol, i.e., it is basically a framework that facilitates us to create and develop HTTP-based RESTFUL services. Technologies such as java, ASP.NET, etc. can be utilized to develop the web API, which can be used in either a web server or a web browser. Web APIs does not include web browser since web development concepts strictly adhere to the Client-side (including Frameworks). Being open-source, Web APIs generally offer lower bandwidth which facilitates passing not only JSON /XML but also HTML. They offer centralization of Business Logic which helps in maintaining consistency across all the layers.

    Overview

    This tutorial creates the following API:

    API Description Request body Response body
    Get all to-do items None Array of to-do items
    Get an item by ID None To-do item
    Add a new item To-do item To-do item
    Update an existing item To-do item None
    Delete an item None None

    The following diagram shows the design of the app.

    Difference between MVC & Web APIs

    MVC is used for developing Web applications that reply to both data and views

    Web API is used for generating HTTP services that reply only as data.

    When receiving the request, MVC performs tracing based on the action name.

    When receiving the request, Web API performs tracing based on HTTP requests.

    By using JSONResult, MVC returns the data in the JSON format

    Depending on the accepted header of the request, The Web API returns data in JSON, XML, and different formats

    “System.Web.MVC” assembly has all defined features of MVC.

    “System.Web.Http” assembly has all features of MVC but does not have routing, and model binding which are exclusive to Web API.

    MVC does not either support content negotiation or self-hosting.

    Web API supports content negotiation, self-hosting

    MVC controller is extremely heavy and we can see the number of interfaces the code uses.

    Web API has a lighter controller and it can distinguish requests by their passed parameters

    MVC controller cant support API views as it is tightly coupled with the views.

    Web API can be hosted anywhere without worrying about the views.

    Popular MVC Frameworks are Ruby on Rails, Django, CherryPy, Spring MVC, Catalyst, etc. Popular API Examples are Google Maps API, YouTube API, Twitter API, etc.

    Whether you’re preparing for your first job interview or aiming to upskill in this ever-evolving tech landscape, GeeksforGeeks Courses are your key to success. We provide top-quality content at affordable prices, all geared towards accelerating your growth in a time-bound manner. Join the millions we’ve already empowered, and we’re here to do the same for you. Don’t miss out – check it out now!

    Looking for a place to share your ideas, learn, and connect? Our Community portal is just the spot! Come join us and see what all the buzz is about!

    Last Updated :
    08 Nov, 2023

    Like Article

    Save Article

    Share your thoughts in the comments

    Please Login to comment…

    Create a web project

    • From the File menu, select New > Project.
    • Enter Web API in the search box.
    • Select the ASP.NET Core Web API template and select Next.
    • In the Configure your new project dialog, name the project TodoApi and select Next.
    • In the Additional information dialog:

      • Confirm the Framework is .NET 7.0 (or later).
      • Confirm the checkbox for Use controllers(uncheck to use minimal APIs) is checked.
      • Select Create.

    Note

    For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.

    Test the project

    The project template creates a

    WeatherForecast

    API with support for Swagger.

    Press Ctrl+F5 to run without the debugger.

    Visual Studio displays the following dialog when a project is not yet configured to use SSL:

    Select Yes if you trust the IIS Express SSL certificate.

    The following dialog is displayed:

    Select Yes if you agree to trust the development certificate.

    For information on trusting the Firefox browser, see Firefox SEC_ERROR_INADEQUATE_KEY_USAGE certificate error.

    Visual Studio launches the default browser and navigates to

    https://localhost: /swagger/index.html

    , where is a randomly chosen port number.

    The Swagger page

    /swagger/index.html

    is displayed. Select GET > Try it out > Execute. The page displays:

    • The Curl command to test the WeatherForecast API.
    • The URL to test the WeatherForecast API.
    • The response code, body, and headers.
    • A drop-down list box with media types and the example value and schema.

    If the Swagger page doesn’t appear, see this GitHub issue.

    Swagger is used to generate useful documentation and help pages for web APIs. This tutorial focuses on creating a web API. For more information on Swagger, see ASP.NET Core web API documentation with Swagger / OpenAPI.

    Copy and paste the Request URL in the browser:

    https://localhost: /weatherforecast

    JSON similar to the following example is returned:


    [ { "date": "2019-07-16T19:04:05.7257911-06:00", "temperatureC": 52, "temperatureF": 125, "summary": "Mild" }, { "date": "2019-07-17T19:04:05.7258461-06:00", "temperatureC": 36, "temperatureF": 96, "summary": "Warm" }, { "date": "2019-07-18T19:04:05.7258467-06:00", "temperatureC": 39, "temperatureF": 102, "summary": "Cool" }, { "date": "2019-07-19T19:04:05.7258471-06:00", "temperatureC": 10, "temperatureF": 49, "summary": "Bracing" }, { "date": "2019-07-20T19:04:05.7258474-06:00", "temperatureC": -1, "temperatureF": 31, "summary": "Chilly" } ]

    Prevent over-posting

    Currently the sample app exposes the entire

    TodoItem

    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. DTO is used in this tutorial.

    A DTO may be used to:

    • Prevent over-posting.
    • Hide properties that clients are not supposed to view.
    • Omit some properties in order to reduce payload size.
    • Flatten object graphs that contain nested objects. Flattened object graphs can be more convenient for clients.

    To demonstrate the DTO approach, update the

    TodoItem

    class to include a secret field:


    namespace TodoApi.Models { public class TodoItem { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } public string? Secret { get; set; } } }

    The secret field needs to be hidden from this app, but an administrative app could choose to expose it.

    Verify you can post and get the secret field.

    Create a DTO model:


    namespace TodoApi.Models { public class TodoItemDTO { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } } }

    Update the

    TodoItemsController

    to use

    TodoItemDTO

    :


    using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using TodoApi.Models; namespace TodoApi.Controllers { [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase { private readonly TodoContext _context; public TodoItemsController(TodoContext context) { _context = context; } // GET: api/TodoItems [HttpGet] public async Task

    >> GetTodoItems() { return await _context.TodoItems .Select(x => ItemToDTO(x)) .ToListAsync(); } // GET: api/TodoItems/5 [HttpGet("{id}")] public async Task

    > GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return ItemToDTO(todoItem); } // PUT: api/TodoItems/5 // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 [HttpPut("{id}")] public async Task

    UpdateTodoItem(long id, TodoItemDTO todoItemDTO) { if (id != todoItemDTO.Id) { return BadRequest(); } var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } todoItem.Name = todoItemDTO.Name; todoItem.IsComplete = todoItemDTO.IsComplete; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) when (!TodoItemExists(id)) { return NotFound(); } return NoContent(); } // POST: api/TodoItems // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 [HttpPost] public async Task

    > CreateTodoItem(TodoItemDTO todoItemDTO) { var todoItem = new TodoItem { IsComplete = todoItemDTO.IsComplete, Name = todoItemDTO.Name }; _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); return CreatedAtAction( nameof(GetTodoItem), new { id = todoItem.Id }, ItemToDTO(todoItem)); } // DELETE: api/TodoItems/5 [HttpDelete("{id}")] public async Task

    DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); } private bool TodoItemExists(long id) { return _context.TodoItems.Any(e => e.Id == id); } private static TodoItemDTO ItemToDTO(TodoItem todoItem) => new TodoItemDTO { Id = todoItem.Id, Name = todoItem.Name, IsComplete = todoItem.IsComplete }; } }





    Verify you can’t post or get the secret field.

    Routing and URL paths

    The

    [HttpGet]

    attribute denotes a method that responds to an HTTP GET request. The URL path for each method is constructed as follows:

    • Start with the template string in the controller’s


      Route

      attribute:

      [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase

    • Replace


      [controller]

      with the name of the controller, which by convention is the controller class name minus the “Controller” suffix. For this sample, the controller class name is TodoItemsController, so the controller name is “TodoItems”. ASP.NET Core routing is case insensitive.

    • If the


      [HttpGet]

      attribute has a route template (for example,

      [HttpGet("products")]

      ), append that to the path. This sample doesn’t use a template. For more information, see Attribute routing with Http[Verb] attributes.

    In the following

    GetTodoItem

    method,

    "{id}"

    is a placeholder variable for the unique identifier of the to-do item. When

    GetTodoItem

    is invoked, the value of

    "{id}"

    in the URL is provided to the method in its

    id

    parameter.


    [HttpGet("{id}")] public async Task

    > GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; }

    Overview

    This tutorial creates the following API:

    API Description Request body Response body
    Get all to-do items None Array of to-do items
    Get an item by ID None To-do item
    Add a new item To-do item To-do item
    Update an existing item To-do item None
    Delete an item None None

    The following diagram shows the design of the app.

    Scaffold a controller

    • Right-click the Controllers folder.

    • Select Add > New Scaffolded Item.

    • Select API Controller with actions, using Entity Framework, and then select Add.

    • In the Add API Controller with actions, using Entity Framework dialog:

      • Select TodoItem (TodoApi.Models) in the Model class.
      • Select TodoContext (TodoApi.Models) in the Data context class.
      • Select Add.

    The generated code:

    • Marks the class with the

      [ApiController]

      attribute. This attribute indicates that the controller responds to web API requests. For information about specific behaviors that the attribute enables, see Create web APIs with ASP.NET Core.
    • Uses DI to inject the database context (

      TodoContext

      ) into the controller. The database context is used in each of the CRUD methods in the controller.

    The ASP.NET Core templates for:

    • Controllers with views include

      [action]

      in the route template.
    • API controllers don’t include

      [action]

      in the route template.

    When the

    [action]

    token isn’t in the route template, the action name is excluded from the route. That is, the action’s associated method name isn’t used in the matching route.

    Let’s begin with adding Web API Controller

    Now let’s begin with adding a Web API Controller. It is nearly similar to adding a Controller in ASP.NET MVC.

    Right-click on the Controller folder and add a new Web API Controller with the name CarDetailsController and in the template select API Controller with an empty read / write action.

    After adding the Controller you will see the code as in the following snapshot.

    You can keep this Web API controller anywhere in the application.

    If you want to follow the convention then create the new folder in the root your of application with the name API.

    Inside that you can add a Web API controller.

    You have successfully added a Web API controller to your application.

    Now you can run the application and test it.

    For testing I am passing http://localhost:32359/api/cardetails/1 for calling the method get.

    Wow, it’s working!

    It’s easy to configure it as a Web API.

    The ASP.Net MVC and ASP.Net Web API makes heavy use of convention for configuration to lighten the work load for creating the services.

    For example, add a decorating method with attributes to make it easy to do CRUD operations.

    Else it will make it difficult to understand and code.

    1. [HttpPut]
    2. public void Put(int id, [FromBody]string value)
    3. [HttpPost]
    4. public void Post([FromBody]string value)
    5. [HttpDelete]
    6. public void Delete(int id)
    7. {}

    The HTTP actions and their corresponding CRUD operations are:

    • GET (Read)Retrieves the representation of the resource.
    • PUT(Update)Update an existing resource.
    • POST (Create)Create new resource.
    • DELETE (Delete)Delete an existing resource.

    Now let’s begin with how to create a CRUD operation with the WEB API.

    Let’s start by adding a Model.

    To add the model right-click on the model folder and add a class with the name CarsStock.

    After adding the Model CarsStock.cs now let’s start with adding properties to the class.

    After adding the model properties now I will consume the HTTP service developed using the ASP.NET Web API in a simple cshtml page with jQuery and Ajax.

    For that in the View folder I will add a folder named Car and inside that folder will add a CarStock named view. To add it just right-click on the View folder and select View.

    The following snapshot shows how I had added the view.

    After adding the view you will get a blank view because we are not using any tightly coupled model here.

    Then add a Controller with the name CarController. Call this view Carstock for the demo of consuming the Web API.

    In this I called the view CarStock.

    After adding the Controller and View now let us move back towards the Web API and make some changes that we have already created with the name “CarDetailsController”.

    Let’s get to the first method in CarDetailsController.

    1. GET IEnumerable

      1. [HttpGet]
      2. public IEnumerable

        GetAllcarDetails()
      3. CarsStock ST = new CarsStock();
      4. CarsStock ST1 = new CarsStock();
      5. List

        li = new List

        ();

      6. ST.CarName = “Maruti Waganor”;
      7. ST.CarPrice = “4 Lakh”;
      8. ST.CarModel = “VXI”;
      9. ST.CarColor = “Brown”;
      10. ST1.CarName = “Maruti Swift”;
      11. ST1.CarPrice = “5 Lakh”;
      12. ST1.CarModel = “VXI”;
      13. ST1.CarColor = “RED”;
      14. li.Add(ST);
      15. li.Add(ST1);
      16. return li;

      This method is used to get a list of data.
      In this method, I have used the Model CarsStock and created a list of CarsStock “List

      “.
      And returning it.

    2. GET by id

      1. public IEnumerable

        Get(int id)
      2. CarsStock ST = new CarsStock();
      3. CarsStock ST1 = new CarsStock();
      4. List

        li = new List

        ();

      5. if (id == 1)
      6. ST.CarName = “Maruti Waganor”;
      7. ST.CarPrice = “4 Lakh”;
      8. ST.CarModel = “VXI”;
      9. ST.CarColor = “Brown”;
      10. li.Add(ST);
      11. else
      12. ST1.CarName = “Maruti Swift”;
      13. ST1.CarPrice = “5 Lakh”;
      14. ST1.CarModel = “VXI”;
      15. ST1.CarColor = “RED”;
      16. li.Add(ST1);
      17. return li;

      In this GET method, you can retrieve records for the database by passing an id.

    3. POST

      1. [HttpPost]
      2. public void PostCar([FromBody] CarsStock cs)

      In this POST method, you can post data (CREATE) to the database. In this, I am using the Carstock model to post the data.

    4. PUT

      1. [HttpPut]
      2. public void Putcar(int id, [FromBody]CarsStock cs)

      In this PUT method you can UPDATE the data (UPDATE) to the database. I am using the Carstock model to update the data.

    5. DELETE

      1. [HttpDelete]
      2. public void Deletecar(int id)

    In this DELETE method you can delete data (DELETE) from the database. I am using an id to delete the data.

    Here is a snapshot of all the methods and models after adding the attributes to it.

    Now let’s move to the view and do CRUD operations from there.

    For getting a list of data I have created a function in jQuery.

    1. Calling GET IEnumerable List from Ajax and getting data from the Web API.

    Tutorial: Create a web API with ASP.NET Core

    Note

    This isn’t the latest version of this article. For the current release, see the ASP.NET Core 8.0 version of this article.

    By Rick Anderson and Kirk Larkin

    This tutorial teaches the basics of building a controller-based web API that uses a database. Another approach to creating APIs in ASP.NET Core is to create minimal APIs. For help in choosing between minimal APIs and controller-based APIs, see APIs overview. For a tutorial on creating a minimal API, see Tutorial: Create a minimal API with ASP.NET Core.

    Register the database context

    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

    Program.cs

    with the following highlighted code:


    using Microsoft.EntityFrameworkCore; using TodoApi.Models; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddDbContext

    (opt => opt.UseInMemoryDatabase("TodoList")); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();

    The preceding code:

    • Adds

      using

      directives.
    • Adds the database context to the DI container.
    • Specifies that the database context will use an in-memory database.

    Overview

    This tutorial creates the following API:

    API Description Request body Response body
    Get all to-do items None Array of to-do items
    Get an item by ID None To-do item
    Add a new item To-do item To-do item
    Update an existing item To-do item None
    Delete an item None None

    The following diagram shows the design of the app.

    Add a model class

    A model is a set of classes that represent the data that the app manages. The model for this app is a single

    TodoItem

    class.

    • In Solution Explorer, right-click the project. Select Add > New Folder. Name the folder


      Models

      .

    • Right-click the


      Models

      folder and select Add > Class. Name the class TodoItem and select Add.

    • Replace the template code with the following code:


    public class TodoItem { public long Id { get; set; } public string Name { get; set; } public bool IsComplete { get; set; } }

    The

    Id

    property functions as the unique key in a relational database.

    Model classes can go anywhere in the project, but the

    Models

    folder is used by convention.

    Next Steps

    • For a more complete example of an HTTP service that supports POST, PUT, and DELETE actions and writes to a database, see Using Web API 2 with Entity Framework 6.
    • For more about creating fluid and responsive web applications on top of an HTTP service, see ASP.NET Single Page Application.
    • For information about how to deploy a Visual Studio web project to Azure App Service, see Create an ASP.NET web app in Azure App Service.

    Examine the GET methods

    These methods implement two GET endpoints:


    • GET /api/todoitems

    • GET /api/todoitems/{id}

    Test the app by calling the two endpoints from a browser or Postman. For example:


    • https://localhost:5001/api/todoitems

    • https://localhost:5001/api/todoitems/1

    A response similar to the following is produced by the call to

    GetTodoItems

    :


    [ { "id": 1, "name": "Item1", "isComplete": false } ]

    Test Get with Postman

    • Create a new request.
    • Set the HTTP method to GET.
    • Set the request URI to

      https://localhost: /api/todoitems

      . For example,

      https://localhost:5001/api/todoitems

      .
    • Set Two pane view in Postman.
    • Select Send.

    This app uses an in-memory database. If the app is stopped and started, the preceding GET request will not return any data. If no data is returned, POST data to the app.

    The PutTodoItem method

    Examine the

    PutTodoItem

    method:


    [HttpPut("{id}")] public async Task

    PutTodoItem(long id, TodoItem todoItem) { if (id != todoItem.Id) { return BadRequest(); } _context.Entry(todoItem).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!TodoItemExists(id)) { return NotFound(); } else { throw; } } return NoContent(); }


    PutTodoItem

    is similar to

    PostTodoItem

    , except it uses HTTP PUT. The response is 204 (No Content). According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. To support partial updates, use HTTP PATCH.

    If you get an error calling

    PutTodoItem

    in the following section, call

    GET

    to ensure there’s an item in the database.

    Test the PutTodoItem method

    This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PUT call. Call GET to ensure there’s an item in the database before making a PUT call.

    Update the to-do item that has Id = 1 and set its name to

    "feed fish"

    :


    connect https://localhost:5001/api/todoitems/1 put -h Content-Type=application/json -c "{"id":1,"name":"feed fish","isComplete":true}"

    Here’s an example of the output from the command:


    HTTP/1.1 204 No Content Date: Tue, 07 Sep 2021 21:20:47 GMT Server: Kestrel

    Add the TodoContext database context

    • Right-click the

      Models

      folder and select Add > Class. Name the class TodoContext and click Add.
    • Enter the following code:


      using Microsoft.EntityFrameworkCore; namespace TodoApi.Models { public class TodoContext : DbContext { public TodoContext(DbContextOptions

      options) : base(options) { } public DbSet

      TodoItems { get; set; } } }


    The DeleteTodoItem method

    Examine the

    DeleteTodoItem

    method:


    // DELETE: api/TodoItems/5 [HttpDelete("{id}")] public async Task

    DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); }

    Test the DeleteTodoItem method

    Use Postman to delete a to-do item:

    • Set the method to

      DELETE

      .
    • Set the URI of the object to delete (for example

      https://localhost:5001/api/todoitems/1

      ).
    • Select Send.

    Scaffold a controller

    • Right-click the Controllers folder.

    • Select Add > New Scaffolded Item.

    • Select API Controller with actions, using Entity Framework, and then select Add.

    • In the Add API Controller with actions, using Entity Framework dialog:

      • Select TodoItem (TodoApi.Models) in the Model class.
      • Select TodoContext (TodoApi.Models) in the Data context class.
      • Select Add.

      If the scaffolding operation fails, select Add to try scaffolding a second time.

    The generated code:

    • Marks the class with the

      [ApiController]

      attribute. This attribute indicates that the controller responds to web API requests. For information about specific behaviors that the attribute enables, see Create web APIs with ASP.NET Core.
    • Uses DI to inject the database context (

      TodoContext

      ) into the controller. The database context is used in each of the CRUD methods in the controller.

    The ASP.NET Core templates for:

    • Controllers with views include

      [action]

      in the route template.
    • API controllers don’t include

      [action]

      in the route template.

    When the

    [action]

    token isn’t in the route template, the action name (method name) isn’t included in the endpoint. That is, the action’s associated method name isn’t used in the matching route.

    Overview

    This tutorial creates the following API:

    API Description Request body Response body
    Get all to-do items None Array of to-do items
    Get an item by ID None To-do item
    Add a new item To-do item To-do item
    Update an existing item To-do item None
    Delete an item None None

    The following diagram shows the design of the app.

    Create a web project

    • From the File menu, select New > Project.
    • Enter Web API in the search box.
    • Select the ASP.NET Core Web API template and select Next.
    • In the Configure your new project dialog, name the project TodoApi and select Next.
    • In the Additional information dialog:

      • Confirm the Framework is .NET 8.0 (Long Term Support).
      • Confirm the checkbox for Use controllers(uncheck to use minimal APIs) is checked.
      • Confirm the checkbox for Enable OpenAPI support is checked.
      • Select Create.

    Routing Variations

    The previous section described the basic routing mechanism for ASP.NET Web API. This section describes some variations.

    HTTP verbs

    Instead of using the naming convention for HTTP verbs, you can explicitly specify the HTTP verb for an action by decorating the action method with one of the following attributes:


    • [HttpGet]

    • [HttpPut]

    • [HttpPost]

    • [HttpDelete]

    • [HttpHead]

    • [HttpOptions]

    • [HttpPatch]

    In the following example, the

    FindProduct

    method is mapped to GET requests:


    public class ProductsController : ApiController { [HttpGet] public Product FindProduct(id) {} }

    To allow multiple HTTP verbs for an action, or to allow HTTP verbs other than GET, PUT, POST, DELETE, HEAD, OPTIONS, and PATCH, use the

    [AcceptVerbs]

    attribute, which takes a list of HTTP verbs.


    public class ProductsController : ApiController { [AcceptVerbs("GET", "HEAD")] public Product FindProduct(id) { } // WebDAV method [AcceptVerbs("MKCOL")] public void MakeCollection() { } }

    Routing by Action Name

    With the default routing template, Web API uses the HTTP verb to select the action. However, you can also create a route where the action name is included in the URI:


    routes.MapHttpRoute( name: "ActionApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } );

    In this route template, the {action} parameter names the action method on the controller. With this style of routing, use attributes to specify the allowed HTTP verbs. For example, suppose your controller has the following method:


    public class ProductsController : ApiController { [HttpGet] public string Details(int id); }

    In this case, a GET request for “api/products/details/1” would map to the

    Details

    method. This style of routing is similar to ASP.NET MVC, and may be appropriate for an RPC-style API.

    You can override the action name by using the

    [ActionName]

    attribute. In the following example, there are two actions that map to “api/products/thumbnail/id. One supports GET and the other supports POST:


    public class ProductsController : ApiController { [HttpGet] [ActionName("Thumbnail")] public HttpResponseMessage GetThumbnailImage(int id); [HttpPost] [ActionName("Thumbnail")] public void AddThumbnailImage(int id); }

    Non-Actions

    To prevent a method from getting invoked as an action, use the

    [NonAction]

    attribute. This signals to the framework that the method is not an action, even if it would otherwise match the routing rules.


    // Not an action method. [NonAction] public string GetPrivateData() { ... }

    Prevent over-posting

    Currently the sample app exposes the entire

    TodoItem

    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. DTO is used in this tutorial.

    A DTO may be used to:

    • Prevent over-posting.
    • Hide properties that clients are not supposed to view.
    • Omit some properties in order to reduce payload size.
    • Flatten object graphs that contain nested objects. Flattened object graphs can be more convenient for clients.

    To demonstrate the DTO approach, update the

    TodoItem

    class to include a secret field:


    namespace TodoApi.Models { public class TodoItem { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } public string? Secret { get; set; } } }

    The secret field needs to be hidden from this app, but an administrative app could choose to expose it.

    Verify you can post and get the secret field.

    Create a DTO model:


    namespace TodoApi.Models { public class TodoItemDTO { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } } }

    Update the

    TodoItemsController

    to use

    TodoItemDTO

    :


    using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using TodoApi.Models; namespace TodoApi.Controllers { [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase { private readonly TodoContext _context; public TodoItemsController(TodoContext context) { _context = context; } // GET: api/TodoItems [HttpGet] public async Task

    >> GetTodoItems() { return await _context.TodoItems .Select(x => ItemToDTO(x)) .ToListAsync(); } // GET: api/TodoItems/5 [HttpGet("{id}")] public async Task

    > GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return ItemToDTO(todoItem); } // PUT: api/TodoItems/5 // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 [HttpPut("{id}")] public async Task

    UpdateTodoItem(long id, TodoItemDTO todoItemDTO) { if (id != todoItemDTO.Id) { return BadRequest(); } var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } todoItem.Name = todoItemDTO.Name; todoItem.IsComplete = todoItemDTO.IsComplete; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) when (!TodoItemExists(id)) { return NotFound(); } return NoContent(); } // POST: api/TodoItems // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 [HttpPost] public async Task

    > CreateTodoItem(TodoItemDTO todoItemDTO) { var todoItem = new TodoItem { IsComplete = todoItemDTO.IsComplete, Name = todoItemDTO.Name }; _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); return CreatedAtAction( nameof(GetTodoItem), new { id = todoItem.Id }, ItemToDTO(todoItem)); } // DELETE: api/TodoItems/5 [HttpDelete("{id}")] public async Task

    DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); } private bool TodoItemExists(long id) { return _context.TodoItems.Any(e => e.Id == id); } private static TodoItemDTO ItemToDTO(TodoItem todoItem) => new TodoItemDTO { Id = todoItem.Id, Name = todoItem.Name, IsComplete = todoItem.IsComplete }; } }





    Verify you can’t post or get the secret field.

    Add the TodoContext database context

    • Right-click the

      Models

      folder and select Add > Class. Name the class TodoContext and click Add.
    • Enter the following code:


      using Microsoft.EntityFrameworkCore; namespace TodoApi.Models { public class TodoContext : DbContext { public TodoContext(DbContextOptions

      options) : base(options) { } public DbSet

      TodoItems { get; set; } } }


    Test with other tools

    There are many other tools that can be used to test web APIs, for example:

    • Visual Studio Endpoints Explorer and .http files
    • http-repl
    • Postman
    • curl. Swagger uses

      curl

      and shows the

      curl

      commands it submits.
    • Fiddler

    For more information, see:

    • Minimal API tutorial: test with .http files and Endpoints Explorer
    • Test APIs with Postman
    • Install and test APIs with

      http-repl

    Examine the PostTodoItem create method

    Replace the return statement in the

    PostTodoItem

    to use the nameof operator:


    // POST: api/TodoItems [HttpPost] public async Task

    > PostTodoItem(TodoItem todoItem) { _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); //return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem); return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem); }

    The preceding code is an HTTP POST method, as indicated by the

    [HttpPost]

    attribute. The method gets the value of the to-do item from the body of the HTTP request.

    For more information, see Attribute routing with Http[Verb] attributes.

    The CreatedAtAction method:

    • Returns an HTTP 201 status code if successful. HTTP 201 is the standard response for an HTTP POST method that creates a new resource on the server.
    • Adds a Location header to the response. The

      Location

      header specifies the URI of the newly created to-do item. For more information, see 201 Created.
    • References the

      GetTodoItem

      action to create the

      Location

      header’s URI. The C#

      nameof

      keyword is used to avoid hard-coding the action name in the

      CreatedAtAction

      call.

    Install Postman

    This tutorial uses Postman to test the web API.

    • Install Postman
    • Start the web app.
    • Start Postman.
    • Disable SSL certificate verification:

      • Postman for Windows: Postman for Windows File > Settings (General tab), disable SSL certificate verification.
      • Postman for macOS: Postman for Windows Postman > Settings (General tab), disable SSL certificate verification.

        Warning

        Re-enable SSL certificate verification after testing the controller.

    Test PostTodoItem with Postman

    • Create a new request.

    • Set the HTTP method to


      POST

      .

    • Set the URI to


      https://localhost: /api/todoitems

      . For example,

      https://localhost:5001/api/todoitems

      .

    • Select the Body tab.

    • Select the raw radio button.

    • Set the type to JSON (application/json).

    • In the request body enter JSON for a to-do item:


      { "name":"walk dog", "isComplete":true }

    • Select Send.

    Test the location header URI with Postman

    • Select the Headers tab in the Response pane.

    • Copy the Location header value:

    • Set the HTTP method to


      GET

      .

    • Set the URI to


      https://localhost: /api/todoitems/1

      . For example,

      https://localhost:5001/api/todoitems/1

      .

    • Select Send.

    Add the TodoContext database context

    • Right-click the

      Models

      folder and select Add > Class. Name the class TodoContext and click Add.
    • Enter the following code:


      using Microsoft.EntityFrameworkCore; namespace TodoApi.Models; public class TodoContext : DbContext { public TodoContext(DbContextOptions

      options) : base(options) { } public DbSet

      TodoItems { get; set; } = null!; }


    The DeleteTodoItem method

    Examine the

    DeleteTodoItem

    method:


    [HttpDelete("{id}")] public async Task

    DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); }

    Test the DeleteTodoItem method

    Delete the to-do item that has Id = 1:


    connect https://localhost:5001/api/todoitems/1 delete

    Here’s an example of the output from the command:


    HTTP/1.1 204 No Content Date: Tue, 07 Sep 2021 21:43:00 GMT Server: Kestrel

    Examine the GET methods

    Two GET endpoints are implemented:


    • GET /api/todoitems

    • GET /api/todoitems/{id}

    You just saw an example of the

    /api/todoitems/{id}

    route. Test the

    /api/todoitems

    route:


    connect https://localhost:5001/api/todoitems get

    Here’s an example of the output from the command:


    HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Tue, 07 Sep 2021 20:59:21 GMT Server: Kestrel Transfer-Encoding: chunked [ { "id": 1, "name": "walk dog", "isComplete": true } ]

    This time, the JSON returned is an array of one item.

    This app uses an in-memory database. If the app is stopped and started, the preceding GET request will not return any data. If no data is returned, POST data to the app.

    Add a NuGet package

    A NuGet package must be added to support the database used in this tutorial.

    • From the Tools menu, select NuGet Package Manager > Manage NuGet Packages for Solution.
    • Select the Browse tab.
    • Enter Microsoft.EntityFrameworkCore.InMemory in the search box, and then select

      Microsoft.EntityFrameworkCore.InMemory

      .
    • Select the Project checkbox in the right pane and then select Install.

    Note

    For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.

    Test the project

    The project template creates a

    WeatherForecast

    API with support for Swagger.

    Press Ctrl+F5 to run without the debugger.

    Visual Studio displays the following dialog when a project is not yet configured to use SSL:

    Select Yes if you trust the IIS Express SSL certificate.

    The following dialog is displayed:

    Select Yes if you agree to trust the development certificate.

    For information on trusting the Firefox browser, see Firefox SEC_ERROR_INADEQUATE_KEY_USAGE certificate error.

    Visual Studio launches the default browser and navigates to

    https://localhost: /swagger/index.html

    , where is a randomly chosen port number set at the project creation.

    The Swagger page

    /swagger/index.html

    is displayed. Select GET > Try it out > Execute. The page displays:

    • The Curl command to test the WeatherForecast API.
    • The URL to test the WeatherForecast API.
    • The response code, body, and headers.
    • A drop-down list box with media types and the example value and schema.

    If the Swagger page doesn’t appear, see this GitHub issue.

    Swagger is used to generate useful documentation and help pages for web APIs. This tutorial uses Swagger to test the app. For more information on Swagger, see ASP.NET Core web API documentation with Swagger / OpenAPI.

    Copy and paste the Request URL in the browser:

    https://localhost: /weatherforecast

    JSON similar to the following example is returned:


    [ { "date": "2019-07-16T19:04:05.7257911-06:00", "temperatureC": 52, "temperatureF": 125, "summary": "Mild" }, { "date": "2019-07-17T19:04:05.7258461-06:00", "temperatureC": 36, "temperatureF": 96, "summary": "Warm" }, { "date": "2019-07-18T19:04:05.7258467-06:00", "temperatureC": 39, "temperatureF": 102, "summary": "Cool" }, { "date": "2019-07-19T19:04:05.7258471-06:00", "temperatureC": 10, "temperatureF": 49, "summary": "Bracing" }, { "date": "2019-07-20T19:04:05.7258474-06:00", "temperatureC": -1, "temperatureF": 31, "summary": "Chilly" } ]

    Adding a Controller

    In Web API, a controller is an object that handles HTTP requests. We’ll add a controller that can return either a list of products or a single product specified by ID.

    Note

    If you have used ASP.NET MVC, you are already familiar with controllers. Web API controllers are similar to MVC controllers, but inherit the ApiController class instead of the Controller class.

    In Solution Explorer, right-click the Controllers folder. Select Add and then select Controller.

    In the Add Scaffold dialog, select Web API Controller – Empty. Click Add.

    In the Add Controller dialog, name the controller “ProductsController”. Click Add.

    The scaffolding creates a file named ProductsController.cs in the Controllers folder.

    Note

    You don’t need to put your controllers into a folder named Controllers. The folder name is just a convenient way to organize your source files.

    If this file is not open already, double-click the file to open it. Replace the code in this file with the following:


    using ProductsApp.Models; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Web.Http; namespace ProductsApp.Controllers { public class ProductsController : ApiController { Product[] products = new Product[] { new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 }, new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M }, new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M } }; public IEnumerable GetAllProducts() { return products; } public IHttpActionResult GetProduct(int id) { var product = products.FirstOrDefault((p) => p.Id == id); if (product == null) { return NotFound(); } return Ok(product); } } }

    To keep the example simple, products are stored in a fixed array inside the controller class. Of course, in a real application, you would query a database or use some other external data source.

    The controller defines two methods that return products:

    • The

      GetAllProducts

      method returns the entire list of products as an IEnumerable type.
    • The

      GetProduct

      method looks up a single product by its ID.

    That’s it! You have a working web API. Each method on the controller corresponds to one or more URIs:

    Controller Method URI
    GetAllProducts /api/products
    GetProduct /api/products/id

    For the

    GetProduct

    method, the id in the URI is a placeholder. For example, to get the product with ID of 5, the URI is

    api/products/5

    .

    For more information about how Web API routes HTTP requests to controller methods, see Routing in ASP.NET Web API.

    Stand-alone Web API Project

    Here, we will create a new stand-alone Web API project without MVC project.

    For this, open Visual Studio 2013 for Web -> go to File menu and select New Project.. This will open New Project popup as below.

    Select Web template in the left pane and ASP.NET Web Application in the middle pane. Enter a name of the project, location and Solution name as shown above. Clicking on OK will open a popup as shown below.

    In the above popup, select Empty as a template and click ok. This will create an empty “HelloWebAPI” project.

    Now, we need to add latest Web API references using NuGet Package Manager. Right Click on the project and click Manage NuGet Packages.. as shown below.

    This will open Manage NuGet Packages popup. Select Online in the left pane and search for webapi (make sure that internet connection is on). This will display all the Web API related packages. Select Microsoft ASP.NET Web API2.2 package and click on Install as shown below.

    Accept the license agreement and continue.

    The following Web API packages are displayed upon successful installation.

    Now, create Controllers and Configuration folder in the HelloWebAPI project as shown below. We will add Web API controller in the Controllers folder and configuration class in the Configuration folder.

    Now, add a new class in the configuration folder and name it “HelloWebAPIConfig” with following content. (You may give any appropriate name)


    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; namespace HelloWebAPI.Configuration { public static class HelloWebAPIConfig { public static void Register(HttpConfiguration config) { // Web API routes config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } } }

    Now, add Global.asax by right clicking on the project -> select Add -> click New Item.. to open Add New Item popup as below. Select Global Application Class and click OK.

    This will add Global.asax file into the project. We need to configure our Web API routes when application starts. So call HelloWebAPIConfig.Register() method in the Application_Start event in the Global.asax as shown below.


    public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { GlobalConfiguration.Configure(HelloWebAPIConfig.Register); } }

    Web API is configured only using code based configuration using GlobalConfiguration class. The Configure() method requires a callback method where you have configured your Web API.

    Thus, when application starts it will call Application_Start event which in turn calls HelloWebAPIConfig.Register() method to configure your Web API.

    Now, let’s add Web API controller by right clicking on the Controllers folder -> select Controller.. this will open popup as below.

    Select Web API in the left pane and Web API 2 Controller – Empty in the middle pane and click Add. This will open another popup to enter a name of your controller as below. Enter controller name and click Add.

    This will create following empty HelloController class in Controllers folder.


    using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; namespace HelloWebAPI.Controller { public class HelloController : ApiController { } }

    Now, we need to add action methods. Here, we will add simple Get action methods as shown below.


    using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; namespace HelloWebAPI.Controller { public class HelloController : ApiController { public string Get() { return "Hello World"; } } }

    Now, compile and run the project and navigate to

    http://localhost:xxxx/api/hello

    in the browser. It will display following result. (replace xxxx with your local port number)

    So in this way you can create a simple Web API from scratch with config and controller class.

    During the development, programmers often need to test and check the result of Web API. Learn how to test Web API for development in the next section.

    • ASP.NET MVC Tutorial
    • ASP.NET MVC – Home
    • ASP.NET MVC – Overview
    • ASP.NET MVC – Pattern
    • ASP.NET MVC – Environment Setup
    • ASP.NET MVC – Getting Started
    • ASP.NET MVC – Life Cycle
    • ASP.NET MVC – Routing
    • ASP.NET MVC – Controllers
    • ASP.NET MVC – Actions
    • ASP.NET MVC – Filters
    • ASP.NET MVC – Selectors
    • ASP.NET MVC – Views
    • ASP.NET MVC – Data Model
    • ASP.NET MVC – Helpers
    • ASP.NET MVC – Model Binding
    • ASP.NET MVC – Databases
    • ASP.NET MVC – Validation
    • ASP.NET MVC – Security
    • ASP.NET MVC – Caching
    • ASP.NET MVC – Razor
    • ASP.NET MVC – Data Annotations
    • Nuget Package Management
    • ASP.NET MVC – Web API
    • ASP.NET MVC – Scaffolding
    • ASP.NET MVC – Bootstrap
    • ASP.NET MVC – Unit Testing
    • ASP.NET MVC – Deployment
    • ASP.NET MVC – Self-hosting
    • ASP.NET MVC Useful Resources
    • ASP.NET MVC – Quick Guide
    • ASP.NET MVC – Useful Resources
    • ASP.NET MVC – Discussion

    ASP.NET MVC – Web API

    ASP.NET Web API is a framework that makes it easy to build HTTP services that reach a broad range of clients, including browsers and mobile devices. ASP.NET Web API is an ideal platform for building RESTful applications on the .NET Framework.

    When you’re building APIs on the Web, there are several ways you can build APIs on the Web. These include HTTP/RPC, and what this means is using HTTP in Remote Procedure Call to call into things, like Methods, across the Web.

    The verbs themselves are included in the APIs, like Get Customers, Insert Invoice, Delete Customer, and that each of these endpoints end up being a separate URI.

    Let’s take a look at a simple example of Web API by creating a new ASP.NET Web Application.

    Step 1 − Open the Visual Studio and click File → New → Project menu option.

    A new Project dialog opens.

    Step 2 − From the left pane, select Templates → Visual C# → Web.

    Step 3 − In the middle pane, select ASP.NET Web Application

    Enter project name WebAPIDemo in the Name field and click Ok to continue. You will see the following dialog, which asks you to set the initial content for the ASP.NET project.

    Step 4 − To keep things simple, select the Empty option and check the Web API checkbox in the ‘Add folders and core references for’ section and click Ok.

    Step 5 − It will create a basic MVC project with minimal predefined content.

    Once the project is created by Visual Studio, you will see a number of files and folders displayed in the Solution Explorer window.

    Step 6 − Now we need to add a model. Right-click on the Models folder in the solution explorer and select Add → Class.

    You will now see the Add New Item dialog.

    Step 7 − Select Class in the middle pan and enter Employee.cs in the name field.

    Step 8 − Add some properties to Employee class using the following code.

    using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace WebAPIDemo.Models { public class Employee{ public int ID { get; set; } public string Name { get; set; } public DateTime JoiningDate { get; set; } public int Age { get; set; } } }

    Step 9 − Let’s add the controller. Right-click on the controller folder in the solution explorer and select Add → Controller.

    It will display the Add Scaffold dialog.

    Step 10 − Select the Web API 2 Controller – Empty option. This template will create an Index method with default action for controller.

    Step 11 − Click ‘Add’ button and the Add Controller dialog will appear.

    Step 12 − Set the name to EmployeesController and click ‘Add’ button.

    You will see a new C# file ‘EmployeeController.cs’ in the Controllers folder, which is open for editing in Visual Studio with some default actions.

    using System; using System.Collections.Generic; using System.Linq; using System.Web.Http; using WebAPIDemo.Models; namespace WebAPIDemo.Controllers{ public class EmployeesController : ApiController{ Employee[] employees = new Employee[]{ new Employee { ID = 1, Name = “Mark”, JoiningDate = DateTime.Parse(DateTime.Today.ToString()), Age = 30 }, new Employee { ID = 2, Name = “Allan”, JoiningDate = DateTime.Parse(DateTime.Today.ToString()), Age = 35 }, new Employee { ID = 3, Name = “Johny”, JoiningDate = DateTime.Parse(DateTime.Today.ToString()), Age = 21 } }; public IEnumerable

    GetAllEmployees(){ return employees; } public IHttpActionResult GetEmployee(int id){ var employee = employees.FirstOrDefault((p) => p.ID == id); if (employee == null){ return NotFound(); } return Ok(employee); } } }

    Step 13 − Run this application and specify /api/employees/ at the end of the URL and press ‘Enter’. You will see the following output.

    Step 14 − Let us specify the following URL http://localhost:63457/api/employees/1 and you will see the following output.

    In this article, we will see what is Web API & MVC, their features & components, along with knowing their advantages & disadvantages, finally, will see the difference between them.

    The Model View Controller (MVC) is part of an architecture pattern that separates the application into 3 major Logical components that consist of a data model that contains only the pure application data, without containing any logic that describes how to present the data to a user. The Presentation(view) signifies the model’s data to the user. The view knows how to access the model’s data, but it does not know what this data means or what the user can do to manipulate it. The final part is the controller that exists between the view and the model. It listens to events triggered by the view (or another external source) and executes the appropriate reaction to these events. In most cases, the reaction is to call a method on the model. It is basically responsible for managing the query string values and transferring the result values to the models.

    Overview

    This tutorial creates the following API:

    API Description Request body Response body
    Get all to-do items None Array of to-do items
    Get an item by ID None To-do item
    Add a new item To-do item To-do item
    Update an existing item To-do item None
    Delete an item None None

    The following diagram shows the design of the app.

    Add a database context

    The database context 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.

    Add NuGet packages

    • From the Tools menu, select NuGet Package Manager > Manage NuGet Packages for Solution.
    • Select the Browse tab, and then enter

      Microsoft.EntityFrameworkCore.InMemory

      in the search box.
    • Select

      Microsoft.EntityFrameworkCore.InMemory

      in the left pane.
    • Select the Project checkbox in the right pane and then select Install.

    The PutTodoItem method

    Examine the

    PutTodoItem

    method:


    // PUT: api/TodoItems/5 [HttpPut("{id}")] public async Task

    PutTodoItem(long id, TodoItem todoItem) { if (id != todoItem.Id) { return BadRequest(); } _context.Entry(todoItem).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!TodoItemExists(id)) { return NotFound(); } else { throw; } } return NoContent(); }


    PutTodoItem

    is similar to

    PostTodoItem

    , except it uses HTTP PUT. The response is 204 (No Content). According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. To support partial updates, use HTTP PATCH.

    If you get an error calling

    PutTodoItem

    , call

    GET

    to ensure there’s an item in the database.

    Test the PutTodoItem method

    This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PUT call. Call GET to ensure there’s an item in the database before making a PUT call.

    Update the to-do item that has Id = 1 and set its name to “feed fish”:


    { "id":1, "name":"feed fish", "isComplete":true }

    The following image shows the Postman update:

    See this App Running on Azure

    Would you like to see the finished site running as a live web app? You can deploy a complete version of the app to your Azure account.

    You need an Azure account to deploy this solution to Azure. If you do not already have an account, you have the following options:

    • Open an Azure account for free – You get credits you can use to try out paid Azure services, and even after they’re used up you can keep the account and use free Azure services.
    • Activate MSDN subscriber benefits – Your MSDN subscription gives you credits every month that you can use for paid Azure services.

    Nghiên cứu Web API với ASP.NET MVC4

    Bài đăng này đã không được cập nhật trong 8 năm

    ASP.NET Web API là 1 framework để xây dựng các dịch vụ HTTP có thể truy cập từ nhiều client như trình duyệt hay các thiết bị di động. Web API được giới thiệu là 1 phần của MVC4. Trong bài viết này tôi sẽ giới thiệu thiết kế, khái niệm, tính năng và so sánh Web API với WCF.

    Thực thi 1 WEB API project

    Hãy bắt đầu với việ tạo 1 project ví dụ về Web API. Bước đầu cần tạo 1 ASP.NET MVC 4 project dùng Web API template như hình sau:

    Tiếp đó ta cần tạo 1 Model tên là Product với các thuộc tính như sau:

    Sau khi tạo Product model ta có thể tạo API controller để xử lý Product model:

    Tiếp đó ta tạo 1 số dữ liệu mẫu:


    public class ProductsController : ApiController { List products = new List (); public IEnumerable GetAllProducts() { GetProducts(); return products; } private void GetProducts() { products.Add(new Product {Id = 1, Name = "Television", Category="Electronic", Price=82000}); products.Add(new Product { Id = 2, Name = "Refrigerator", Category = "Electronic", Price = 23000 }); products.Add(new Product { Id = 3, Name = "Mobiles", Category = "Electronic", Price = 20000 }); products.Add(new Product { Id = 4, Name = "Laptops", Category = "Electronic", Price = 45000 }); products.Add(new Product { Id = 5, Name = "iPads", Category = "Electronic", Price = 67000 }); products.Add(new Product { Id = 6, Name = "Toys", Category = "Gift Items", Price = 15000 }); } public IEnumerable GetProducts(int selectedId) { if (products.Count() > 0) { return products.Where(p => p.Id == selectedId); } else { GetProducts(); return products.Where(p => p.Id == selectedId); } }

    Chạy project và thử truy cập API theo 2 url sau ta có thể thấy kết quả như mong đợi:

    http://localhost:11715/api/products

    http://localhost:11715/api/products?selectedID=2

    Truyền những đối tượng phức tạp vào phương thức của Web API:

    Hãy cùng thử 1 ví dụ nếu ta cần truyền 1 object tới phương thức của Web API như sau:


    namespace WebApiProject.Controllers { public class SampleController : ApiController { public string GetTime(Time t) { return string.Format("Received Time: {0}:{1}.{2}", t.Hour, t.Minute, t.Second); } } public class Time { public int Hour { get; set; } public int Minute { get; set; } public int Second { get; set; } } }

    Sau khi chạy thử project truyền vào các tham số Hour, Minute và Second. Ta có thể thấy nó sẽ trả về null exception.




    An error has occurred.


    Object reference not set to an instance of an object.


    System.NullReferenceException


    at WebApiProject.Controllers.SampleController.GetTime(Time t) in c:\Users\Trungx\Documents\Visual Studio 2013\Projects\WebApiProject\WebApiProject\Controllers\SampleController.cs:line 14 at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.

    b__9(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at System.Web.Http.Controllers.ApiControllerActionInvoker.

    d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at System.Web.Http.Controllers.ActionFilterResult.

    d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at System.Web.Http.Dispatcher.HttpControllerDispatcher.

    d__0.MoveNext()






    Giờ hãy cùng xem sự thay đổi khi ta sửa lại code và thêm thuộc tính [FromUri] để xử lý object truyền vào từ query string:


    public string GetTime([FromUri] Time t)

    Kết quả:



    Received Time: 10:25.12

    Làm việc với HttpClient API:

    Ta có thể gọi đến Web API bằng nhiều cách trong đó có cách sử dụng lớp HttpClient có sẵn của ASP.NET, đoạn code dưới đây giới thiệu cách tạo 1 HttpClient object và dùng nó để truy cập bất đồng bộ đến phương thức API:


    // asynchronous accessing of web api method async Task GetData() { StringBuilder result = new StringBuilder(); // Define the httpClient object using (HttpClient client = new HttpClient()) { // Define the base address of the MVC application hosting the web api // accessing the web api from the same solution client.BaseAddress = new Uri(HttpContext.Current.Request.Url.AbsoluteUri); // Define the serialization used json/xml/ etc client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json")); // Call the method HttpResponseMessage response = client.GetAsync("api/products").Result; if (response.IsSuccessStatusCode) { // Convert the result into business object var products = response.Content.ReadAsAsync
    >().Result; foreach (var p in products) { result.Append(string.Format("{0} --- [Price: {1} Category: {2}] ", p.Name, p.Price, p.Category)); } } else { result.Append(string.Format("Error Code:-{0} Error Details: {1}", (int)response.StatusCode, response.ReasonPhrase)); } } data.Text = result.ToString(); }

    Truy cập Web API từ jQuery:

    Việc truy cập Web API cũng rất dễ dàng với hàm getJSON:

    Kết quả:


    Television Electronic 82000 Refrigerator Electronic 23000 Mobiles Electronic 20000 Laptops Electronic 45000 iPads Electronic 67000 Toys Gift Items 15000

    Để truyền tham số dùng jQuery ta thêm vào như sau:


    $.getJSON("api/products", { selectedId: '4' }, function (data) { ….});

    Các phương thức Serialization:

    Web API hỗ trợ nhiều phương thức serialization bao gồm: XML, JSON và MessagePack. Trong phần này chúng ta sẽ tìm hiểu cách thực thi 3 phương thức này và so sách cách thể hiện của chúng. Để làm việc đó trước hết hãy sửa project ví dụ của chúng ta trả về 1 lượng dữ liệu để chúng ta hiểu và so sánh hiệu suất của 3 phương thức 1 cách tốt hơn.


    private void GetProducts() { for (int i = 0; i < 5000; i++) { products.Add(new Product { Id = i, Name = "Product - "+i, Category = "The ASP.NET and Visual Web Developer teams have released the ASP.NET and Web Tools 2012.2 update, which extends the existing ASP.NET runtime and adds new web tooling to Visual Studio 2012. Whether you use Web Forms, MVC, Web API, or any other ASP.NET technology, there is something cool in this update for you.", Price = 1 }); } }

    Mặc định Web API dùng JSON là phương thức serialization mặc định. Để dùng XML serialization ta cần chỉnh sửa trong Global.asax thêm vào 2 dòng sau:


    GlobalConfiguration.Configuration.Formatters.RemoveAt(0); GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;

    Với MessagePack serialization:

    Để dùng phương thức này trước hết ta phải cài đặt MessagePack tại địa chỉ: http://msgpack.org/. Sau khi cài đặt hãy thêm reference thư viện: MsgPack.dll. Tiếp đó tạo 1 MediaTypeFormatter sử dụng MessagePack để serialize.


    public class MediaTypeFormatterCompatibleMessagePack : MediaTypeFormatter { private readonly string _mime = "application/x-msgpack"; Func

    IsAllowedType = (t) => { if (!t.IsAbstract && !t.IsInterface && t != null && !t.IsNotPublic) return true; if (typeof(IEnumerable).IsAssignableFrom(t)) return true; return false; }; public MediaTypeFormatterCompatibleMessagePack() { SupportedMediaTypes.Add(new MediaTypeHeaderValue(_mime)); } public override bool CanWriteType(Type type) { if (type == null) throw new ArgumentNullException("Type is null"); return IsAllowedType(type); } public override Task WriteToStreamAsync(Type type, object value, System.IO.Stream stream, HttpContent content, TransportContext transportContext) { if (type == null) throw new ArgumentNullException("type is null"); if (stream == null) throw new ArgumentNullException("Write stream is null"); var tcs = new TaskCompletionSource
    (); if (type != typeof(string) && typeof(IEnumerable).IsAssignableFrom(type)) { value = (value as IEnumerable
    ).ToList(); } var serializer = MessagePackSerializer.Create

    (); serializer.Pack(stream, value); tcs.SetResult(null); return tcs.Task; } public override Task
    ReadFromStreamAsync(Type type,Stream stream, HttpContent content, IFormatterLogger formatterLogger) { var tcs = new TaskCompletionSource
    (); if (content.Headers != null && content.Headers.ContentLength == 0) return null; try { var serializer = MessagePackSerializer.Create(type); object result; using (var mpUnpacker = Unpacker.Create(stream)) { mpUnpacker.Read(); result = serializer.UnpackFrom(mpUnpacker); } tcs.SetResult(result); } catch (Exception e) { if (formatterLogger == null) throw; formatterLogger.LogError(String.Empty, e.Message); tcs.SetResult(GetDefaultValueForType(type)); } return tcs.Task; } public override bool CanReadType(Type type) { if (type == null) throw new ArgumentNullException("type is null"); return IsAllowedType(type); } }



    Tiếp đó ta cấu hình trong Global.asax tương tự như với phương thức XML:


    GlobalConfiguration.Configuration.Formatters.Clear(); GlobalConfiguration.Configuration.Formatters.Add(new MediaTypeFormatterCompatibleMessagePack());

    So sánh 3 phương thức ta thu được kết quả về khả năng nén dữ liệu: MessagePack > JSON > XML

    WCF và Web API:

    Tất nhiên WCF hỗ trợ rất nhiều giao thức trong đó có cả HTTP tuy nhiên để thực thi 1 service dựa trên HTTP bằng WCF khá khó khăn và phức tạp và không sử dụng được các tính năng chính của HTTP như Caching hay Status Code. Trong khi đó sử dụng WEB API ta có thể thực thi tất cả GET,POST,PUT,DELETE và đầy đủ các tính năng của HTTP 1 cách dễ dàng.

    All rights reserved

    Tổng quan về MVC API trong .NET 6

    Mô hình MVC

    • Model : là nơi chứa những nghiệp vụ tương tác với dữ liệu hoặc hệ quản trị cơ sở dữ liệu (mysql, mssql… ); nó s0ẽbao gồm các class/function xử lý nhiều nghiệp vụ như kết nối database, truy vấn dữ liệu, th• êm –• xóa •– sửa• dữ liệu…

    • View : là nới chứa những giao diện như một nút bấm, khung nhập, menu, hình ảnh… nó đảm nhiệm nhiệm vụ hiển thị dữ liệu và giúp người dùng tương tác với hệ thống.

    • Controller : là nới tiếp nhận những yêu cầu xử lý được gửi từ người dùng, nó sẽ gồm những class/ function xử lý nhiều nghiệp vụ logic giúp lấy đúng dữ liệu thông tin cần thiết nhờ các nghiệp vụ lớp Model cung cấp và hiển thị dữ liệu đó ra cho người dùng nhờ lớp View.

    • Tương tác giữa các thành phần:

      • Controller tương tác với qua lại với View
      • Controller tương tác qua lại với Model
      • Model và View không có sự tương tác với nhau mà nó tương tác với nhau thông qua Controller.

    API

    • API viết tắt là Application Programming Interface – giao diện lập trình ứng dụng. Nó cung cấp khả năng giao tiếp trao đổi giữa các ứng dụng thông qua internent.
    • Ở phần trước khi không sử dụng api .net 6 thì ứng dụng sẽ bao gồm phần backend và frontend chung.

    • Khi sử dụng web api thì thường sẽ chia backend ra riêng và frontend ra riêng. Và frontend website sẽ giao tiếp với backend qua API hoặc có các app mobile sẽ giao tiếp với backend qua API.

    • Ứng dụng web

    • Ứng dụng mobile

    Restful là gì?

    • RESTful API là một tiêu chuẩn dùng trong việc thiết kế API cho các ứng dụng web (thiết kế Web services) để tiện cho việc quản lý các resource. Nó chú trọng vào tài nguyên hệ thống (tệp văn bản, ảnh, âm thanh, video, hoặc dữ liệu động…), bao gồm các trạng thái tài nguyên được định dạng và được truyền tải qua HTTP.

    • Các giao thức HTTP:

      • GET (SELECT): Trả về một Resource hoặc một danh sách Resource.
      • POST (CREATE): Tạo mới một Resource.
      • PUT (UPDATE): Cập nhật thông tin cho Resource.
      • DELETE (DELETE): Xoá một Resource.
    • Những phương thức hay hoạt động này thường được gọi là CRUD tương ứng với Create, Read, Update, Delete – Tạo, Đọc, Sửa, Xóa.

    Status code

    • Khi chúng ta request một API nào đó thường thì sẽ có vài status code để nhận biết sau:

      • 200 OK – Trả về thành công cho những phương thức GET, PUT, PATCH hoặc DELETE.
      • 201 Created – Trả về khi một Resouce vừa được tạo thành công.
      • 204 No Content – Trả về khi Resource xoá thành công.
      • 304 Not Modified – Client có thể sử dụng dữ liệu cache.
      • 400 Bad Request – Request không hợp lệ
      • 401 Unauthorized – Request cần có auth.
      • 403 Forbidden – bị từ chối không cho phép.
      • 404 Not Found – Không tìm thấy resource từ URI
      • 405 Method Not Allowed – Phương thức không cho phép với user hiện tại.
      • 410 Gone – Resource không còn tồn tại, Version cũ đã không còn hỗ trợ.
      • 415 Unsupported Media Type – Không hỗ trợ kiểu Resource này.
      • 422 Unprocessable Entity – Dữ liệu không được xác thực
      • 429 Too Many Requests – Request bị từ chối do bị giới hạn
    • Đọc thêm về http code: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status

    • Tương ứng với trong .NET 6:

      • return Ok(Value) : trả về http code 200 và kết quả.
      • return BadRequest(): trả về http code 400
      • return NotFound(): trả về http code 404
      • return NoContent(): trả về http code 204
      • return new UnsupportedMediaTypeResult(): trả về http code 415
    • Trả về HTML

      • Phương thức View() sẽ trả về một ViewResult là một HTML response.
      • Phương thức PartialView() sẽ trả về một phần của View. Sử dụng khi muốn cập nhật 1 phần của view mà không muốn load lại toàn bộ view (hữu ích trong Single Page Application)
    • Trả về File

      • FileContentResult: đọc một mảng byte và trả về như một file.
      • FileStreamResult: đọc một luồng stream và trả về một file.
      • VirtualFileResult: đọc nội dung file từ một đường dẫn tương đối trên hosting và trả về cho client.
      • PhysicalFileResult: đọc nội dung file từ một đường dẫn vật lý và trả về cho client.
    • Trả về nội dung văn bản

      • Content(value): ActionResult trả về một nội dung cụ thể như một văn bản thuần.
      • new JsonResult(value): ActionResult này trả về dữ liệu định dạng JSON. Có thể chuyển một object sang Json và trả về cho client
    • Đọc thêm về Json: https://www.w3schools.com/js/js_json_intro.asp

    Thực hành MVC API

    • Tạo 5 api:

      • GET: api/categories
      • GET: api/categories/{id}
      • POST: api/categories
      • PUT: api/categories/{id}
      • DELETE: api/categories/{id}
    • Cài đặt postman để test api: https://www.postman.com/downloads/

    Sử dụng Javascript làm frontend để call api

    • Tham khảo: https://learn.microsoft.com/vi-vn/aspnet/core/tutorials/web-api-javascript?view=aspnetcore-6.0

    • Bài tập về nhà: Làm chức năng create new categories, update category và delete category.

    Routing trong .net core

    • Routing là quá trình điều hướng các URL request đến đúng các controller và action tương ứng.

    • Route template

      • Để url request tìm đến đúng controller action tương ứng cần có một template đóng vai trò như bản đồ chỉ dẫn.
      • Ví dụ: {controller=Post}/{action=GetByIdl}/{id?}
    • Có 2 cách để cài đặt route template:

      • Attribute routing: Ví dụ: [Route(“api/[controller]”)]
      • Convention Based Routing: https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-6.0

    Environment trong .NET 6

    • Development: môi trường cho nhà phát triển

    • Staging: môi trường để testing (gần giống production)

    • Production: môi trường thực tế khách hàng sử dụng.

    • Cấu hình (configuration) trong .net

      • .NET cung cấp appsettings.json file để lưu trữ các cấu hình cho ứng dụng.
      • Ví dụ: lưu trữ cấu hình ConnectionString đến cơ sở dữ liệu, thông tin tham số ứng dụng, đường dẫn thư mục hình ảnh,….
    • Cấu hình (configuration) tùy theo môi trường

      • appsettings.json
      • appsettings.Development.json cho môi trường development.
      • appsettings.Staging.json cho môi trường staging.
      • appsettings.Production.json cho môi trường production.
    • launchSettings.json sẽ dựa vào ASPNETCORE_ENVIRONMENT để biết ứng dụng đang chạy môi trường nào.

    Đọc file cấu hình appsettings.json bằng IConfiguration

    • Tham khảo: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0

    • Binding data trong file cấu hình thành object với IOptions

      • Khai báo dependence injection:

        builder.Services.Configure (builder.Configuration.GetSection("Position"));
      • Sử dụng IOptions Inject vào constructor:
    • Khai báo dependence injection:
    • Lấy giá trị connection string từ appsettings.json

    Tham khảo:

    • https://medium.com/@joespinelli_6190/mvc-model-view-controller-ef878e2fd6f5
    • https://www.geeksforgeeks.org/benefit-of-using-mvc/
    • API là gì? Tại sao API được sử dụng nhiều hiện nay?

    • https://www.guru99.com/what-is-api.html
    • https://viblo.asia/p/restful-api-la-gi-1Je5EDJ4lnL
    • https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
    • https://learn.microsoft.com/vi-vn/aspnet/core/tutorials/web-api-javascript?view=aspnetcore-6.0

    All rights reserved

    Get Started with ASP.NET Web API 2 (C#)

    by Mike Wasson

    In this tutorial, you will use ASP.NET Web API to create a web API that returns a list of products.

    HTTP is not just for serving up web pages. HTTP is also a powerful platform for building APIs that expose services and data. HTTP is simple, flexible, and ubiquitous. Almost any platform that you can think of has an HTTP library, so HTTP services can reach a broad range of clients, including browsers, mobile devices, and traditional desktop applications.

    ASP.NET Web API is a framework for building web APIs on top of the .NET Framework.

    Overview

    This tutorial creates the following API:

    API Description Request body Response body
    Get all to-do items None Array of to-do items
    Get an item by ID None To-do item
    Add a new item To-do item To-do item
    Update an existing item To-do item None
    Delete an item None None

    The following diagram shows the design of the app.

    Add a database context

    The database context 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.

    Add NuGet packages

    • From the Tools menu, select NuGet Package Manager > Manage NuGet Packages for Solution.
    • Select the Browse tab, and then enter

      Microsoft.EntityFrameworkCore.InMemory

      in the search box.
    • Select

      Microsoft.EntityFrameworkCore.InMemory

      in the left pane.
    • Select the Project checkbox in the right pane and then select Install.

    Scaffold a controller

    • Right-click the Controllers folder.

    • Select Add > New Scaffolded Item.

    • Select API Controller with actions, using Entity Framework, and then select Add.

    • In the Add API Controller with actions, using Entity Framework dialog:

      • Select TodoItem (TodoApi.Models) in the Model class.
      • Select TodoContext (TodoApi.Models) in the Data context class.
      • Select Add.

    The generated code:

    • Marks the class with the

      [ApiController]

      attribute. This attribute indicates that the controller responds to web API requests. For information about specific behaviors that the attribute enables, see Create web APIs with ASP.NET Core.
    • Uses DI to inject the database context (

      TodoContext

      ) into the controller. The database context is used in each of the CRUD methods in the controller.

    The ASP.NET Core templates for:

    • Controllers with views include

      [action]

      in the route template.
    • API controllers don’t include

      [action]

      in the route template.

    When the

    [action]

    token isn’t in the route template, the action name is excluded from the route. That is, the action’s associated method name isn’t used in the matching route.

    Prevent over-posting

    Currently the sample app exposes the entire

    TodoItem

    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. DTO is used in this article.

    A DTO may be used to:

    • Prevent over-posting.
    • Hide properties that clients are not supposed to view.
    • Omit some properties in order to reduce payload size.
    • Flatten object graphs that contain nested objects. Flattened object graphs can be more convenient for clients.

    To demonstrate the DTO approach, update the

    TodoItem

    class to include a secret field:


    public class TodoItem { public long Id { get; set; } public string Name { get; set; } public bool IsComplete { get; set; } public string Secret { get; set; } }

    The secret field needs to be hidden from this app, but an administrative app could choose to expose it.

    Verify you can post and get the secret field.

    Create a DTO model:


    public class TodoItemDTO { public long Id { get; set; } public string Name { get; set; } public bool IsComplete { get; set; } }

    Update the

    TodoItemsController

    to use

    TodoItemDTO

    :


    [HttpGet] public async Task

    >> GetTodoItems() { return await _context.TodoItems .Select(x => ItemToDTO(x)) .ToListAsync(); } [HttpGet("{id}")] public async Task

    > GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return ItemToDTO(todoItem); } [HttpPut("{id}")] public async Task

    UpdateTodoItem(long id, TodoItemDTO todoItemDTO) { if (id != todoItemDTO.Id) { return BadRequest(); } var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } todoItem.Name = todoItemDTO.Name; todoItem.IsComplete = todoItemDTO.IsComplete; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) when (!TodoItemExists(id)) { return NotFound(); } return NoContent(); } [HttpPost] public async Task

    > CreateTodoItem(TodoItemDTO todoItemDTO) { var todoItem = new TodoItem { IsComplete = todoItemDTO.IsComplete, Name = todoItemDTO.Name }; _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); return CreatedAtAction( nameof(GetTodoItem), new { id = todoItem.Id }, ItemToDTO(todoItem)); } [HttpDelete("{id}")] public async Task

    DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); } private bool TodoItemExists(long id) => _context.TodoItems.Any(e => e.Id == id); private static TodoItemDTO ItemToDTO(TodoItem todoItem) => new TodoItemDTO { Id = todoItem.Id, Name = todoItem.Name, IsComplete = todoItem.IsComplete }; }





    Verify you can’t post or get the secret field.

    Add authentication support to a web API

    ASP.NET Core Identity adds user interface (UI) login functionality to ASP.NET Core web apps. To secure web APIs and SPAs, use one of the following:

    • Microsoft Entra ID
    • Azure Active Directory B2C (Azure AD B2C)
    • Duende Identity Server

    Duende Identity Server is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core. Duende Identity Server enables the following security features:

    • Authentication as a Service (AaaS)
    • Single sign-on/off (SSO) over multiple application types
    • Access control for APIs
    • Federation Gateway

    Important

    Duende Software might require you to pay a license fee for production use of Duende Identity Server. For more information, see Migrate from ASP.NET Core 5.0 to 6.0.

    For more information, see the Duende Identity Server documentation (Duende Software website).

    Prevent over-posting

    Currently the sample app exposes the entire

    TodoItem

    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. DTO is used in this tutorial.

    A DTO may be used to:

    • Prevent over-posting.
    • Hide properties that clients are not supposed to view.
    • Omit some properties in order to reduce payload size.
    • Flatten object graphs that contain nested objects. Flattened object graphs can be more convenient for clients.

    To demonstrate the DTO approach, update the

    TodoItem

    class to include a secret field:


    namespace TodoApi.Models { public class TodoItem { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } public string? Secret { get; set; } } }

    The secret field needs to be hidden from this app, but an administrative app could choose to expose it.

    Verify you can post and get the secret field.

    Create a DTO model:


    namespace TodoApi.Models; public class TodoItemDTO { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } }

    Update the

    TodoItemsController

    to use

    TodoItemDTO

    :


    using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using TodoApi.Models; namespace TodoApi.Controllers; [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase { private readonly TodoContext _context; public TodoItemsController(TodoContext context) { _context = context; } // GET: api/TodoItems [HttpGet] public async Task

    >> GetTodoItems() { return await _context.TodoItems .Select(x => ItemToDTO(x)) .ToListAsync(); } // GET: api/TodoItems/5 //

    [HttpGet("{id}")] public async Task

    > GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return ItemToDTO(todoItem); } //


    // PUT: api/TodoItems/5 // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 //

    [HttpPut("{id}")] public async Task

    PutTodoItem(long id, TodoItemDTO todoDTO) { if (id != todoDTO.Id) { return BadRequest(); } var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } todoItem.Name = todoDTO.Name; todoItem.IsComplete = todoDTO.IsComplete; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) when (!TodoItemExists(id)) { return NotFound(); } return NoContent(); } //


    // POST: api/TodoItems // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 //

    [HttpPost] public async Task

    > PostTodoItem(TodoItemDTO todoDTO) { var todoItem = new TodoItem { IsComplete = todoDTO.IsComplete, Name = todoDTO.Name }; _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); return CreatedAtAction( nameof(GetTodoItem), new { id = todoItem.Id }, ItemToDTO(todoItem)); } //


    // DELETE: api/TodoItems/5 [HttpDelete("{id}")] public async Task

    DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); } private bool TodoItemExists(long id) { return _context.TodoItems.Any(e => e.Id == id); } private static TodoItemDTO ItemToDTO(TodoItem todoItem) => new TodoItemDTO { Id = todoItem.Id, Name = todoItem.Name, IsComplete = todoItem.IsComplete }; }


    Verify you can’t post or get the secret field.

    Routing and URL paths

    The

    [HttpGet]

    attribute denotes a method that responds to an HTTP GET request. The URL path for each method is constructed as follows:

    • Start with the template string in the controller’s


      Route

      attribute:

      [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase { private readonly TodoContext _context; public TodoItemsController(TodoContext context) { _context = context; }

    • Replace


      [controller]

      with the name of the controller, which by convention is the controller class name minus the “Controller” suffix. For this sample, the controller class name is TodoItemsController, so the controller name is “TodoItems”. ASP.NET Core routing is case insensitive.

    • If the


      [HttpGet]

      attribute has a route template (for example,

      [HttpGet("products")]

      ), append that to the path. This sample doesn’t use a template. For more information, see Attribute routing with Http[Verb] attributes.

    In the following

    GetTodoItem

    method,

    "{id}"

    is a placeholder variable for the unique identifier of the to-do item. When

    GetTodoItem

    is invoked, the value of

    "{id}"

    in the URL is provided to the method in its

    id

    parameter.


    // GET: api/TodoItems/5 [HttpGet("{id}")] public async Task

    > GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; }

    Add a model class

    A model is a set of classes that represent the data that the app manages. The model for this app is a single

    TodoItem

    class.

    • In Solution Explorer, right-click the project. Select Add > New Folder. Name the folder


      Models

      .

    • Right-click the


      Models

      folder and select Add > Class. Name the class TodoItem and select Add.

    • Replace the template code with the following:


    namespace TodoApi.Models { public class TodoItem { public long Id { get; set; } public string? Name { get; set; } public bool IsComplete { get; set; } } }

    The

    Id

    property functions as the unique key in a relational database.

    Model classes can go anywhere in the project, but the

    Models

    folder is used by convention.

    Feedback

    Submit and view feedback for

    Routing in ASP.NET Web API

    This article describes how ASP.NET Web API routes HTTP requests to controllers.

    Note

    If you are familiar with ASP.NET MVC, Web API routing is very similar to MVC routing. The main difference is that Web API uses the HTTP verb, not the URI path, to select the action. You can also use MVC-style routing in Web API. This article does not assume any knowledge of ASP.NET MVC.

    Register the database context

    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

    Program.cs

    with the following highlighted code:


    using Microsoft.EntityFrameworkCore; using TodoApi.Models; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddDbContext

    (opt => opt.UseInMemoryDatabase("TodoList")); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();

    The preceding code:

    • Adds

      using

      directives.
    • Adds the database context to the DI container.
    • Specifies that the database context will use an in-memory database.

    Routing and URL paths

    The

    [HttpGet]

    attribute denotes a method that responds to an HTTP GET request. The URL path for each method is constructed as follows:

    • Start with the template string in the controller’s


      Route

      attribute:

      [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase { private readonly TodoContext _context; public TodoItemsController(TodoContext context) { _context = context; }

    • Replace


      [controller]

      with the name of the controller, which by convention is the controller class name minus the “Controller” suffix. For this sample, the controller class name is TodoItemsController, so the controller name is “TodoItems”. ASP.NET Core routing is case insensitive.

    • If the


      [HttpGet]

      attribute has a route template (for example,

      [HttpGet("products")]

      ), append that to the path. This sample doesn’t use a template. For more information, see Attribute routing with Http[Verb] attributes.

    In the following

    GetTodoItem

    method,

    "{id}"

    is a placeholder variable for the unique identifier of the to-do item. When

    GetTodoItem

    is invoked, the value of

    "{id}"

    in the URL is provided to the method in its

    id

    parameter.


    // GET: api/TodoItems/5 [HttpGet("{id}")] public async Task

    > GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; }

    Update the PostTodoItem create method

    Update the return statement in the

    PostTodoItem

    to use the nameof operator:


    // POST: api/TodoItems [HttpPost] public async Task

    > PostTodoItem(TodoItem todoItem) { _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); //return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem); return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem); }

    The preceding code is an HTTP POST method, as indicated by the

    [HttpPost]

    attribute. The method gets the value of the to-do item from the body of the HTTP request.

    For more information, see Attribute routing with Http[Verb] attributes.

    The CreatedAtAction method:

    • Returns an HTTP 201 status code if successful. HTTP 201 is the standard response for an HTTP POST method that creates a new resource on the server.
    • Adds a Location header to the response. The

      Location

      header specifies the URI of the newly created to-do item. For more information, see 201 Created.
    • References the

      GetTodoItem

      action to create the

      Location

      header’s URI. The C#

      nameof

      keyword is used to avoid hard-coding the action name in the

      CreatedAtAction

      call.

    Install Postman

    This tutorial uses Postman to test the web API.

    • Install Postman
    • Start the web app.
    • Start Postman.
    • Disable SSL certificate verification:

      • Postman for Windows: Select File > Settings (General tab), disable SSL certificate verification.
      • Postman for macOS: Select Postman > Settings (General tab), disable SSL certificate verification.

        Warning

        Re-enable SSL certificate verification after testing the controller.

    Test PostTodoItem with Postman

    • Create a new request.

    • Set the HTTP method to


      POST

      .

    • Set the URI to


      https://localhost: /api/todoitems

      . For example,

      https://localhost:5001/api/todoitems

      .

    • Select the Body tab.

    • Select the raw radio button.

    • Set the type to JSON (application/json).

    • In the request body enter JSON for a to-do item:


      { "name":"walk dog", "isComplete":true }

    • Select Send.

    Test the location header URI

    The location header URI can be tested in the browser. Copy and paste the location header URI into the browser.

    To test in Postman:

    • Select the Headers tab in the Response pane.

    • Copy the Location header value:

    • Set the HTTP method to


      GET

      .

    • Set the URI to


      https://localhost: /api/todoitems/1

      . For example,

      https://localhost:5001/api/todoitems/1

      .

    • Select Send.

    Using F12 to View the HTTP Request and Response

    When you are working with an HTTP service, it can be very useful to see the HTTP request and response messages. You can do this by using the F12 developer tools in Internet Explorer 9. From Internet Explorer 9, press F12 to open the tools. Click the Network tab and press Start Capturing. Now go back to the web page and press F5 to reload the web page. Internet Explorer will capture the HTTP traffic between the browser and the web server. The summary view shows all the network traffic for a page:

    Locate the entry for the relative URI “api/products/”. Select this entry and click Go to detailed view. In the detail view, there are tabs to view the request and response headers and bodies. For example, if you click the Request headers tab, you can see that the client requested “application/json” in the Accept header.

    If you click the Response body tab, you can see how the product list was serialized to JSON. Other browsers have similar functionality. Another useful tool is Fiddler, a web debugging proxy. You can use Fiddler to view your HTTP traffic, and also to compose HTTP requests, which gives you full control over the HTTP headers in the request.

    Overview

    This tutorial creates the following API:

    API Description Request body Response body
    Get all to-do items None Array of to-do items
    Get an item by ID None To-do item
    Add a new item To-do item To-do item
    Update an existing item To-do item None
    Delete an item None None

    The following diagram shows the design of the app.

    Calling the Web API with Javascript and jQuery

    In this section, we’ll add an HTML page that uses AJAX to call the web API. We’ll use jQuery to make the AJAX calls and also to update the page with the results.

    In Solution Explorer, right-click the project and select Add, then select New Item.

    In the Add New Item dialog, select the Web node under Visual C#, and then select the HTML Page item. Name the page “index.html”.

    Replace everything in this file with the following:


    <br /> Product App<br />

    Register the database context

    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

    Startup.cs

    with the following code:


    // Unused usings removed using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.EntityFrameworkCore; using TodoApi.Models; namespace TodoApi { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddDbContext

    (opt => opt.UseInMemoryDatabase("TodoList")); //services.AddSwaggerGen(c => //{ // c.SwaggerDoc("v1", new OpenApiInfo { Title = "TodoApi", Version = "v1" }); //}); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); //app.UseSwagger(); //app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TodoApi v1")); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } }

    The preceding code:

    • Removes the Swagger calls.
    • Removes unused

      using

      declarations.
    • Adds the database context to the DI container.
    • Specifies that the database context will use an in-memory database.

    The PutTodoItem method

    Examine the

    PutTodoItem

    method:


    [HttpPut("{id}")] public async Task

    PutTodoItem(long id, TodoItem todoItem) { if (id != todoItem.Id) { return BadRequest(); } _context.Entry(todoItem).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!TodoItemExists(id)) { return NotFound(); } else { throw; } } return NoContent(); }


    PutTodoItem

    is similar to

    PostTodoItem

    , except it uses

    HTTP PUT

    . The response is 204 (No Content). According to the HTTP specification, a

    PUT

    request requires the client to send the entire updated entity, not just the changes. To support partial updates, use HTTP PATCH.

    Test the PutTodoItem method

    This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PUT call. Call GET to ensure there's an item in the database before making a PUT call.

    Using the Swagger UI, use the PUT button to update the

    TodoItem

    that has Id = 1 and set its name to

    "feed fish"

    . Note the response is

    HTTP 204 No Content

    .

    Additional resources

    View or download sample code for this tutorial. See how to download.

    For more information, see the following resources:

    • Create web APIs with ASP.NET Core
    • Tutorial: Create a minimal API with ASP.NET Core
    • ASP.NET Core web API documentation with Swagger / OpenAPI
    • Razor Pages with Entity Framework Core in ASP.NET Core - Tutorial 1 of 8
    • Routing to controller actions in ASP.NET Core
    • Controller action return types in ASP.NET Core web API
    • Deploy ASP.NET Core apps to Azure App Service
    • Host and deploy ASP.NET Core
    • Create a web API with ASP.NET Core

    This tutorial teaches the basics of building a controller-based web API that uses a database. Another approach to creating APIs in ASP.NET Core is to create minimal APIs. For help in choosing between minimal APIs and controller-based APIs, see APIs overview. For a tutorial on creating a minimal API, see Tutorial: Create a minimal API with ASP.NET Core.

    The PutTodoItem method

    Examine the

    PutTodoItem

    method:


    [HttpPut("{id}")] public async Task

    PutTodoItem(long id, TodoItem todoItem) { if (id != todoItem.Id) { return BadRequest(); } _context.Entry(todoItem).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!TodoItemExists(id)) { return NotFound(); } else { throw; } } return NoContent(); }


    PutTodoItem

    is similar to

    PostTodoItem

    , except it uses

    HTTP PUT

    . The response is 204 (No Content). According to the HTTP specification, a

    PUT

    request requires the client to send the entire updated entity, not just the changes. To support partial updates, use HTTP PATCH.

    Test the PutTodoItem method

    This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PUT call. Call GET to ensure there's an item in the database before making a PUT call.

    Using the Swagger UI, use the PUT button to update the

    TodoItem

    that has Id = 1 and set its name to

    "feed fish"

    . Note the response is

    HTTP 204 No Content

    .

    Add authentication support to a web API

    ASP.NET Core Identity adds user interface (UI) login functionality to ASP.NET Core web apps. To secure web APIs and SPAs, use one of the following:

    • Microsoft Entra ID
    • Azure Active Directory B2C (Azure AD B2C)
    • Duende Identity Server

    Duende Identity Server is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core. Duende Identity Server enables the following security features:

    • Authentication as a Service (AaaS)
    • Single sign-on/off (SSO) over multiple application types
    • Access control for APIs
    • Federation Gateway

    Important

    Duende Software might require you to pay a license fee for production use of Duende Identity Server. For more information, see Migrate from ASP.NET Core 5.0 to 6.0.

    For more information, see the Duende Identity Server documentation (Duende Software website).

    Test with other tools

    There are many other tools that can be used to test web APIs, for example:

    • Visual Studio Endpoints Explorer and .http files
    • http-repl
    • Postman
    • curl. Swagger uses

      curl

      and shows the

      curl

      commands it submits.
    • Fiddler

    For more information, see:

    • Minimal API tutorial: test with .http files and Endpoints Explorer
    • Test APIs with Postman
    • Install and test APIs with

      http-repl

    Examine the GET methods

    Two GET endpoints are implemented:


    • GET /api/todoitems

    • GET /api/todoitems/{id}

    Test the app by calling the two endpoints from a browser or Postman. For example:


    • https://localhost:5001/api/todoitems

    • https://localhost:5001/api/todoitems/1

    A response similar to the following is produced by the call to

    GetTodoItems

    :


    [ { "id": 1, "name": "Item1", "isComplete": false } ]

    Test Get with Postman

    • Create a new request.
    • Set the HTTP method to GET.
    • Set the request URI to

      https://localhost: /api/todoitems

      . For example,

      https://localhost:5001/api/todoitems

      .
    • Set Two pane view in Postman.
    • Select Send.

    This app uses an in-memory database. If the app is stopped and started, the preceding GET request will not return any data. If no data is returned, POST data to the app.

    Register the database context

    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

    Startup.cs

    with the following code:


    // Unused usings removed using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.EntityFrameworkCore; using TodoApi.Models; namespace TodoApi { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddDbContext

    (opt => opt.UseInMemoryDatabase("TodoList")); //services.AddSwaggerGen(c => //{ // c.SwaggerDoc("v1", new OpenApiInfo { Title = "TodoApi", Version = "v1" }); //}); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); //app.UseSwagger(); //app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TodoApi v1")); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } }

    The preceding code:

    • Removes the Swagger calls.
    • Removes unused

      using

      declarations.
    • Adds the database context to the DI container.
    • Specifies that the database context will use an in-memory database.

    Keywords searched by users: web api in mvc

    Creating Asp.Net Web Api With Mvc 6 | Dotnetcurry
    Creating Asp.Net Web Api With Mvc 6 | Dotnetcurry
    Web Api Là Gì? Tài Liệu Web Api Tiếng Việt
    Web Api Là Gì? Tài Liệu Web Api Tiếng Việt
    Web Api Crud Operations And Consume Service In Asp.Net Mvc Application
    Web Api Crud Operations And Consume Service In Asp.Net Mvc Application
    Mvc Vs Asp.Net Web Api? - Youtube
    Mvc Vs Asp.Net Web Api? - Youtube
    Creating An Asp.Net Mvc 4 Restful Api For A Sql Stored Procedure - Deep In  The Code
    Creating An Asp.Net Mvc 4 Restful Api For A Sql Stored Procedure - Deep In The Code
    Developer Points: The Lifecycle Of An Asp.Net Web Api
    Developer Points: The Lifecycle Of An Asp.Net Web Api
    Difference Between Asp.Net Mvc And Asp.Net Web Api
    Difference Between Asp.Net Mvc And Asp.Net Web Api
    Build Asp.Net Core Mvc App To Consume Webapi In One Lecture - Part 2 -  Youtube
    Build Asp.Net Core Mvc App To Consume Webapi In One Lecture - Part 2 - Youtube
    Nghiên Cứu Web Api Với Asp.Net Mvc4
    Nghiên Cứu Web Api Với Asp.Net Mvc4
    Create Asp Net Mvc Web Api, Rest Api, Json By Rezaulkhan111 | Fiverr
    Create Asp Net Mvc Web Api, Rest Api, Json By Rezaulkhan111 | Fiverr
    Web Api #1 - What Is A Web Api?
    Web Api #1 - What Is A Web Api?
    Asp.Net Mvc - Web Api
    Asp.Net Mvc - Web Api
    Difference Between Asp.Net Mvc And Asp.Net Web Api – Exposing Functionality  Of Web Application | Brainvire.Com
    Difference Between Asp.Net Mvc And Asp.Net Web Api – Exposing Functionality Of Web Application | Brainvire.Com
    Filter Pipeline In Web Api Part 1 | Asp.Net Core 5 Web Api - Ep 4 | Rest Api  | Mvc Filters - Youtube
    Filter Pipeline In Web Api Part 1 | Asp.Net Core 5 Web Api - Ep 4 | Rest Api | Mvc Filters - Youtube
    Get Data In Asp.Net Mvc Using Web Api
    Get Data In Asp.Net Mvc Using Web Api
    Can I Have Asp.Net Core Mvc And Web Api As Single Project - Microsoft Q&A
    Can I Have Asp.Net Core Mvc And Web Api As Single Project - Microsoft Q&A

    See more here: kientrucannam.vn

    Trả lời

    Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *