Browse Source
* Adding new Endpoints * update nuget packages * Modifying API to work well with Swagger. * Remove Swashbuckle.Coremain
committed by
GitHub
20 changed files with 307 additions and 22 deletions
@ -0,0 +1,20 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Microsoft.eShopWeb.Web.API |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Base class used by API requests
|
||||
|
/// </summary>
|
||||
|
public abstract class BaseMessage |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Unique Identifier used by logging
|
||||
|
/// </summary>
|
||||
|
protected Guid _correlationId = Guid.NewGuid(); |
||||
|
public Guid CorrelationId() => _correlationId; |
||||
|
} |
||||
|
|
||||
|
public abstract class BaseRequest : BaseMessage |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Microsoft.eShopWeb.Web.API |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Base class used by API responses
|
||||
|
/// </summary>
|
||||
|
public abstract class BaseResponse : BaseMessage |
||||
|
{ |
||||
|
public BaseResponse(Guid correlationId) : base() |
||||
|
{ |
||||
|
base._correlationId = correlationId; |
||||
|
} |
||||
|
|
||||
|
public BaseResponse() |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
namespace Microsoft.eShopWeb.Web.API.CatalogItemEndpoints |
||||
|
{ |
||||
|
public class CatalogItemDto |
||||
|
{ |
||||
|
public int Id { get; set; } |
||||
|
public string Name { get; set; } |
||||
|
public string Description { get; set; } |
||||
|
public decimal Price { get; set; } |
||||
|
public string PictureUri { get; set; } |
||||
|
public int CatalogTypeId { get; set; } |
||||
|
public int CatalogBrandId { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
namespace Microsoft.eShopWeb.Web.API.CatalogItemEndpoints |
||||
|
{ |
||||
|
public class CreateCatalogItemRequest : BaseRequest |
||||
|
{ |
||||
|
public int CatalogBrandId { get; set; } |
||||
|
public int CatalogTypeId { get; set; } |
||||
|
public string Description { get; set; } |
||||
|
public string Name { get; set; } |
||||
|
public string PictureUri { get; set; } |
||||
|
public decimal Price { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Microsoft.eShopWeb.Web.API.CatalogItemEndpoints |
||||
|
{ |
||||
|
public class CreateCatalogItemResponse : BaseResponse |
||||
|
{ |
||||
|
public CreateCatalogItemResponse(Guid correlationId) : base(correlationId) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public CatalogItemDto CatalogItem { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
using Ardalis.ApiEndpoints; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.eShopWeb.ApplicationCore.Entities; |
||||
|
using Microsoft.eShopWeb.ApplicationCore.Interfaces; |
||||
|
using Swashbuckle.AspNetCore.Annotations; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Microsoft.eShopWeb.Web.API.CatalogItemEndpoints |
||||
|
{ |
||||
|
public class Create : BaseAsyncEndpoint<CreateCatalogItemRequest, CreateCatalogItemResponse> |
||||
|
{ |
||||
|
private readonly IAsyncRepository<CatalogItem> _itemRepository; |
||||
|
|
||||
|
public Create(IAsyncRepository<CatalogItem> itemRepository) |
||||
|
{ |
||||
|
_itemRepository = itemRepository; |
||||
|
} |
||||
|
|
||||
|
[HttpPost("api/catalog-items")] |
||||
|
[SwaggerOperation( |
||||
|
Summary = "Creates a new Catalog Item", |
||||
|
Description = "Creates a new Catalog Item", |
||||
|
OperationId = "catalog-items.create", |
||||
|
Tags = new[] { "CatalogItemEndpoints" }) |
||||
|
] |
||||
|
public override async Task<ActionResult<CreateCatalogItemResponse>> HandleAsync(CreateCatalogItemRequest request) |
||||
|
{ |
||||
|
var response = new CreateCatalogItemResponse(request.CorrelationId()); |
||||
|
|
||||
|
CatalogItem newItem = new CatalogItem(request.CatalogTypeId, request.CatalogBrandId, request.Description, request.Name, request.Price, request.PictureUri); |
||||
|
|
||||
|
newItem = await _itemRepository.AddAsync(newItem); |
||||
|
|
||||
|
var dto = new CatalogItemDto |
||||
|
{ |
||||
|
Id = newItem.Id, |
||||
|
CatalogBrandId = newItem.CatalogBrandId, |
||||
|
CatalogTypeId = newItem.CatalogTypeId, |
||||
|
Description = newItem.Description, |
||||
|
Name = newItem.Name, |
||||
|
PictureUri = newItem.PictureUri, |
||||
|
Price = newItem.Price |
||||
|
}; |
||||
|
response.CatalogItem = dto; |
||||
|
return response; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace Microsoft.eShopWeb.Web.API.CatalogItemEndpoints |
||||
|
{ |
||||
|
public class DeleteCatalogItemRequest : BaseRequest |
||||
|
{ |
||||
|
//[FromRoute]
|
||||
|
public int CatalogItemId { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Microsoft.eShopWeb.Web.API.CatalogItemEndpoints |
||||
|
{ |
||||
|
public class DeleteCatalogItemResponse : BaseResponse |
||||
|
{ |
||||
|
public DeleteCatalogItemResponse(Guid correlationId) : base(correlationId) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public string Status { get; set; } = "Deleted"; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
using Ardalis.ApiEndpoints; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.eShopWeb.ApplicationCore.Entities; |
||||
|
using Microsoft.eShopWeb.ApplicationCore.Interfaces; |
||||
|
using Swashbuckle.AspNetCore.Annotations; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Microsoft.eShopWeb.Web.API.CatalogItemEndpoints |
||||
|
{ |
||||
|
public class Delete : BaseAsyncEndpoint<DeleteCatalogItemRequest, DeleteCatalogItemResponse> |
||||
|
{ |
||||
|
private readonly IAsyncRepository<CatalogItem> _itemRepository; |
||||
|
|
||||
|
public Delete(IAsyncRepository<CatalogItem> itemRepository) |
||||
|
{ |
||||
|
_itemRepository = itemRepository; |
||||
|
} |
||||
|
|
||||
|
[HttpDelete("api/catalog-items/{CatalogItemId}")] |
||||
|
[SwaggerOperation( |
||||
|
Summary = "Deletes a Catalog Item", |
||||
|
Description = "Deletes a Catalog Item", |
||||
|
OperationId = "catalog-items.Delete", |
||||
|
Tags = new[] { "CatalogItemEndpoints" }) |
||||
|
] |
||||
|
public override async Task<ActionResult<DeleteCatalogItemResponse>> HandleAsync([FromRoute]DeleteCatalogItemRequest request) |
||||
|
{ |
||||
|
var response = new DeleteCatalogItemResponse(request.CorrelationId()); |
||||
|
|
||||
|
var itemToDelete = await _itemRepository.GetByIdAsync(request.CatalogItemId); |
||||
|
if (itemToDelete is null) return NotFound(); |
||||
|
|
||||
|
await _itemRepository.DeleteAsync(itemToDelete); |
||||
|
|
||||
|
return Ok(response); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
namespace Microsoft.eShopWeb.Web.API.CatalogItemEndpoints |
||||
|
{ |
||||
|
public class GetByIdCatalogItemRequest : BaseRequest |
||||
|
{ |
||||
|
public int CatalogItemId { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Microsoft.eShopWeb.Web.API.CatalogItemEndpoints |
||||
|
{ |
||||
|
public class GetByIdCatalogItemResponse : BaseResponse |
||||
|
{ |
||||
|
public GetByIdCatalogItemResponse(Guid correlationId) : base(correlationId) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public CatalogItemDto CatalogItem { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
using Ardalis.ApiEndpoints; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.eShopWeb.ApplicationCore.Entities; |
||||
|
using Microsoft.eShopWeb.ApplicationCore.Interfaces; |
||||
|
using Swashbuckle.AspNetCore.Annotations; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Microsoft.eShopWeb.Web.API.CatalogItemEndpoints |
||||
|
{ |
||||
|
public class GetById : BaseAsyncEndpoint<GetByIdCatalogItemRequest, GetByIdCatalogItemResponse> |
||||
|
{ |
||||
|
private readonly IAsyncRepository<CatalogItem> _itemRepository; |
||||
|
|
||||
|
public GetById(IAsyncRepository<CatalogItem> itemRepository) |
||||
|
{ |
||||
|
_itemRepository = itemRepository; |
||||
|
} |
||||
|
|
||||
|
[HttpGet("api/catalog-items/{CatalogItemId}")] |
||||
|
[SwaggerOperation( |
||||
|
Summary = "Get a Catalog Item by Id", |
||||
|
Description = "Gets a Catalog Item by Id", |
||||
|
OperationId = "catalog-items.GetById", |
||||
|
Tags = new[] { "CatalogItemEndpoints" }) |
||||
|
] |
||||
|
public override async Task<ActionResult<GetByIdCatalogItemResponse>> HandleAsync([FromRoute]GetByIdCatalogItemRequest request) |
||||
|
{ |
||||
|
var response = new GetByIdCatalogItemResponse(request.CorrelationId()); |
||||
|
|
||||
|
var item = await _itemRepository.GetByIdAsync(request.CatalogItemId); |
||||
|
if (item is null) return NotFound(); |
||||
|
|
||||
|
response.CatalogItem = new CatalogItemDto |
||||
|
{ |
||||
|
Id = item.Id, |
||||
|
CatalogBrandId = item.CatalogBrandId, |
||||
|
CatalogTypeId = item.CatalogTypeId, |
||||
|
Description = item.Description, |
||||
|
Name = item.Name, |
||||
|
PictureUri = item.PictureUri, |
||||
|
Price = item.Price |
||||
|
}; |
||||
|
return Ok(response); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using Microsoft.OpenApi.Models; |
||||
|
using Swashbuckle.AspNetCore.SwaggerGen; |
||||
|
|
||||
|
namespace Microsoft.eShopWeb.Web.API |
||||
|
{ |
||||
|
public class CustomSchemaFilters : ISchemaFilter |
||||
|
{ |
||||
|
public void Apply(OpenApiSchema schema, SchemaFilterContext context) |
||||
|
{ |
||||
|
var excludeProperties = new[] { "CorrelationId" }; |
||||
|
|
||||
|
foreach (var prop in excludeProperties) |
||||
|
if (schema.Properties.ContainsKey(prop)) |
||||
|
schema.Properties.Remove(prop); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,4 @@ |
|||||
|
# API Endpoints |
||||
|
|
||||
|
This folder demonstrates how to configure API endpoints as individual classes. You can compare it to the traditional controller-based approach found in /Controllers/Api. |
||||
|
|
||||
Loading…
Reference in new issue