diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Message.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Message.cs new file mode 100644 index 000000000000..b352fffdee18 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Message.cs @@ -0,0 +1,8 @@ +public class Message +{ + public Message() + { + } + + public string Text { get; set; } +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Program.cs new file mode 100644 index 000000000000..0cd1540ced1f --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Program.cs @@ -0,0 +1,205 @@ +#define FINAL // MINIMAL FINAL WITHPATCH TYPEDR +#if MINIMAL +// +var builder = WebApplication.CreateBuilder(args); +var app = builder.Build(); + +app.MapGet("/", () => "Hello World!"); + +app.Run(); +// +#elif FINAL +// +using Microsoft.EntityFrameworkCore; + +// +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); +var app = builder.Build(); +// + +// +app.MapGet("/todoitems", async (TodoDb db) => + await db.Todos.ToListAsync()); + +app.MapGet("/todoitems/complete", async (TodoDb db) => + await db.Todos.Where(t => t.IsComplete).ToListAsync()); + +// +app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? Results.Ok(todo) + : Results.NotFound()); +// +// + +// +app.MapPost("/todoitems", async (Todo todo, TodoDb db) => +{ + db.Todos.Add(todo); + await db.SaveChangesAsync(); + + return Results.Created($"/todoitems/{todo.Id}", todo); +}); +// + +// +app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + todo.Name = inputTodo.Name; + todo.IsComplete = inputTodo.IsComplete; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); +// + +// +app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) => +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return Results.NoContent(); + } + + return Results.NotFound(); +}); +// + +app.Run(); +// +#elif WITHPATCH +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); +var app = builder.Build(); + +app.MapGet("/todoitems", async (TodoDb db) => + await db.Todos.ToListAsync()); + +app.MapGet("/todoitems/complete", async (TodoDb db) => + await db.Todos.Where(t => t.IsComplete).ToListAsync()); + +app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? Results.Ok(todo) + : Results.NotFound()); + +app.MapPost("/todoitems", async (Todo todo, TodoDb db) => +{ + db.Todos.Add(todo); + await db.SaveChangesAsync(); + + return Results.Created($"/todoitems/{todo.Id}", todo); +}); + +app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + todo.Name = inputTodo.Name; + todo.IsComplete = inputTodo.IsComplete; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); + +// +app.MapPatch("/todoitems/{id}", async (int id, TodoPatchDto inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + if (inputTodo.Name is not null) todo.Name = inputTodo.Name; + if (inputTodo.IsComplete is not null) todo.IsComplete = inputTodo.IsComplete.Value; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); +// + +app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) => +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return Results.NoContent(); + } + + return Results.NotFound(); +}); + +app.Run(); +#elif TYPEDR +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); +var app = builder.Build(); + +app.MapGet("/todoitems", async (TodoDb db) => + await db.Todos.ToListAsync()); + +app.MapGet("/todoitems/complete", async (TodoDb db) => + await db.Todos.Where(t => t.IsComplete).ToListAsync()); + +// +app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? Results.Ok(todo) + : Results.NotFound()); +// + +/* +// + app.MapGet("/todoitems/{id}", async Task, NotFound>> (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? TypedResults.Ok(todo) + : TypedResults.NotFound()); +// +*/ + +/* +// +app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? TypedResults.Ok(todo) + : TypedResults.NotFound()); +// +*/ + +// +app.MapGet("/hello", () => Results.Ok(new Message() { Text = "Hello World!" })) + .Produces(); +// + +// +app.MapGet("/hello2", () => TypedResults.Ok(new Message() { Text = "Hello World!" })); +// + +app.Run(); +#endif + diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Todo.cs new file mode 100644 index 000000000000..2900a835b043 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Todo.cs @@ -0,0 +1,6 @@ +class Todo +{ + public int Id { get; set; } + public string? Name { get; set; } + public bool IsComplete { get; set; } +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi.csproj new file mode 100644 index 000000000000..abc9f7648bf9 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi.csproj @@ -0,0 +1,14 @@ + + + + net9.0 + enable + enable + + + + + + + + diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoDb.cs new file mode 100644 index 000000000000..c1584b807819 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoDb.cs @@ -0,0 +1,9 @@ +using Microsoft.EntityFrameworkCore; + +class TodoDb : DbContext +{ + public TodoDb(DbContextOptions options) + : base(options) { } + + public DbSet Todos => Set(); +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoPatchDto.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoPatchDto.cs new file mode 100644 index 000000000000..ab225cf2280b --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoPatchDto.cs @@ -0,0 +1,5 @@ +public class TodoPatchDto +{ + public string? Name { get; set; } + public bool? IsComplete { get; set; } +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/Program.cs new file mode 100644 index 000000000000..861c355b7387 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/Program.cs @@ -0,0 +1,84 @@ +// +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); +var app = builder.Build(); + +// +RouteGroupBuilder todoItems = app.MapGroup("/todoitems"); + +todoItems.MapGet("/", GetAllTodos); +todoItems.MapGet("/complete", GetCompleteTodos); +todoItems.MapGet("/{id}", GetTodo); +todoItems.MapPost("/", CreateTodo); +todoItems.MapPut("/{id}", UpdateTodo); +todoItems.MapDelete("/{id}", DeleteTodo); +// + +app.Run(); + +// +// +static async Task GetAllTodos(TodoDb db) +{ + return TypedResults.Ok(await db.Todos.Select(x => new TodoItemDTO(x)).ToArrayAsync()); +} +// + +static async Task GetCompleteTodos(TodoDb db) { + return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).Select(x => new TodoItemDTO(x)).ToListAsync()); +} + +static async Task GetTodo(int id, TodoDb db) +{ + return await db.Todos.FindAsync(id) + is Todo todo + ? TypedResults.Ok(new TodoItemDTO(todo)) + : TypedResults.NotFound(); +} + +static async Task CreateTodo(TodoItemDTO todoItemDTO, TodoDb db) +{ + var todoItem = new Todo + { + IsComplete = todoItemDTO.IsComplete, + Name = todoItemDTO.Name + }; + + db.Todos.Add(todoItem); + await db.SaveChangesAsync(); + + todoItemDTO = new TodoItemDTO(todoItem); + + return TypedResults.Created($"/todoitems/{todoItem.Id}", todoItemDTO); +} + +static async Task UpdateTodo(int id, TodoItemDTO todoItemDTO, TodoDb db) +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return TypedResults.NotFound(); + + todo.Name = todoItemDTO.Name; + todo.IsComplete = todoItemDTO.IsComplete; + + await db.SaveChangesAsync(); + + return TypedResults.NoContent(); +} + +static async Task DeleteTodo(int id, TodoDb db) +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return TypedResults.NoContent(); + } + + return TypedResults.NotFound(); +} +// +// diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/Todo.cs new file mode 100644 index 000000000000..d9ea203029c5 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/Todo.cs @@ -0,0 +1,7 @@ +public class Todo +{ + public int Id { get; set; } + public string? Name { get; set; } + public bool IsComplete { get; set; } + public string? Secret { get; set; } +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoApi.csproj new file mode 100644 index 000000000000..abc9f7648bf9 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoApi.csproj @@ -0,0 +1,14 @@ + + + + net9.0 + enable + enable + + + + + + + + diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoDb.cs new file mode 100644 index 000000000000..c1584b807819 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoDb.cs @@ -0,0 +1,9 @@ +using Microsoft.EntityFrameworkCore; + +class TodoDb : DbContext +{ + public TodoDb(DbContextOptions options) + : base(options) { } + + public DbSet Todos => Set(); +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoItemDTO.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoItemDTO.cs new file mode 100644 index 000000000000..76f99abe44bd --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoItemDTO.cs @@ -0,0 +1,10 @@ +public class TodoItemDTO +{ + public int Id { get; set; } + public string? Name { get; set; } + public bool IsComplete { get; set; } + + public TodoItemDTO() { } + public TodoItemDTO(Todo todoItem) => + (Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete); +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/Program.cs new file mode 100644 index 000000000000..aa53df894a24 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/Program.cs @@ -0,0 +1,105 @@ +// +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); + +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddOpenApiDocument(config => +{ + config.DocumentName = "TodoAPI"; + config.Title = "TodoAPI v1"; + config.Version = "v1"; +}); + +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.UseOpenApi(); + app.UseSwaggerUi(config => + { + config.DocumentTitle = "TodoAPI"; + config.Path = "/swagger"; + config.DocumentPath = "/swagger/{documentName}/swagger.json"; + config.DocExpansion = "list"; + }); +} + +// +RouteGroupBuilder todoItems = app.MapGroup("/todoitems"); + +todoItems.MapGet("/", GetAllTodos); +todoItems.MapGet("/complete", GetCompleteTodos); +todoItems.MapGet("/{id}", GetTodo); +todoItems.MapPost("/", CreateTodo); +todoItems.MapPut("/{id}", UpdateTodo); +todoItems.MapDelete("/{id}", DeleteTodo); +// + +app.Run(); + +// +// +static async Task GetAllTodos(TodoDb db) +{ + return TypedResults.Ok(await db.Todos.Select(x => new TodoItemDTO(x)).ToArrayAsync()); +} +// + +static async Task GetCompleteTodos(TodoDb db) { + return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).Select(x => new TodoItemDTO(x)).ToListAsync()); +} + +static async Task GetTodo(int id, TodoDb db) +{ + return await db.Todos.FindAsync(id) + is Todo todo + ? TypedResults.Ok(new TodoItemDTO(todo)) + : TypedResults.NotFound(); +} + +static async Task CreateTodo(TodoItemDTO todoItemDTO, TodoDb db) +{ + var todoItem = new Todo + { + IsComplete = todoItemDTO.IsComplete, + Name = todoItemDTO.Name + }; + + db.Todos.Add(todoItem); + await db.SaveChangesAsync(); + + todoItemDTO = new TodoItemDTO(todoItem); + + return TypedResults.Created($"/todoitems/{todoItem.Id}", todoItemDTO); +} + +static async Task UpdateTodo(int id, TodoItemDTO todoItemDTO, TodoDb db) +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return TypedResults.NotFound(); + + todo.Name = todoItemDTO.Name; + todo.IsComplete = todoItemDTO.IsComplete; + + await db.SaveChangesAsync(); + + return TypedResults.NoContent(); +} + +static async Task DeleteTodo(int id, TodoDb db) +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return TypedResults.NoContent(); + } + + return TypedResults.NotFound(); +} +// +// diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/Todo.cs new file mode 100644 index 000000000000..d9ea203029c5 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/Todo.cs @@ -0,0 +1,7 @@ +public class Todo +{ + public int Id { get; set; } + public string? Name { get; set; } + public bool IsComplete { get; set; } + public string? Secret { get; set; } +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoApi.csproj new file mode 100644 index 000000000000..067275c7128b --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoApi.csproj @@ -0,0 +1,15 @@ + + + + net8.0 + enable + enable + + + + + + + + + diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoDb.cs new file mode 100644 index 000000000000..c1584b807819 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoDb.cs @@ -0,0 +1,9 @@ +using Microsoft.EntityFrameworkCore; + +class TodoDb : DbContext +{ + public TodoDb(DbContextOptions options) + : base(options) { } + + public DbSet Todos => Set(); +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoItemDTO.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoItemDTO.cs new file mode 100644 index 000000000000..76f99abe44bd --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoItemDTO.cs @@ -0,0 +1,10 @@ +public class TodoItemDTO +{ + public int Id { get; set; } + public string? Name { get; set; } + public bool IsComplete { get; set; } + + public TodoItemDTO() { } + public TodoItemDTO(Todo todoItem) => + (Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete); +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/Program.cs new file mode 100644 index 000000000000..2a82ad8c9f76 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/Program.cs @@ -0,0 +1,60 @@ +// +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); +var app = builder.Build(); + +// +var todoItems = app.MapGroup("/todoitems"); + +todoItems.MapGet("/", async (TodoDb db) => + await db.Todos.ToListAsync()); + +todoItems.MapGet("/complete", async (TodoDb db) => + await db.Todos.Where(t => t.IsComplete).ToListAsync()); + +todoItems.MapGet("/{id}", async (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? Results.Ok(todo) + : Results.NotFound()); + +todoItems.MapPost("/", async (Todo todo, TodoDb db) => +{ + db.Todos.Add(todo); + await db.SaveChangesAsync(); + + return Results.Created($"/todoitems/{todo.Id}", todo); +}); + +todoItems.MapPut("/{id}", async (int id, Todo inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + todo.Name = inputTodo.Name; + todo.IsComplete = inputTodo.IsComplete; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); + +todoItems.MapDelete("/{id}", async (int id, TodoDb db) => +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return Results.NoContent(); + } + + return Results.NotFound(); +}); +// + +app.Run(); +// \ No newline at end of file diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/Todo.cs new file mode 100644 index 000000000000..986d0c7de8c4 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/Todo.cs @@ -0,0 +1,6 @@ +public class Todo +{ + public int Id { get; set; } + public string? Name { get; set; } + public bool IsComplete { get; set; } +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/TodoApi.csproj new file mode 100644 index 000000000000..abc9f7648bf9 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/TodoApi.csproj @@ -0,0 +1,14 @@ + + + + net9.0 + enable + enable + + + + + + + + diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/TodoDb.cs new file mode 100644 index 000000000000..c1584b807819 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/TodoDb.cs @@ -0,0 +1,9 @@ +using Microsoft.EntityFrameworkCore; + +class TodoDb : DbContext +{ + public TodoDb(DbContextOptions options) + : base(options) { } + + public DbSet Todos => Set(); +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Program.cs new file mode 100644 index 000000000000..3787cd75a0ce --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Program.cs @@ -0,0 +1,81 @@ +// +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); + +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddOpenApiDocument(config => +{ + config.DocumentName = "TodoAPI"; + config.Title = "TodoAPI v1"; + config.Version = "v1"; +}); + +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.UseOpenApi(); + app.UseSwaggerUi(config => + { + config.DocumentTitle = "TodoAPI"; + config.Path = "/swagger"; + config.DocumentPath = "/swagger/{documentName}/swagger.json"; + config.DocExpansion = "list"; + }); +} + +// +var todoItems = app.MapGroup("/todoitems"); + +todoItems.MapGet("/", async (TodoDb db) => + await db.Todos.ToListAsync()); + +todoItems.MapGet("/complete", async (TodoDb db) => + await db.Todos.Where(t => t.IsComplete).ToListAsync()); + +todoItems.MapGet("/{id}", async (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? Results.Ok(todo) + : Results.NotFound()); + +todoItems.MapPost("/", async (Todo todo, TodoDb db) => +{ + db.Todos.Add(todo); + await db.SaveChangesAsync(); + + return Results.Created($"/todoitems/{todo.Id}", todo); +}); + +todoItems.MapPut("/{id}", async (int id, Todo inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + todo.Name = inputTodo.Name; + todo.IsComplete = inputTodo.IsComplete; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); + +todoItems.MapDelete("/{id}", async (int id, TodoDb db) => +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return Results.NoContent(); + } + + return Results.NotFound(); +}); +// + +app.Run(); +// diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Todo.cs new file mode 100644 index 000000000000..986d0c7de8c4 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Todo.cs @@ -0,0 +1,6 @@ +public class Todo +{ + public int Id { get; set; } + public string? Name { get; set; } + public bool IsComplete { get; set; } +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/TodoApi.csproj new file mode 100644 index 000000000000..067275c7128b --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/TodoApi.csproj @@ -0,0 +1,15 @@ + + + + net8.0 + enable + enable + + + + + + + + + diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/TodoDb.cs new file mode 100644 index 000000000000..c1584b807819 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/TodoDb.cs @@ -0,0 +1,9 @@ +using Microsoft.EntityFrameworkCore; + +class TodoDb : DbContext +{ + public TodoDb(DbContextOptions options) + : base(options) { } + + public DbSet Todos => Set(); +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/Program.cs new file mode 100644 index 000000000000..591f97decb52 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/Program.cs @@ -0,0 +1,79 @@ +// +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); +var app = builder.Build(); + +// +var todoItems = app.MapGroup("/todoitems"); + +todoItems.MapGet("/", GetAllTodos); +todoItems.MapGet("/complete", GetCompleteTodos); +todoItems.MapGet("/{id}", GetTodo); +todoItems.MapPost("/", CreateTodo); +todoItems.MapPut("/{id}", UpdateTodo); +todoItems.MapDelete("/{id}", DeleteTodo); +// + +app.Run(); + +// +// +static async Task GetAllTodos(TodoDb db) +{ + return TypedResults.Ok(await db.Todos.ToArrayAsync()); +} +// + +static async Task GetCompleteTodos(TodoDb db) +{ + return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync()); +} + +// +static async Task GetTodo(int id, TodoDb db) +{ + return await db.Todos.FindAsync(id) + is Todo todo + ? TypedResults.Ok(todo) + : TypedResults.NotFound(); +} +// + +static async Task CreateTodo(Todo todo, TodoDb db) +{ + db.Todos.Add(todo); + await db.SaveChangesAsync(); + + return TypedResults.Created($"/todoitems/{todo.Id}", todo); +} + +static async Task UpdateTodo(int id, Todo inputTodo, TodoDb db) +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return TypedResults.NotFound(); + + todo.Name = inputTodo.Name; + todo.IsComplete = inputTodo.IsComplete; + + await db.SaveChangesAsync(); + + return TypedResults.NoContent(); +} + +static async Task DeleteTodo(int id, TodoDb db) +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return TypedResults.NoContent(); + } + + return TypedResults.NotFound(); +} +// +// diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/Todo.cs new file mode 100644 index 000000000000..2900a835b043 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/Todo.cs @@ -0,0 +1,6 @@ +class Todo +{ + public int Id { get; set; } + public string? Name { get; set; } + public bool IsComplete { get; set; } +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/TodoApi.csproj new file mode 100644 index 000000000000..abc9f7648bf9 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/TodoApi.csproj @@ -0,0 +1,14 @@ + + + + net9.0 + enable + enable + + + + + + + + diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/TodoDb.cs new file mode 100644 index 000000000000..c1584b807819 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/TodoDb.cs @@ -0,0 +1,9 @@ +using Microsoft.EntityFrameworkCore; + +class TodoDb : DbContext +{ + public TodoDb(DbContextOptions options) + : base(options) { } + + public DbSet Todos => Set(); +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Program.cs new file mode 100644 index 000000000000..522968205c21 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Program.cs @@ -0,0 +1,100 @@ +// +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); + +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddOpenApiDocument(config => +{ + config.DocumentName = "TodoAPI"; + config.Title = "TodoAPI v1"; + config.Version = "v1"; +}); + +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.UseOpenApi(); + app.UseSwaggerUi(config => + { + config.DocumentTitle = "TodoAPI"; + config.Path = "/swagger"; + config.DocumentPath = "/swagger/{documentName}/swagger.json"; + config.DocExpansion = "list"; + }); +} + +// +var todoItems = app.MapGroup("/todoitems"); + +todoItems.MapGet("/", GetAllTodos); +todoItems.MapGet("/complete", GetCompleteTodos); +todoItems.MapGet("/{id}", GetTodo); +todoItems.MapPost("/", CreateTodo); +todoItems.MapPut("/{id}", UpdateTodo); +todoItems.MapDelete("/{id}", DeleteTodo); +// + +app.Run(); + +// +// +static async Task GetAllTodos(TodoDb db) +{ + return TypedResults.Ok(await db.Todos.ToArrayAsync()); +} +// + +static async Task GetCompleteTodos(TodoDb db) +{ + return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync()); +} + +// +static async Task GetTodo(int id, TodoDb db) +{ + return await db.Todos.FindAsync(id) + is Todo todo + ? TypedResults.Ok(todo) + : TypedResults.NotFound(); +} +// + +static async Task CreateTodo(Todo todo, TodoDb db) +{ + db.Todos.Add(todo); + await db.SaveChangesAsync(); + + return TypedResults.Created($"/todoitems/{todo.Id}", todo); +} + +static async Task UpdateTodo(int id, Todo inputTodo, TodoDb db) +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return TypedResults.NotFound(); + + todo.Name = inputTodo.Name; + todo.IsComplete = inputTodo.IsComplete; + + await db.SaveChangesAsync(); + + return TypedResults.NoContent(); +} + +static async Task DeleteTodo(int id, TodoDb db) +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return TypedResults.NoContent(); + } + + return TypedResults.NotFound(); +} +// +// diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Todo.cs new file mode 100644 index 000000000000..2900a835b043 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Todo.cs @@ -0,0 +1,6 @@ +class Todo +{ + public int Id { get; set; } + public string? Name { get; set; } + public bool IsComplete { get; set; } +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/TodoApi.csproj new file mode 100644 index 000000000000..067275c7128b --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/TodoApi.csproj @@ -0,0 +1,15 @@ + + + + net8.0 + enable + enable + + + + + + + + + diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/TodoDb.cs new file mode 100644 index 000000000000..c1584b807819 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/TodoDb.cs @@ -0,0 +1,9 @@ +using Microsoft.EntityFrameworkCore; + +class TodoDb : DbContext +{ + public TodoDb(DbContextOptions options) + : base(options) { } + + public DbSet Todos => Set(); +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/Program.cs new file mode 100644 index 000000000000..b657be5cd7ad --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/Program.cs @@ -0,0 +1,149 @@ +#define FINAL // MINIMAL FINAL TYPEDR +#if MINIMAL +// +var builder = WebApplication.CreateBuilder(args); +var app = builder.Build(); + +app.MapGet("/", () => "Hello World!"); + +app.Run(); +// +#elif FINAL +// +// +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); + +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddOpenApiDocument(config => +{ + config.DocumentName = "TodoAPI"; + config.Title = "TodoAPI v1"; + config.Version = "v1"; +}); +// +var app = builder.Build(); +// +if (app.Environment.IsDevelopment()) +{ + app.UseOpenApi(); + app.UseSwaggerUi(config => + { + config.DocumentTitle = "TodoAPI"; + config.Path = "/swagger"; + config.DocumentPath = "/swagger/{documentName}/swagger.json"; + config.DocExpansion = "list"; + }); +} +// +// +app.MapGet("/todoitems", async (TodoDb db) => + await db.Todos.ToListAsync()); + +app.MapGet("/todoitems/complete", async (TodoDb db) => + await db.Todos.Where(t => t.IsComplete).ToListAsync()); + +// +app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? Results.Ok(todo) + : Results.NotFound()); +// +// + +// +app.MapPost("/todoitems", async (Todo todo, TodoDb db) => +{ + db.Todos.Add(todo); + await db.SaveChangesAsync(); + + return Results.Created($"/todoitems/{todo.Id}", todo); +}); +// + +// +app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + todo.Name = inputTodo.Name; + todo.IsComplete = inputTodo.IsComplete; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); +// + +// +app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) => +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return Results.NoContent(); + } + + return Results.NotFound(); +}); +// + +app.Run(); +// +#elif TYPEDR +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); +var app = builder.Build(); + +app.MapGet("/todoitems", async (TodoDb db) => + await db.Todos.ToListAsync()); + +app.MapGet("/todoitems/complete", async (TodoDb db) => + await db.Todos.Where(t => t.IsComplete).ToListAsync()); + +app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? Results.Ok(todo) + : Results.NotFound()); + +// + app.MapGet("/todos/{id}", async Task, NotFound>> (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? TypedResults.Ok(todo) + : TypedResults.NotFound()); +// + +/* +// +app.MapGet("/todos/{id}", async (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? TypedResults.Ok(todo) + : TypedResults.NotFound()); +// +*/ + +// +app.MapGet("/hello", () => Results.Ok(new Message() { Text = "Hello World!" })) + .Produces(); +// + +// +app.MapGet("/hello2", () => TypedResults.Ok(new Message() { Text = "Hello World!" })); +// + +app.Run(); +#endif \ No newline at end of file diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/Todo.cs new file mode 100644 index 000000000000..86aba6a37cee --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/Todo.cs @@ -0,0 +1,6 @@ +public class Todo +{ + public int Id { get; set; } + public string? Name { get; set; } + public bool IsComplete { get; set; } +} \ No newline at end of file diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/TodoApi.csproj new file mode 100644 index 000000000000..067275c7128b --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/TodoApi.csproj @@ -0,0 +1,15 @@ + + + + net8.0 + enable + enable + + + + + + + + + diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/TodoDb.cs new file mode 100644 index 000000000000..d202ecad4cc8 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/TodoDb.cs @@ -0,0 +1,9 @@ +using Microsoft.EntityFrameworkCore; + +class TodoDb : DbContext +{ + public TodoDb(DbContextOptions options) + : base(options) { } + + public DbSet Todos => Set(); +} \ No newline at end of file