Skip to content

Commit 121fae8

Browse files
committed
Catalog.API service with mongoDb
1 parent 07078c4 commit 121fae8

File tree

13 files changed

+424
-0
lines changed

13 files changed

+424
-0
lines changed

Src/AspNetCoreMicroservice.sln

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,36 @@ Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio Version 17
44
VisualStudioVersion = 17.3.32901.215
55
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Services", "Services", "{FDE99E6D-6CC6-4FAF-BCAC-B5A8E3448D87}"
7+
EndProject
8+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Catalog", "Catalog", "{A87BF17D-17F1-49B0-9250-FB1898154244}"
9+
EndProject
10+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Catalog.API", "Services\Catalog\Catalog.API\Catalog.API.csproj", "{C1919028-A1C5-46A5-9BAE-A2BED21FFEAB}"
11+
EndProject
12+
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{CF0B640E-9459-4F17-9337-F1A778AECEB3}"
13+
EndProject
614
Global
15+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
16+
Debug|Any CPU = Debug|Any CPU
17+
Release|Any CPU = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
20+
{C1919028-A1C5-46A5-9BAE-A2BED21FFEAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{C1919028-A1C5-46A5-9BAE-A2BED21FFEAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{C1919028-A1C5-46A5-9BAE-A2BED21FFEAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{C1919028-A1C5-46A5-9BAE-A2BED21FFEAB}.Release|Any CPU.Build.0 = Release|Any CPU
24+
{CF0B640E-9459-4F17-9337-F1A778AECEB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25+
{CF0B640E-9459-4F17-9337-F1A778AECEB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
26+
{CF0B640E-9459-4F17-9337-F1A778AECEB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
27+
{CF0B640E-9459-4F17-9337-F1A778AECEB3}.Release|Any CPU.Build.0 = Release|Any CPU
28+
EndGlobalSection
729
GlobalSection(SolutionProperties) = preSolution
830
HideSolutionNode = FALSE
931
EndGlobalSection
32+
GlobalSection(NestedProjects) = preSolution
33+
{A87BF17D-17F1-49B0-9250-FB1898154244} = {FDE99E6D-6CC6-4FAF-BCAC-B5A8E3448D87}
34+
{C1919028-A1C5-46A5-9BAE-A2BED21FFEAB} = {A87BF17D-17F1-49B0-9250-FB1898154244}
35+
EndGlobalSection
1036
GlobalSection(ExtensibilityGlobals) = postSolution
1137
SolutionGuid = {D7B43DFB-CD61-4F50-9804-103C4A7E05AF}
1238
EndGlobalSection
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
8+
<DockerfileContext>..\..\..</DockerfileContext>
9+
<DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
14+
<PackageReference Include="MongoDB.Driver" Version="2.19.0" />
15+
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
16+
</ItemGroup>
17+
18+
</Project>
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using Catalog.API.Data;
2+
using Catalog.API.Models;
3+
using Catalog.API.Repository;
4+
using Microsoft.AspNetCore.Http;
5+
using Microsoft.AspNetCore.Mvc;
6+
7+
namespace Catalog.API.Controllers
8+
{
9+
[Route("api/v1/[controller]")]
10+
[ApiController]
11+
public class CatalogController : ControllerBase
12+
{
13+
private readonly IProductRepository _productRepository;
14+
private readonly ILogger<CatalogController> _logger;
15+
public CatalogController(ILogger<CatalogController> logger, IProductRepository productRepository)
16+
{
17+
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
18+
_productRepository = productRepository ?? throw new ArgumentNullException(nameof(_productRepository));
19+
}
20+
21+
[HttpGet]
22+
public async Task<ActionResult<IEnumerable<Product>>> GetProducts()
23+
{
24+
var products = await _productRepository.GetProducts();
25+
return Ok(products);
26+
}
27+
28+
[HttpGet("{id:length(24)}",Name = "GetProduct")]
29+
[ProducesResponseType(typeof(Product), (int)StatusCodes.Status200OK)]
30+
public async Task<ActionResult<Product>> GetProductById(string id)
31+
{
32+
var product = await _productRepository.GetProduct(id);
33+
if(product == null)
34+
{
35+
_logger.LogError("Product with ID:{0} not found.", id);
36+
return NotFound();
37+
}
38+
return Ok(product);
39+
}
40+
41+
[HttpGet("[action]/{category}", Name = "GetByCategory")]
42+
[ProducesResponseType(typeof(IEnumerable<Product>), (int)StatusCodes.Status200OK)]
43+
public async Task<ActionResult<IEnumerable<Product>>> GetProductByCategory(string category)
44+
{
45+
var product = await _productRepository.GetProductByCategory(category);
46+
return Ok(product);
47+
}
48+
49+
[HttpGet("[action]/{name}", Name = "GetByName")]
50+
[ProducesResponseType(typeof(IEnumerable<Product>), (int)StatusCodes.Status200OK)]
51+
public async Task<ActionResult<IEnumerable<Product>>> GetProductByName(string name)
52+
{
53+
var product = await _productRepository.GetProductByName(name);
54+
return Ok(product);
55+
}
56+
57+
[HttpPost]
58+
public async Task<ActionResult<Product>> CreatePruduct(Product product)
59+
{
60+
await _productRepository.CreateProduct(product);
61+
return CreatedAtRoute("GetProduct", new {id=product.Id}, product);
62+
}
63+
64+
[HttpPut]
65+
public async Task<ActionResult> UpdatePruduct(Product product)
66+
{
67+
return Ok(await _productRepository.UpdateProduct(product));
68+
}
69+
70+
[HttpDelete("{id:length(24)}", Name = "DeleteProduct")]
71+
public async Task<ActionResult> DeletePruduct(string id)
72+
{
73+
return Ok(await _productRepository.DeleteProduct(id));
74+
}
75+
}
76+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Catalog.API.Models;
2+
using MongoDB.Driver;
3+
4+
namespace Catalog.API.Data
5+
{
6+
public class CatalogContext : ICatalogContext
7+
{
8+
IMongoDatabase Database { get; set; }
9+
public CatalogContext(IConfiguration configuration)
10+
{
11+
var client = new MongoClient(configuration.GetValue<string>("DatabaseSettings:ConnectionString"));
12+
Database = client.GetDatabase("CatalogDb");
13+
14+
CatalogContextSeed.SeedData(Products);
15+
}
16+
17+
public IMongoCollection<Product> Products => Database.GetCollection<Product>("Products");
18+
}
19+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using Catalog.API.Models;
2+
using MongoDB.Driver;
3+
4+
namespace Catalog.API.Data
5+
{
6+
internal class CatalogContextSeed
7+
{
8+
internal static void SeedData(IMongoCollection<Product> products)
9+
{
10+
bool isExists = products.Find(f => true).Any();
11+
if (!isExists)
12+
{
13+
products.InsertManyAsync(GetInitialProductList());
14+
}
15+
16+
//throw new NotImplementedException();
17+
}
18+
19+
private static IEnumerable<Product> GetInitialProductList()
20+
{
21+
return new List<Product>()
22+
{
23+
new Product()
24+
{
25+
Id = "602d2149e773f2a3990b47f5",
26+
Name = "IPhone X",
27+
Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.",
28+
Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.",
29+
ImageFile = "product-1.png",
30+
Price = 950.00M,
31+
Category = "Smart Phone"
32+
},
33+
new Product()
34+
{
35+
Id = "602d2149e773f2a3990b47f6",
36+
Name = "Samsung 10",
37+
Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.",
38+
Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.",
39+
ImageFile = "product-2.png",
40+
Price = 840.00M,
41+
Category = "Smart Phone"
42+
},
43+
new Product()
44+
{
45+
Id = "602d2149e773f2a3990b47f7",
46+
Name = "Huawei Plus",
47+
Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.",
48+
Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.",
49+
ImageFile = "product-3.png",
50+
Price = 650.00M,
51+
Category = "White Appliances"
52+
},
53+
new Product()
54+
{
55+
Id = "602d2149e773f2a3990b47f8",
56+
Name = "Xiaomi Mi 9",
57+
Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.",
58+
Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.",
59+
ImageFile = "product-4.png",
60+
Price = 470.00M,
61+
Category = "White Appliances"
62+
},
63+
new Product()
64+
{
65+
Id = "602d2149e773f2a3990b47f9",
66+
Name = "HTC U11+ Plus",
67+
Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.",
68+
Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.",
69+
ImageFile = "product-5.png",
70+
Price = 380.00M,
71+
Category = "Smart Phone"
72+
},
73+
new Product()
74+
{
75+
Id = "602d2149e773f2a3990b47fa",
76+
Name = "LG G7 ThinQ",
77+
Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.",
78+
Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.",
79+
ImageFile = "product-6.png",
80+
Price = 240.00M,
81+
Category = "Home Kitchen"
82+
}
83+
};
84+
}
85+
}
86+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using Catalog.API.Models;
2+
using MongoDB.Driver;
3+
4+
namespace Catalog.API.Data
5+
{
6+
public interface ICatalogContext
7+
{
8+
IMongoCollection<Product> Products { get; }
9+
}
10+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using MongoDB.Bson.Serialization.Attributes;
2+
3+
namespace Catalog.API.Models
4+
{
5+
public class Product
6+
{
7+
[BsonId]
8+
[BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]
9+
public string Id { get; set; }
10+
[BsonElement("Name")]
11+
public string Name { get; set; }
12+
public string Category { get; set; }
13+
public string Summary { get; set; }
14+
public string Description { get; set; }
15+
public decimal Price { get; set; }
16+
public string ImageFile { get; set; }
17+
}
18+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using Catalog.API.Data;
2+
using Catalog.API.Repository;
3+
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
4+
5+
var builder = WebApplication.CreateBuilder(args);
6+
7+
// Add services to the container.
8+
builder.Services.AddScoped<ICatalogContext, CatalogContext>();
9+
builder.Services.AddScoped<IProductRepository, ProductRepository>();
10+
11+
builder.Services.AddControllers();
12+
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
13+
builder.Services.AddEndpointsApiExplorer();
14+
builder.Services.AddSwaggerGen(c =>
15+
{
16+
c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title="Catalog.API", Version="v1" });
17+
});
18+
19+
var app = builder.Build();
20+
21+
// Configure the HTTP request pipeline.
22+
if (app.Environment.IsDevelopment())
23+
{
24+
app.UseDeveloperExceptionPage();
25+
app.UseSwagger();
26+
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Catalog.API v1"));
27+
}
28+
29+
app.UseRouting();
30+
app.UseAuthorization();
31+
32+
app.UseEndpoints(endpoints =>
33+
{
34+
endpoints.MapControllers();
35+
//endpoints.MapHealthChecks("/hc", new HealthCheckOptions()
36+
//{
37+
// Predicate = _ => true,
38+
// ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
39+
//});
40+
});
41+
42+
app.Run();
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"profiles": {
3+
"Catalog.API": {
4+
"commandName": "Project",
5+
"launchBrowser": true,
6+
"launchUrl": "swagger",
7+
"environmentVariables": {
8+
"ASPNETCORE_ENVIRONMENT": "Development"
9+
},
10+
"dotnetRunMessages": true,
11+
"applicationUrl": "http://localhost:5000"
12+
},
13+
"IIS Express": {
14+
"commandName": "IISExpress",
15+
"launchBrowser": true,
16+
"launchUrl": "swagger",
17+
"environmentVariables": {
18+
"ASPNETCORE_ENVIRONMENT": "Development"
19+
}
20+
},
21+
"Docker": {
22+
"commandName": "Docker",
23+
"launchBrowser": true,
24+
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
25+
"publishAllPorts": true
26+
}
27+
},
28+
"$schema": "https://json.schemastore.org/launchsettings.json",
29+
"iisSettings": {
30+
"windowsAuthentication": false,
31+
"anonymousAuthentication": true,
32+
"iisExpress": {
33+
"applicationUrl": "http://localhost:64996",
34+
"sslPort": 0
35+
}
36+
}
37+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using Catalog.API.Models;
2+
3+
namespace Catalog.API.Repository
4+
{
5+
public interface IProductRepository
6+
{
7+
Task<IEnumerable<Product>> GetProducts();
8+
Task<Product> GetProduct(string id);
9+
Task<IEnumerable<Product>> GetProductByName(string name);
10+
Task<IEnumerable<Product>> GetProductByCategory(string categoryName);
11+
12+
Task CreateProduct(Product product);
13+
Task<bool> UpdateProduct(Product product);
14+
Task<bool> DeleteProduct(string id);
15+
}
16+
}

0 commit comments

Comments
 (0)