From e5ae9c8d0420c72e272970c0bad4c8b86cf48849 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 29 Sep 2022 15:40:30 -0700 Subject: [PATCH 1/2] New Sample project --- .../ProductsController.ActionResultOfT.cs | 43 ++++++++++++ .../ProductsController.IActionResult.cs | 43 ++++++++++++ .../Controllers/ProductsController.IResult.cs | 44 ++++++++++++ .../ProductsController.ResultsOfT.cs | 39 +++++++++++ .../Controllers/ProductsController.cs | 55 +++++++++++++++ .../7.x/WebApiSample/Models/Product.cs | 18 +++++ .../7.x/WebApiSample/ProductContext.cs | 14 ++++ .../7.x/WebApiSample/Program.cs | 28 ++++++++ .../Repositories/ProductsRepository.cs | 67 +++++++++++++++++++ .../7.x/WebApiSample/WebApiSample.csproj | 15 +++++ .../WebApiSample/appsettings.Development.json | 8 +++ .../7.x/WebApiSample/appsettings.json | 9 +++ 12 files changed, 383 insertions(+) create mode 100644 mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.ActionResultOfT.cs create mode 100644 mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.IActionResult.cs create mode 100644 mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.IResult.cs create mode 100644 mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.ResultsOfT.cs create mode 100644 mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.cs create mode 100644 mvc/action-return-types/7.x/WebApiSample/Models/Product.cs create mode 100644 mvc/action-return-types/7.x/WebApiSample/ProductContext.cs create mode 100644 mvc/action-return-types/7.x/WebApiSample/Program.cs create mode 100644 mvc/action-return-types/7.x/WebApiSample/Repositories/ProductsRepository.cs create mode 100644 mvc/action-return-types/7.x/WebApiSample/WebApiSample.csproj create mode 100644 mvc/action-return-types/7.x/WebApiSample/appsettings.Development.json create mode 100644 mvc/action-return-types/7.x/WebApiSample/appsettings.json diff --git a/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.ActionResultOfT.cs b/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.ActionResultOfT.cs new file mode 100644 index 00000000..4c8fe227 --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.ActionResultOfT.cs @@ -0,0 +1,43 @@ +namespace WebApiSample.Controllers; + +using System.Net.Mime; +using Microsoft.AspNetCore.Mvc; +using WebApiSample.Models; + +public partial class ProductsController : ControllerBase +{ +#if ActionResultOfT + // + [HttpGet("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public ActionResult GetById(int id) + { + if (!_repository.TryGetProduct(id, out var product)) + { + return NotFound(); + } + + return product; + } + // + + // + [HttpPost] + [Consumes(MediaTypeNames.Application.Json)] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task> CreateAsync(Product product) + { + if (product.Description.Contains("XYZ Widget")) + { + return BadRequest(); + } + + await _repository.AddProductAsync(product); + + return CreatedAtAction(nameof(GetById), new { id = product.Id }, product); + } + // +#endif +} diff --git a/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.IActionResult.cs b/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.IActionResult.cs new file mode 100644 index 00000000..a0a6421f --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.IActionResult.cs @@ -0,0 +1,43 @@ +namespace WebApiSample.Controllers; + +using System.Net.Mime; +using Microsoft.AspNetCore.Mvc; +using WebApiSample.Models; + +public partial class ProductsController : ControllerBase +{ +#if IActionResult + // + [HttpGet("{id}")] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Product))] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public IActionResult GetById(int id) + { + if (!_repository.TryGetProduct(id, out var product)) + { + return NotFound(); + } + + return Ok(product); + } + // + + // + [HttpPost] + [Consumes(MediaTypeNames.Application.Json)] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateAsync(Product product) + { + if (product.Description.Contains("XYZ Widget")) + { + return BadRequest(); + } + + await _repository.AddProductAsync(product); + + return CreatedAtAction(nameof(GetById), new { id = product.Id }, product); + } + // +#endif +} diff --git a/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.IResult.cs b/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.IResult.cs new file mode 100644 index 00000000..9cd5df28 --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.IResult.cs @@ -0,0 +1,44 @@ +namespace WebApiSample.Controllers; + +using System.Net.Mime; +using Microsoft.AspNetCore.Mvc; +using WebApiSample.Models; + +public partial class ProductsController : ControllerBase +{ +#if IResult + // + [HttpGet("{id}")] + [ProducesResponseType(typeof(Product), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public IResult GetById(int id) + { + if (!_repository.TryGetProduct(id, out var product)) + { + return Results.NotFound(); + } + + return 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(); + } + + await _repository.AddProductAsync(product); + + var location = Url.Action(nameof(GetById), new { id = product.Id }) ?? $"/{product.Id}"; + return Results.Created(location, product); + } + // +#endif +} diff --git a/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.ResultsOfT.cs b/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.ResultsOfT.cs new file mode 100644 index 00000000..759fc226 --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.ResultsOfT.cs @@ -0,0 +1,39 @@ +namespace WebApiSample.Controllers; + +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using WebApiSample.Models; + +public partial class ProductsController : ControllerBase +{ +#if ResultsOfT + // + [HttpGet("{id}")] + public Results> GetById(int id) + { + if (!_repository.TryGetProduct(id, out var product)) + { + return TypedResults.NotFound(); + } + + return TypedResults.Ok(product); + } + // + + // + [HttpPost] + public async Task>> CreateAsync(Product product) + { + if (product.Description.Contains("XYZ Widget")) + { + return TypedResults.BadRequest(); + } + + await _repository.AddProductAsync(product); + + var location = Url.Action(nameof(GetById), new { id = product.Id }) ?? $"/{product.Id}"; + return TypedResults.Created(location, product); + } + // +#endif +} 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..b9170d7b --- /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 WebApiSample.Models; +using WebApiSample.Repositories; + +[ApiController] +[Route("[controller]")] +public partial class ProductsController : ControllerBase +{ + private readonly ProductsRepository _repository; + + public ProductsController(ProductsRepository repository) + { + _repository = repository; + } + + // + [HttpGet] + public List Get() => + _repository.GetProducts(); + // + + // + [HttpGet("syncsale")] + public IEnumerable GetOnSaleProducts() + { + var products = _repository.GetProducts(); + + foreach (var product in products) + { + if (product.IsOnSale) + { + yield return product; + } + } + } + // + + // + [HttpGet("asyncsale")] + public async IAsyncEnumerable GetOnSaleProductsAsync() + { + var products = _repository.GetProductsAsync(); + + await foreach (var product in products) + { + if (product.IsOnSale) + { + yield return 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..187e0e63 --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/ProductContext.cs @@ -0,0 +1,14 @@ +namespace WebApiSample; + +using Microsoft.EntityFrameworkCore; +using WebApiSample.Models; + +public class ProductContext : DbContext +{ + public ProductContext(DbContextOptions options) + : base(options) + { + } + + 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..2eca7716 --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/Program.cs @@ -0,0 +1,28 @@ +using WebApiSample.Repositories; +using WebApiSample; +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +builder.Services.AddScoped(); +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(); +} + +app.MapControllers(); +app.Run(); diff --git a/mvc/action-return-types/7.x/WebApiSample/Repositories/ProductsRepository.cs b/mvc/action-return-types/7.x/WebApiSample/Repositories/ProductsRepository.cs new file mode 100644 index 00000000..54502c79 --- /dev/null +++ b/mvc/action-return-types/7.x/WebApiSample/Repositories/ProductsRepository.cs @@ -0,0 +1,67 @@ +namespace WebApiSample.Repositories; + +using Microsoft.EntityFrameworkCore; +using WebApiSample.Models; + +public class ProductsRepository +{ + private readonly ProductContext _context; + + public ProductsRepository(ProductContext context) + { + _context = context; + + if (_context.Products.Count() == 0) + { + _context.Products.AddRange( + new Product + { + Name = "Learning ASP.NET Core", + Description = "A best-selling book covering the fundamentals of ASP.NET Core", + IsOnSale = true, + }, + new Product + { + Name = "Learning EF Core", + Description = "A best-selling book covering the fundamentals of Entity Framework Core", + IsOnSale = true, + }, + new Product + { + Name = "Learning .NET Standard", + Description = "A best-selling book covering the fundamentals of .NET Standard", + }, + new Product + { + Name = "Learning .NET Core", + Description = "A best-selling book covering the fundamentals of .NET Core", + }, + new Product + { + Name = "Learning C#", + Description = "A best-selling book covering the fundamentals of C#", + }); + _context.SaveChanges(); + } + } + + public List GetProducts() => + _context.Products.OrderBy(p => p.Name).ToList(); + + public IAsyncEnumerable GetProductsAsync() => + _context.Products.OrderBy(p => p.Name).AsAsyncEnumerable(); + + public bool TryGetProduct(int id, out Product product) + { + product = _context.Products.Find(id); + + return (product != null); + } + + public async Task AddProductAsync(Product product) + { + _context.Products.Add(product); + int rowsAffected = await _context.SaveChangesAsync(); + return rowsAffected; + } +} 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": "*" +} From f4f64735a4b957718856b6b86223d9057d77f0f8 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 30 Sep 2022 11:02:44 -0700 Subject: [PATCH 2/2] Removing repository and changing routes --- .../ActionResultOfTProductsController.cs | 47 +++++++++++++ .../ActionResultProductsController.cs | 47 +++++++++++++ ...Result.cs => IResultProductsController.cs} | 24 ++++--- .../ProductsController.ActionResultOfT.cs | 43 ------------ .../ProductsController.IActionResult.cs | 43 ------------ .../Controllers/ProductsController.cs | 16 ++--- ...OfT.cs => ResultsOfTProductsController.cs} | 24 ++++--- .../7.x/WebApiSample/ProductContext.cs | 40 +++++++++++ .../7.x/WebApiSample/Program.cs | 10 ++- .../Repositories/ProductsRepository.cs | 67 ------------------- 10 files changed, 178 insertions(+), 183 deletions(-) create mode 100644 mvc/action-return-types/7.x/WebApiSample/Controllers/ActionResultOfTProductsController.cs create mode 100644 mvc/action-return-types/7.x/WebApiSample/Controllers/ActionResultProductsController.cs rename mvc/action-return-types/7.x/WebApiSample/Controllers/{ProductsController.IResult.cs => IResultProductsController.cs} (66%) delete mode 100644 mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.ActionResultOfT.cs delete mode 100644 mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.IActionResult.cs rename mvc/action-return-types/7.x/WebApiSample/Controllers/{ProductsController.ResultsOfT.cs => ResultsOfTProductsController.cs} (59%) delete mode 100644 mvc/action-return-types/7.x/WebApiSample/Repositories/ProductsRepository.cs 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/ProductsController.IResult.cs b/mvc/action-return-types/7.x/WebApiSample/Controllers/IResultProductsController.cs similarity index 66% rename from mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.IResult.cs rename to mvc/action-return-types/7.x/WebApiSample/Controllers/IResultProductsController.cs index 9cd5df28..81423dac 100644 --- a/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.IResult.cs +++ b/mvc/action-return-types/7.x/WebApiSample/Controllers/IResultProductsController.cs @@ -4,21 +4,25 @@ namespace WebApiSample.Controllers; using Microsoft.AspNetCore.Mvc; using WebApiSample.Models; -public partial class ProductsController : ControllerBase +[ApiController] +[Route("products/iresult")] +public class IResultProductsController : ControllerBase { -#if IResult + 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) { - if (!_repository.TryGetProduct(id, out var product)) - { - return Results.NotFound(); - } - - return Results.Ok(product); + var product = _productContext.Products.Find(id); + return product == null ? Results.NotFound() : Results.Ok(product); } // @@ -34,11 +38,11 @@ public async Task CreateAsync(Product product) return Results.BadRequest(); } - await _repository.AddProductAsync(product); + _productContext.Products.Add(product); + await _productContext.SaveChangesAsync(); var location = Url.Action(nameof(GetById), new { id = product.Id }) ?? $"/{product.Id}"; return Results.Created(location, product); } // -#endif } diff --git a/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.ActionResultOfT.cs b/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.ActionResultOfT.cs deleted file mode 100644 index 4c8fe227..00000000 --- a/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.ActionResultOfT.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace WebApiSample.Controllers; - -using System.Net.Mime; -using Microsoft.AspNetCore.Mvc; -using WebApiSample.Models; - -public partial class ProductsController : ControllerBase -{ -#if ActionResultOfT - // - [HttpGet("{id}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetById(int id) - { - if (!_repository.TryGetProduct(id, out var product)) - { - return NotFound(); - } - - return product; - } - // - - // - [HttpPost] - [Consumes(MediaTypeNames.Application.Json)] - [ProducesResponseType(StatusCodes.Status201Created)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] - public async Task> CreateAsync(Product product) - { - if (product.Description.Contains("XYZ Widget")) - { - return BadRequest(); - } - - await _repository.AddProductAsync(product); - - return CreatedAtAction(nameof(GetById), new { id = product.Id }, product); - } - // -#endif -} diff --git a/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.IActionResult.cs b/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.IActionResult.cs deleted file mode 100644 index a0a6421f..00000000 --- a/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.IActionResult.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace WebApiSample.Controllers; - -using System.Net.Mime; -using Microsoft.AspNetCore.Mvc; -using WebApiSample.Models; - -public partial class ProductsController : ControllerBase -{ -#if IActionResult - // - [HttpGet("{id}")] - [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Product))] - [ProducesResponseType(StatusCodes.Status404NotFound)] - public IActionResult GetById(int id) - { - if (!_repository.TryGetProduct(id, out var product)) - { - return NotFound(); - } - - return Ok(product); - } - // - - // - [HttpPost] - [Consumes(MediaTypeNames.Application.Json)] - [ProducesResponseType(StatusCodes.Status201Created)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] - public async Task CreateAsync(Product product) - { - if (product.Description.Contains("XYZ Widget")) - { - return BadRequest(); - } - - await _repository.AddProductAsync(product); - - return CreatedAtAction(nameof(GetById), new { id = product.Id }, product); - } - // -#endif -} diff --git a/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.cs b/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.cs index b9170d7b..f7c85850 100644 --- a/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.cs +++ b/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.cs @@ -1,31 +1,31 @@ namespace WebApiSample.Controllers; using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; using WebApiSample.Models; -using WebApiSample.Repositories; [ApiController] [Route("[controller]")] public partial class ProductsController : ControllerBase { - private readonly ProductsRepository _repository; + private readonly ProductContext _productContext; - public ProductsController(ProductsRepository repository) + public ProductsController(ProductContext productContext) { - _repository = repository; + _productContext = productContext; } // [HttpGet] - public List Get() => - _repository.GetProducts(); + public Task> Get() => + _productContext.Products.OrderBy(p => p.Name).ToListAsync(); // // [HttpGet("syncsale")] public IEnumerable GetOnSaleProducts() { - var products = _repository.GetProducts(); + var products = _productContext.Products.OrderBy(p => p.Name).ToList(); foreach (var product in products) { @@ -41,7 +41,7 @@ public IEnumerable GetOnSaleProducts() [HttpGet("asyncsale")] public async IAsyncEnumerable GetOnSaleProductsAsync() { - var products = _repository.GetProductsAsync(); + var products = _productContext.Products.OrderBy(p => p.Name).AsAsyncEnumerable(); await foreach (var product in products) { diff --git a/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.ResultsOfT.cs b/mvc/action-return-types/7.x/WebApiSample/Controllers/ResultsOfTProductsController.cs similarity index 59% rename from mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.ResultsOfT.cs rename to mvc/action-return-types/7.x/WebApiSample/Controllers/ResultsOfTProductsController.cs index 759fc226..dd74f9b6 100644 --- a/mvc/action-return-types/7.x/WebApiSample/Controllers/ProductsController.ResultsOfT.cs +++ b/mvc/action-return-types/7.x/WebApiSample/Controllers/ResultsOfTProductsController.cs @@ -4,19 +4,23 @@ namespace WebApiSample.Controllers; using Microsoft.AspNetCore.Mvc; using WebApiSample.Models; -public partial class ProductsController : ControllerBase +[ApiController] +[Route("products/resultsoft")] +public class ResultsOfTProductsController : ControllerBase { -#if ResultsOfT + private readonly ProductContext _productContext; + + public ResultsOfTProductsController(ProductContext productContext) + { + _productContext = productContext; + } + // [HttpGet("{id}")] public Results> GetById(int id) { - if (!_repository.TryGetProduct(id, out var product)) - { - return TypedResults.NotFound(); - } - - return TypedResults.Ok(product); + var product = _productContext.Products.Find(id); + return product == null ? TypedResults.NotFound() : TypedResults.Ok(product); } // @@ -29,11 +33,11 @@ public async Task>> CreateAsync(Product pro return TypedResults.BadRequest(); } - await _repository.AddProductAsync(product); + _productContext.Products.Add(product); + await _productContext.SaveChangesAsync(); var location = Url.Action(nameof(GetById), new { id = product.Id }) ?? $"/{product.Id}"; return TypedResults.Created(location, product); } // -#endif } diff --git a/mvc/action-return-types/7.x/WebApiSample/ProductContext.cs b/mvc/action-return-types/7.x/WebApiSample/ProductContext.cs index 187e0e63..57f7a461 100644 --- a/mvc/action-return-types/7.x/WebApiSample/ProductContext.cs +++ b/mvc/action-return-types/7.x/WebApiSample/ProductContext.cs @@ -10,5 +10,45 @@ public ProductContext(DbContextOptions 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 index 2eca7716..8304cfc7 100644 --- a/mvc/action-return-types/7.x/WebApiSample/Program.cs +++ b/mvc/action-return-types/7.x/WebApiSample/Program.cs @@ -1,11 +1,9 @@ -using WebApiSample.Repositories; using WebApiSample; using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); // Add services to the container. -builder.Services.AddScoped(); builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("ProductInventory")); @@ -24,5 +22,13 @@ 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/Repositories/ProductsRepository.cs b/mvc/action-return-types/7.x/WebApiSample/Repositories/ProductsRepository.cs deleted file mode 100644 index 54502c79..00000000 --- a/mvc/action-return-types/7.x/WebApiSample/Repositories/ProductsRepository.cs +++ /dev/null @@ -1,67 +0,0 @@ -namespace WebApiSample.Repositories; - -using Microsoft.EntityFrameworkCore; -using WebApiSample.Models; - -public class ProductsRepository -{ - private readonly ProductContext _context; - - public ProductsRepository(ProductContext context) - { - _context = context; - - if (_context.Products.Count() == 0) - { - _context.Products.AddRange( - new Product - { - Name = "Learning ASP.NET Core", - Description = "A best-selling book covering the fundamentals of ASP.NET Core", - IsOnSale = true, - }, - new Product - { - Name = "Learning EF Core", - Description = "A best-selling book covering the fundamentals of Entity Framework Core", - IsOnSale = true, - }, - new Product - { - Name = "Learning .NET Standard", - Description = "A best-selling book covering the fundamentals of .NET Standard", - }, - new Product - { - Name = "Learning .NET Core", - Description = "A best-selling book covering the fundamentals of .NET Core", - }, - new Product - { - Name = "Learning C#", - Description = "A best-selling book covering the fundamentals of C#", - }); - _context.SaveChanges(); - } - } - - public List GetProducts() => - _context.Products.OrderBy(p => p.Name).ToList(); - - public IAsyncEnumerable GetProductsAsync() => - _context.Products.OrderBy(p => p.Name).AsAsyncEnumerable(); - - public bool TryGetProduct(int id, out Product product) - { - product = _context.Products.Find(id); - - return (product != null); - } - - public async Task AddProductAsync(Product product) - { - _context.Products.Add(product); - int rowsAffected = await _context.SaveChangesAsync(); - return rowsAffected; - } -}