Skip to content

Commit 3c483c5

Browse files
committed
add OpenAPI example (no swagger)
1 parent 0232419 commit 3c483c5

19 files changed

+498
-0
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using Microsoft.EntityFrameworkCore;
3+
using TodoApi.Models;
4+
5+
namespace TodoApi.Controllers;
6+
7+
[Route("api/[controller]")]
8+
[ApiController]
9+
public class TodoItemsController : ControllerBase
10+
{
11+
private readonly TodoContext _context;
12+
13+
public TodoItemsController(TodoContext context)
14+
{
15+
_context = context;
16+
}
17+
18+
// GET: api/TodoItems
19+
[HttpGet]
20+
public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
21+
{
22+
return await _context.TodoItems.ToListAsync();
23+
}
24+
25+
// GET: api/TodoItems/5
26+
// <snippet_GetByID>
27+
[HttpGet("{id}")]
28+
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
29+
{
30+
var todoItem = await _context.TodoItems.FindAsync(id);
31+
32+
if (todoItem == null)
33+
{
34+
return NotFound();
35+
}
36+
37+
return todoItem;
38+
}
39+
// </snippet_GetByID>
40+
41+
// PUT: api/TodoItems/5
42+
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
43+
// <snippet_Update>
44+
[HttpPut("{id}")]
45+
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
46+
{
47+
if (id != todoItem.Id)
48+
{
49+
return BadRequest();
50+
}
51+
52+
_context.Entry(todoItem).State = EntityState.Modified;
53+
54+
try
55+
{
56+
await _context.SaveChangesAsync();
57+
}
58+
catch (DbUpdateConcurrencyException)
59+
{
60+
if (!TodoItemExists(id))
61+
{
62+
return NotFound();
63+
}
64+
else
65+
{
66+
throw;
67+
}
68+
}
69+
70+
return NoContent();
71+
}
72+
// </snippet_Update>
73+
74+
// POST: api/TodoItems
75+
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
76+
// <snippet_Create>
77+
[HttpPost]
78+
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
79+
{
80+
_context.TodoItems.Add(todoItem);
81+
await _context.SaveChangesAsync();
82+
83+
// return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
84+
return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
85+
}
86+
// </snippet_Create>
87+
88+
// DELETE: api/TodoItems/5
89+
[HttpDelete("{id}")]
90+
public async Task<IActionResult> DeleteTodoItem(long id)
91+
{
92+
var todoItem = await _context.TodoItems.FindAsync(id);
93+
if (todoItem == null)
94+
{
95+
return NotFound();
96+
}
97+
98+
_context.TodoItems.Remove(todoItem);
99+
await _context.SaveChangesAsync();
100+
101+
return NoContent();
102+
}
103+
104+
private bool TodoItemExists(long id)
105+
{
106+
return _context.TodoItems.Any(e => e.Id == id);
107+
}
108+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
3+
namespace TodoApi.Controllers;
4+
5+
[ApiController]
6+
[Route("[controller]")]
7+
public class WeatherForecastController : ControllerBase
8+
{
9+
private static readonly string[] Summaries = new[]
10+
{
11+
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
12+
};
13+
14+
private readonly ILogger<WeatherForecastController> _logger;
15+
16+
public WeatherForecastController(ILogger<WeatherForecastController> logger)
17+
{
18+
_logger = logger;
19+
}
20+
21+
[HttpGet(Name = "GetWeatherForecast")]
22+
public IEnumerable<WeatherForecast> Get()
23+
{
24+
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
25+
{
26+
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
27+
TemperatureC = Random.Shared.Next(-20, 55),
28+
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
29+
})
30+
.ToArray();
31+
}
32+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Microsoft.EntityFrameworkCore;
2+
3+
namespace TodoApi.Models;
4+
5+
public class TodoContext : DbContext
6+
{
7+
public TodoContext(DbContextOptions<TodoContext> options)
8+
: base(options)
9+
{
10+
}
11+
12+
public DbSet<TodoItem> TodoItems { get; set; } = null!;
13+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace TodoApi.Models;
2+
3+
public class TodoItem
4+
{
5+
public long Id { get; set; }
6+
public string? Name { get; set; }
7+
public bool IsComplete { get; set; }
8+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using Microsoft.EntityFrameworkCore;
2+
using TodoApi.Models;
3+
4+
var builder = WebApplication.CreateBuilder(args);
5+
6+
builder.Services.AddOpenApi();
7+
builder.Services.AddControllers();
8+
builder.Services.AddDbContext<TodoContext>(opt =>
9+
opt.UseInMemoryDatabase("TodoList"));
10+
builder.Services.AddEndpointsApiExplorer();
11+
12+
var app = builder.Build();
13+
14+
if (app.Environment.IsDevelopment())
15+
{
16+
app.MapOpenApi();
17+
}
18+
19+
app.UseHttpsRedirection();
20+
21+
app.UseAuthorization();
22+
23+
app.MapControllers();
24+
25+
app.Run();
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
11+
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.0" />
12+
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
13+
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0">
14+
<PrivateAssets>all</PrivateAssets>
15+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
16+
</PackageReference>
17+
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" />
18+
</ItemGroup>
19+
20+
</Project>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace TodoApi;
2+
3+
public class WeatherForecast
4+
{
5+
public DateOnly Date { get; set; }
6+
7+
public int TemperatureC { get; set; }
8+
9+
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
10+
11+
public string? Summary { get; set; }
12+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
}
8+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
},
8+
"AllowedHosts": "*"
9+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using Microsoft.EntityFrameworkCore;
3+
using TodoApi.Models;
4+
5+
namespace TodoApi.Controllers;
6+
7+
[Route("api/[controller]")]
8+
[ApiController]
9+
public class TodoItemsController : ControllerBase
10+
{
11+
private readonly TodoContext _context;
12+
13+
public TodoItemsController(TodoContext context)
14+
{
15+
_context = context;
16+
}
17+
18+
// GET: api/TodoItems
19+
[HttpGet]
20+
public async Task<ActionResult<IEnumerable<TodoItemDTO>>> GetTodoItems()
21+
{
22+
return await _context.TodoItems
23+
.Select(x => ItemToDTO(x))
24+
.ToListAsync();
25+
}
26+
27+
// GET: api/TodoItems/5
28+
// <snippet_GetByID>
29+
[HttpGet("{id}")]
30+
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
31+
{
32+
var todoItem = await _context.TodoItems.FindAsync(id);
33+
34+
if (todoItem == null)
35+
{
36+
return NotFound();
37+
}
38+
39+
return ItemToDTO(todoItem);
40+
}
41+
// </snippet_GetByID>
42+
43+
// PUT: api/TodoItems/5
44+
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
45+
// <snippet_Update>
46+
[HttpPut("{id}")]
47+
public async Task<IActionResult> PutTodoItem(long id, TodoItemDTO todoDTO)
48+
{
49+
if (id != todoDTO.Id)
50+
{
51+
return BadRequest();
52+
}
53+
54+
var todoItem = await _context.TodoItems.FindAsync(id);
55+
if (todoItem == null)
56+
{
57+
return NotFound();
58+
}
59+
60+
todoItem.Name = todoDTO.Name;
61+
todoItem.IsComplete = todoDTO.IsComplete;
62+
63+
try
64+
{
65+
await _context.SaveChangesAsync();
66+
}
67+
catch (DbUpdateConcurrencyException) when (!TodoItemExists(id))
68+
{
69+
return NotFound();
70+
}
71+
72+
return NoContent();
73+
}
74+
// </snippet_Update>
75+
76+
// POST: api/TodoItems
77+
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
78+
// <snippet_Create>
79+
[HttpPost]
80+
public async Task<ActionResult<TodoItemDTO>> PostTodoItem(TodoItemDTO todoDTO)
81+
{
82+
var todoItem = new TodoItem
83+
{
84+
IsComplete = todoDTO.IsComplete,
85+
Name = todoDTO.Name
86+
};
87+
88+
_context.TodoItems.Add(todoItem);
89+
await _context.SaveChangesAsync();
90+
91+
return CreatedAtAction(
92+
nameof(GetTodoItem),
93+
new { id = todoItem.Id },
94+
ItemToDTO(todoItem));
95+
}
96+
// </snippet_Create>
97+
98+
// DELETE: api/TodoItems/5
99+
[HttpDelete("{id}")]
100+
public async Task<IActionResult> DeleteTodoItem(long id)
101+
{
102+
var todoItem = await _context.TodoItems.FindAsync(id);
103+
if (todoItem == null)
104+
{
105+
return NotFound();
106+
}
107+
108+
_context.TodoItems.Remove(todoItem);
109+
await _context.SaveChangesAsync();
110+
111+
return NoContent();
112+
}
113+
114+
private bool TodoItemExists(long id)
115+
{
116+
return _context.TodoItems.Any(e => e.Id == id);
117+
}
118+
119+
private static TodoItemDTO ItemToDTO(TodoItem todoItem) =>
120+
new TodoItemDTO
121+
{
122+
Id = todoItem.Id,
123+
Name = todoItem.Name,
124+
IsComplete = todoItem.IsComplete
125+
};
126+
}

0 commit comments

Comments
 (0)