Asp Net Web Api Basico
Asp Net Web Api Basico
1&tabs=visual-studio
At the end, you have a web API that can manage "to-do" items stored in a database.
Overview
This tutorial creates the following API:
Prerequisites
Visual Studio
Visual Studio Code
Visual Studio for Mac
Visual Studio 2019 16.4 or later with the ASP.NET and web development workload
.NET Core 3.1 SDK or later
Create a web project
Visual Studio
Visual Studio Code
Visual Studio for Mac
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.
The project template creates a WeatherForecast API. Call the Get method from a browser to test the
app.
Visual Studio
Visual Studio Code
Visual Studio for Mac
Press Ctrl+F5 to run the app. Visual Studio launches a browser and navigates
to https://localhost:<port>/WeatherForecast , where <port> 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.
JSONCopy
[
{
"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"
}
]
Visual Studio
Visual Studio Code
Visual Studio for Mac
C#Copy
public class TodoItem
{
public long Id { get; set; }
public string Name { get; set; }
public bool IsComplete { get; set; }
}
Model classes can go anywhere in the project, but the Models folder is used by convention.
Visual Studio
Visual Studio Code / Visual Studio for Mac
From the Tools menu, select NuGet Package Manager > Manage NuGet Packages for
Solution.
Select the Browse tab, and then enter Microsoft.EntityFrameworkCore.SqlServer in the
search box.
Select Microsoft.EntityFrameworkCore.SqlServer in the left pane.
Select the Project check box in the right pane and then select Install.
Use the preceding instructions to add the Microsoft.EntityFrameworkCore.InMemory NuGet
package.
Add the TodoContext database context
Right-click the Models folder and select Add > Class. Name the class TodoContext and
click Add.
C#Copy
using Microsoft.EntityFrameworkCore;
namespace TodoApi.Models
{
public class TodoContext : DbContext
{
public TodoContext(DbContextOptions<TodoContext> options)
: base(options)
{
}
C#Copy
// 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;
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
Removes unused using declarations.
Adds the database context to the DI container.
Specifies that the database context will use an in-memory database.
Scaffold a controller
Visual Studio
Visual Studio Code / Visual Studio for Mac
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:
o Select TodoItem (TodoApi.Models) in the Model class.
o Select TodoContext (TodoApi.Models) in the Data context class.
o Select Add.
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.
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.
C#Copy
// POST: api/TodoItems
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
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.
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 Postman
Install Postman
Start the web app.
Start Postman.
Disable SSL certificate verification
o From File > Settings (General tab), disable SSL certificate verification.
Warning
JSONCopy
{
"name":"walk dog",
"isComplete":true
}
Select Send.
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
JSONCopy
[
{
"id": 1,
"name": "Item1",
"isComplete": false
}
]
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.
C#Copy
[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
{
private readonly TodoContext _context;
C#Copy
// GET: api/TodoItems/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return todoItem;
}
Return values
The return type of the GetTodoItems and GetTodoItem methods is ActionResult<T> 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.
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.
C#Copy
// PUT: api/TodoItems/5
[HttpPut("{id}")]
public async Task<IActionResult> 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.
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":
JSONCopy
{
"Id":1,
"name":"feed fish",
"isComplete":true
}
C#Copy
// DELETE: api/TodoItems/5
[HttpDelete("{id}")]
public async Task<ActionResult<TodoItem>> DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();
return todoItem;
}
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.
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.
C#Copy
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.
C#Copy
public class TodoItemDTO
{
public long Id { get; set; }
public string Name { get; set; }
public bool IsComplete { get; set; }
}
C#Copy
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItemDTO>>> GetTodoItems()
{
return await _context.TodoItems
.Select(x => ItemToDTO(x))
.ToListAsync();
}
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return ItemToDTO(todoItem);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateTodoItem(long id, TodoItemDTO todoItemDTO)
{
if (id != todoItemDTO.Id)
{
return BadRequest();
}
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<ActionResult<TodoItemDTO>> 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<IActionResult> DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();
return NoContent();
}
IdentityServer4 is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core. IdentityServer4
enables the following security features: