diff --git a/mvc/action-return-types/7.x/WebApiSample/Controllers/ActionResultOfTProductsController.cs b/mvc/action-return-types/7.x/WebApiSample/Controllers/ActionResultOfTProductsController.cs new file mode 100644 index 00000000..0216d54d --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/Controllers/ActionResultOfTProductsController.cs @@ -0,0 +1,47 @@ +namespace WebApiSample.Controllers; + +using System.Net.Mime; +using Microsoft.AspNetCore.Mvc; +using WebApiSample.Models; + +[ApiController] +[Route("products/actionresultoft")] +public class ActionResultOfTProductsController : ControllerBase +{ + private readonly ProductContext _productContext; + + public ActionResultOfTProductsController(ProductContext productContext) + { + _productContext = productContext; + } + + // + [HttpGet("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public ActionResult GetById_ActionResultOfT(int id) + { + var product = _productContext.Products.Find(id); + return product == null ? NotFound() : product; + } + // + + // + [HttpPost()] + [Consumes(MediaTypeNames.Application.Json)] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> CreateAsync_ActionResultOfT(Product product) + { + if (product.Description.Contains("XYZ Widget")) + { + return BadRequest(); + } + + _productContext.Products.Add(product); + await _productContext.SaveChangesAsync(); + + return CreatedAtAction(nameof(GetById_ActionResultOfT), new { id = product.Id }, product); + } + // +} diff --git a/mvc/action-return-types/7.x/WebApiSample/Controllers/ActionResultProductsController.cs b/mvc/action-return-types/7.x/WebApiSample/Controllers/ActionResultProductsController.cs new file mode 100644 index 00000000..c3309139 --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/Controllers/ActionResultProductsController.cs @@ -0,0 +1,47 @@ +namespace WebApiSample.Controllers; + +using System.Net.Mime; +using Microsoft.AspNetCore.Mvc; +using WebApiSample.Models; + +[ApiController] +[Route("products/iactionresult")] +public class ActionResultProductsController : ControllerBase +{ + private readonly ProductContext _productContext; + + public ActionResultProductsController(ProductContext productContext) + { + _productContext = productContext; + } + + // + [HttpGet("{id}")] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Product))] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public IActionResult GetById_IActionResult(int id) + { + var product = _productContext.Products.Find(id); + return product == null ? NotFound() : Ok(product); + } + // + + // + [HttpPost()] + [Consumes(MediaTypeNames.Application.Json)] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync_IActionResult(Product product) + { + if (product.Description.Contains("XYZ Widget")) + { + return BadRequest(); + } + + _productContext.Products.Add(product); + await _productContext.SaveChangesAsync(); + + return CreatedAtAction(nameof(GetById_IActionResult), new { id = product.Id }, product); + } + // +} diff --git a/mvc/action-return-types/7.x/WebApiSample/Controllers/IResultProductsController.cs b/mvc/action-return-types/7.x/WebApiSample/Controllers/IResultProductsController.cs new file mode 100644 index 00000000..81423dac --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/Controllers/IResultProductsController.cs @@ -0,0 +1,48 @@ +namespace WebApiSample.Controllers; + +using System.Net.Mime; +using Microsoft.AspNetCore.Mvc; +using WebApiSample.Models; + +[ApiController] +[Route("products/iresult")] +public class IResultProductsController : ControllerBase +{ + private readonly ProductContext _productContext; + + public IResultProductsController(ProductContext productContext) + { + _productContext = productContext; + } + + // + [HttpGet("{id}")] + [ProducesResponseType(typeof(Product), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public IResult GetById(int id) + { + var product = _productContext.Products.Find(id); + return product == null ? Results.NotFound() : Results.Ok(product); + } + // + + // + [HttpPost] + [Consumes(MediaTypeNames.Application.Json)] + [ProducesResponseType(typeof(Product), StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(Product product) + { + if (product.Description.Contains("XYZ Widget")) + { + return Results.BadRequest(); + } + + _productContext.Products.Add(product); + await _productContext.SaveChangesAsync(); + + var location = Url.Action(nameof(GetById), new { id = product.Id }) ?? $"/{product.Id}"; + return Results.Created(location, product); + } + // +} diff --git a/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.cs b/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.cs new file mode 100644 index 00000000..f7c85850 --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.cs @@ -0,0 +1,55 @@ +namespace WebApiSample.Controllers; + +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using WebApiSample.Models; + +[ApiController] +[Route("[controller]")] +public partial class ProductsController : ControllerBase +{ + private readonly ProductContext _productContext; + + public ProductsController(ProductContext productContext) + { + _productContext = productContext; + } + + // + [HttpGet] + public Task> Get() => + _productContext.Products.OrderBy(p => p.Name).ToListAsync(); + // + + // + [HttpGet("syncsale")] + public IEnumerable GetOnSaleProducts() + { + var products = _productContext.Products.OrderBy(p => p.Name).ToList(); + + foreach (var product in products) + { + if (product.IsOnSale) + { + yield return product; + } + } + } + // + + // + [HttpGet("asyncsale")] + public async IAsyncEnumerable GetOnSaleProductsAsync() + { + var products = _productContext.Products.OrderBy(p => p.Name).AsAsyncEnumerable(); + + await foreach (var product in products) + { + if (product.IsOnSale) + { + yield return product; + } + } + } + // +} diff --git a/mvc/action-return-types/7.x/WebApiSample/Controllers/ResultsOfTProductsController.cs b/mvc/action-return-types/7.x/WebApiSample/Controllers/ResultsOfTProductsController.cs new file mode 100644 index 00000000..dd74f9b6 --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/Controllers/ResultsOfTProductsController.cs @@ -0,0 +1,43 @@ +namespace WebApiSample.Controllers; + +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using WebApiSample.Models; + +[ApiController] +[Route("products/resultsoft")] +public class ResultsOfTProductsController : ControllerBase +{ + private readonly ProductContext _productContext; + + public ResultsOfTProductsController(ProductContext productContext) + { + _productContext = productContext; + } + + // + [HttpGet("{id}")] + public Results> GetById(int id) + { + var product = _productContext.Products.Find(id); + return product == null ? TypedResults.NotFound() : TypedResults.Ok(product); + } + // + + // + [HttpPost] + public async Task>> CreateAsync(Product product) + { + if (product.Description.Contains("XYZ Widget")) + { + return TypedResults.BadRequest(); + } + + _productContext.Products.Add(product); + await _productContext.SaveChangesAsync(); + + var location = Url.Action(nameof(GetById), new { id = product.Id }) ?? $"/{product.Id}"; + return TypedResults.Created(location, product); + } + // +} diff --git a/mvc/action-return-types/7.x/WebApiSample/Models/Product.cs b/mvc/action-return-types/7.x/WebApiSample/Models/Product.cs new file mode 100644 index 00000000..23f599ed --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/Models/Product.cs @@ -0,0 +1,18 @@ +namespace WebApiSample.Models; + +using System.ComponentModel.DataAnnotations; + +// +public class Product +{ + public int Id { get; set; } + + [Required] + public string Name { get; set; } = string.Empty; + + [Required] + public string Description { get; set; } = string.Empty; + + public bool IsOnSale { get; set; } +} +// diff --git a/mvc/action-return-types/7.x/WebApiSample/ProductContext.cs b/mvc/action-return-types/7.x/WebApiSample/ProductContext.cs new file mode 100644 index 00000000..57f7a461 --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/ProductContext.cs @@ -0,0 +1,54 @@ +namespace WebApiSample; + +using Microsoft.EntityFrameworkCore; +using WebApiSample.Models; + +public class ProductContext : DbContext +{ + public ProductContext(DbContextOptions options) + : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().HasData( + new Product + { + Id = 1, + Name = "Learning ASP.NET Core", + Description = "A best-selling book covering the fundamentals of ASP.NET Core", + IsOnSale = true, + }, + new Product + { + Id = 2, + Name = "Learning EF Core", + Description = "A best-selling book covering the fundamentals of Entity Framework Core", + IsOnSale = true, + }, + new Product + { + Id = 3, + Name = "Learning .NET Standard", + Description = "A best-selling book covering the fundamentals of .NET Standard", + }, + new Product + { + Id = 4, + Name = "Learning .NET Core", + Description = "A best-selling book covering the fundamentals of .NET Core", + }, + new Product + { + Id = 5, + Name = "Learning C#", + Description = "A best-selling book covering the fundamentals of C#", + } + ); + + base.OnModelCreating(modelBuilder); + } + + public DbSet Products { get; set; } +} diff --git a/mvc/action-return-types/7.x/WebApiSample/Program.cs b/mvc/action-return-types/7.x/WebApiSample/Program.cs new file mode 100644 index 00000000..8304cfc7 --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/Program.cs @@ -0,0 +1,34 @@ +using WebApiSample; +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +builder.Services.AddDbContext(opt => + opt.UseInMemoryDatabase("ProductInventory")); + +builder.Services.AddControllers(); + +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +using (var scope = app.Services.CreateScope()) +{ + var services = scope.ServiceProvider; + + var context = services.GetRequiredService(); + context.Database.EnsureCreated(); +} + +app.MapControllers(); +app.Run(); diff --git a/mvc/action-return-types/7.x/WebApiSample/WebApiSample.csproj b/mvc/action-return-types/7.x/WebApiSample/WebApiSample.csproj new file mode 100644 index 00000000..ac88cb9a --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/WebApiSample.csproj @@ -0,0 +1,15 @@ + + + + net7.0 + enable + enable + + + + + + + + + diff --git a/mvc/action-return-types/7.x/WebApiSample/appsettings.Development.json b/mvc/action-return-types/7.x/WebApiSample/appsettings.Development.json new file mode 100644 index 00000000..0c208ae9 --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/mvc/action-return-types/7.x/WebApiSample/appsettings.json b/mvc/action-return-types/7.x/WebApiSample/appsettings.json new file mode 100644 index 00000000..10f68b8c --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +}