Add Swagger to Basket Api
SQL databases with the same prefix for services Move application tier to api tier in ordering api
This commit is contained in:
parent
31753fc057
commit
10f3e17b55
@ -9,21 +9,22 @@ version: '2'
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
# webmvc:
|
webmvc:
|
||||||
# environment:
|
environment:
|
||||||
# - CatalogUrl=http://catalog.api
|
- CatalogUrl=http://catalog.api
|
||||||
# - OrderingUrl=http://ordering.api:5102
|
- OrderingUrl=http://ordering.api:5102
|
||||||
#- IdentityUrl=http://104.40.62.65:5105 #Remote: VM Needs to have public access at 5105.
|
#- IdentityUrl=http://13.88.8.119:5105 #Remote: VM Needs to have public access at 5105.
|
||||||
# - IdentityUrl=http://identity.service:5105 #Local: You need a entry in windows host file to run identity in local docker.
|
#- IdentityUrl=http://10.0.75.1:5105 #Local: You need to open windows firewall at range 5100-5105.
|
||||||
# - BasketUrl=http://basket.api:5103
|
- IdentityUrl=http://identity.service:5105 #Local: You need a entry in windows host file to run identity in local docker.
|
||||||
# ports:
|
- BasketUrl=http://basket.api:5103
|
||||||
# - "5100:5100"
|
ports:
|
||||||
|
- "5100:5100"
|
||||||
|
|
||||||
webspa:
|
webspa:
|
||||||
environment:
|
environment:
|
||||||
- CatalogUrl=http://catalog.api
|
- CatalogUrl=http://catalog.api
|
||||||
- OrderingUrl=http://ordering.api
|
- OrderingUrl=http://ordering.api
|
||||||
#- IdentityUrl=http://104.40.62.65:5105 #Remote: VM Needs to have public access at 5105.
|
#- IdentityUrl=http://13.88.8.119:5105 #Remote: VM Needs to have public access at 5105.
|
||||||
- IdentityUrl=http://identity.service:5105 #Local: You need a entry in windows host file to run identity in local docker.
|
- IdentityUrl=http://identity.service:5105 #Local: You need a entry in windows host file to run identity in local docker.
|
||||||
- BasketUrl=http://basket.api:5103
|
- BasketUrl=http://basket.api:5103
|
||||||
ports:
|
ports:
|
||||||
@ -32,30 +33,30 @@ services:
|
|||||||
basket.api:
|
basket.api:
|
||||||
environment:
|
environment:
|
||||||
- ConnectionString=basket.data
|
- ConnectionString=basket.data
|
||||||
#- identityUrl=http://104.40.62.65:5105 #Remote: VM Needs to have public access at 5105.
|
#- identityUrl=http://13.88.8.119:5105 #Remote
|
||||||
- identityUrl=http://identity.service:5105 #Local: You need a entry in windows host file to run identity in local docker.
|
- identityUrl=http://identity.service:5105 #Local: You need a entry in windows host file to run identity in local docker.
|
||||||
ports:
|
ports:
|
||||||
- "5103:5103"
|
- "5103:5103"
|
||||||
|
|
||||||
catalog.api:
|
catalog.api:
|
||||||
environment:
|
environment:
|
||||||
- ConnectionString=Server=sql.data;Database=CatalogDB;User Id=sa;Password=Pass@word
|
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word
|
||||||
ports:
|
ports:
|
||||||
- "5101:80"
|
- "5101:80"
|
||||||
|
|
||||||
# ordering.api:
|
ordering.api:
|
||||||
# environment:
|
environment:
|
||||||
# - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word
|
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word
|
||||||
# - identityUrl=http://identity.service:5105 #local
|
- identityUrl=http://identity.service:5105 #local
|
||||||
#- identityUrl=http://104.40.62.65:5105 #remote
|
#- identityUrl=http://13.88.8.119:5105 #remote
|
||||||
# ports:
|
ports:
|
||||||
# - "5102:5102"
|
- "5102:5102"
|
||||||
|
|
||||||
identity.service:
|
identity.service:
|
||||||
environment:
|
environment:
|
||||||
- SpaClient=http://localhost:5104
|
- SpaClient=http://localhost:5104
|
||||||
- ConnectionStrings__DefaultConnection=Server=sql.data;Database=aspnet-Microsoft.eShopOnContainers;User Id=sa;Password=Pass@word
|
- ConnectionStrings__DefaultConnection=Server=sql.data;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word
|
||||||
#- MvcClient=http://104.40.62.65:5100 #Remote: VM Needs to have public access at 5105.
|
#- MvcClient=http://13.88.8.119:5100 #Remote: VM Needs to have public access at 5105.
|
||||||
- MvcClient=http://localhost:5100 #Local: You need a entry in windows host file to run identity in local docker.
|
- MvcClient=http://localhost:5100 #Local: You need a entry in windows host file to run identity in local docker.
|
||||||
#10.0.75.1:5105 CCE/TODO: try to avoid host entry.
|
#10.0.75.1:5105 CCE/TODO: try to avoid host entry.
|
||||||
ports:
|
ports:
|
||||||
|
@ -7,11 +7,13 @@
|
|||||||
version: '2'
|
version: '2'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# webmvc:
|
webmvc:
|
||||||
# image: eshop/web
|
image: eshop/web
|
||||||
# depends_on:
|
links:
|
||||||
# - identity.service
|
- identity.service:localhost
|
||||||
# - basket.api
|
depends_on:
|
||||||
|
- identity.service
|
||||||
|
- basket.api
|
||||||
|
|
||||||
webspa:
|
webspa:
|
||||||
image: eshop/webspa
|
image: eshop/webspa
|
||||||
@ -30,10 +32,10 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- sql.data
|
- sql.data
|
||||||
|
|
||||||
# ordering.api:
|
ordering.api:
|
||||||
# image: eshop/ordering.api
|
image: eshop/ordering.api
|
||||||
# depends_on:
|
depends_on:
|
||||||
# - sql.data
|
- sql.data
|
||||||
|
|
||||||
identity.service:
|
identity.service:
|
||||||
image: eshop/identity
|
image: eshop/identity
|
||||||
|
19
src/Services/Basket/Basket.API/Controllers/HomeController.cs
Normal file
19
src/Services/Basket/Basket.API/Controllers/HomeController.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
// For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
|
||||||
|
{
|
||||||
|
public class HomeController : Controller
|
||||||
|
{
|
||||||
|
// GET: /<controller>/
|
||||||
|
public IActionResult Index()
|
||||||
|
{
|
||||||
|
return new RedirectResult("~/swagger/ui");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -47,6 +47,20 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
return ConnectionMultiplexer.Connect(ips.First().ToString());
|
return ConnectionMultiplexer.Connect(ips.First().ToString());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddSwaggerGen();
|
||||||
|
services.ConfigureSwaggerGen(options =>
|
||||||
|
{
|
||||||
|
options.DescribeAllEnumsAsStrings();
|
||||||
|
options.SingleApiVersion(new Swashbuckle.Swagger.Model.Info()
|
||||||
|
{
|
||||||
|
Title = "Basket HTTP API",
|
||||||
|
Version = "v1",
|
||||||
|
Description = "The Basket Service HTTP API",
|
||||||
|
TermsOfService = "Terms Of Service"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
services.AddCors(options =>
|
services.AddCors(options =>
|
||||||
{
|
{
|
||||||
options.AddPolicy("CorsPolicy",
|
options.AddPolicy("CorsPolicy",
|
||||||
@ -77,7 +91,11 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
RequireHttpsMetadata = false
|
RequireHttpsMetadata = false
|
||||||
});
|
});
|
||||||
|
|
||||||
app.UseMvc();
|
app.UseMvcWithDefaultRoute();
|
||||||
|
|
||||||
|
app.UseSwagger()
|
||||||
|
.UseSwaggerUi();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
|
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
|
||||||
"StackExchange.Redis": "1.1.608",
|
"StackExchange.Redis": "1.1.608",
|
||||||
"Newtonsoft.Json": "9.0.1",
|
"Newtonsoft.Json": "9.0.1",
|
||||||
"IdentityServer4.AccessTokenValidation": "1.0.1-rc3"
|
"IdentityServer4.AccessTokenValidation": "1.0.1-rc3",
|
||||||
|
"Swashbuckle": "6.0.0-beta902"
|
||||||
},
|
},
|
||||||
"tools": {
|
"tools": {
|
||||||
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final"
|
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"ConnectionString": "Server=tcp:127.0.0.1,5433;Initial Catalog=CatalogDB;User Id=sa;Password=Pass@word",
|
"ConnectionString": "Server=tcp:127.0.0.1,5433;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word",
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"IncludeScopes": false,
|
"IncludeScopes": false,
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace eShopOnContainers.Identity
|
||||||
|
{
|
||||||
|
public class AppSettings
|
||||||
|
{
|
||||||
|
public string MvcClient { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -78,7 +78,7 @@ namespace eShopOnContainers.Identity.Configuration
|
|||||||
new Secret("secret".Sha256())
|
new Secret("secret".Sha256())
|
||||||
},
|
},
|
||||||
ClientUri = $"{clientsUrl["Mvc"]}", // public uri of the client
|
ClientUri = $"{clientsUrl["Mvc"]}", // public uri of the client
|
||||||
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
|
AllowedGrantTypes = GrantTypes.Hybrid,
|
||||||
RedirectUris = new List<string>
|
RedirectUris = new List<string>
|
||||||
{
|
{
|
||||||
$"{clientsUrl["Mvc"]}/signin-oidc",
|
$"{clientsUrl["Mvc"]}/signin-oidc",
|
||||||
|
@ -85,15 +85,9 @@ namespace IdentityServer4.Quickstart.UI.Controllers
|
|||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
var user = await _loginService.FindByUsername(model.Email);
|
var user = await _loginService.FindByUsername(model.Email);
|
||||||
// validate username/password against in-memory store
|
|
||||||
if (await _loginService.ValidateCredentials(user, model.Password))
|
if (await _loginService.ValidateCredentials(user, model.Password))
|
||||||
{
|
{
|
||||||
// issue authentication cookie with subject ID and username
|
AuthenticationProperties props = null;
|
||||||
//var user = _loginService.FindByUsername(model.Username);
|
|
||||||
|
|
||||||
AuthenticationProperties props = null;
|
|
||||||
// only set explicit expiration here if persistent.
|
|
||||||
// otherwise we reply upon expiration configured in cookie middleware.
|
|
||||||
if (model.RememberMe)
|
if (model.RememberMe)
|
||||||
{
|
{
|
||||||
props = new AuthenticationProperties
|
props = new AuthenticationProperties
|
||||||
@ -217,15 +211,7 @@ namespace IdentityServer4.Quickstart.UI.Controllers
|
|||||||
|
|
||||||
// get context information (client name, post logout redirect URI and iframe for federated signout)
|
// get context information (client name, post logout redirect URI and iframe for federated signout)
|
||||||
var logout = await _interaction.GetLogoutContextAsync(model.LogoutId);
|
var logout = await _interaction.GetLogoutContextAsync(model.LogoutId);
|
||||||
|
return Redirect(logout?.PostLogoutRedirectUri);
|
||||||
var vm = new LoggedOutViewModel
|
|
||||||
{
|
|
||||||
PostLogoutRedirectUri = logout?.PostLogoutRedirectUri,
|
|
||||||
ClientName = logout?.ClientId,
|
|
||||||
SignOutIframeUrl = logout?.SignOutIFrameUrl
|
|
||||||
};
|
|
||||||
|
|
||||||
return View("LoggedOut", vm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
|
||||||
|
using eShopOnContainers.Identity;
|
||||||
using IdentityServer4.Quickstart.UI.Models;
|
using IdentityServer4.Quickstart.UI.Models;
|
||||||
using IdentityServer4.Services;
|
using IdentityServer4.Services;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace IdentityServer4.Quickstart.UI.Controllers
|
namespace IdentityServer4.Quickstart.UI.Controllers
|
||||||
@ -12,14 +14,19 @@ namespace IdentityServer4.Quickstart.UI.Controllers
|
|||||||
public class HomeController : Controller
|
public class HomeController : Controller
|
||||||
{
|
{
|
||||||
private readonly IIdentityServerInteractionService _interaction;
|
private readonly IIdentityServerInteractionService _interaction;
|
||||||
|
private readonly IOptions<AppSettings> _settings;
|
||||||
|
|
||||||
public HomeController(IIdentityServerInteractionService interaction)
|
public HomeController(IIdentityServerInteractionService interaction, IOptions<AppSettings> settings)
|
||||||
{
|
{
|
||||||
_interaction = interaction;
|
_interaction = interaction;
|
||||||
|
_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IActionResult Index()
|
public IActionResult Index(string returnUrl)
|
||||||
{
|
{
|
||||||
|
if (returnUrl != "")
|
||||||
|
return Redirect(_settings.Value.MvcClient);
|
||||||
|
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,8 +51,8 @@ namespace eShopOnContainers.Identity
|
|||||||
services.AddIdentity<ApplicationUser, IdentityRole>()
|
services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||||
.AddEntityFrameworkStores<ApplicationDbContext>()
|
.AddEntityFrameworkStores<ApplicationDbContext>()
|
||||||
.AddDefaultTokenProviders();
|
.AddDefaultTokenProviders();
|
||||||
|
|
||||||
|
services.Configure<AppSettings>(Configuration);
|
||||||
|
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
|
|
||||||
|
@ -18,20 +18,6 @@
|
|||||||
<div class="navbar-brand"></div>
|
<div class="navbar-brand"></div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<a asp-action="Register" asp-controller="Account">Register User</a>
|
|
||||||
</div>
|
|
||||||
@*@if (User.Identity.IsAuthenticated)
|
|
||||||
{
|
|
||||||
<ul class="nav navbar-nav">
|
|
||||||
<li class="dropdown">
|
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">@User.Identity.Name <b class="caret"></b></a>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
<li><a asp-action="Logout" asp-controller="Account">Logout</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
}*@
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"DefaultConnection": "Server=127.0.0.1,5433;Database=aspnet-Microsoft.eShopOnContainers;User Id=sa;Password=Pass@word"
|
"DefaultConnection": "Server=127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.IdentityDb;User Id=sa;Password=Pass@word"
|
||||||
},
|
},
|
||||||
"MvcClient": "http://localhost:5100",
|
"MvcClient": "http://localhost:5100",
|
||||||
"SpaClient": "http://localhost:5104",
|
"SpaClient": "http://localhost:5104",
|
||||||
|
@ -5,7 +5,7 @@ services:
|
|||||||
image: eshop/identity
|
image: eshop/identity
|
||||||
environment:
|
environment:
|
||||||
- SpaClient=http://localhost:5104
|
- SpaClient=http://localhost:5104
|
||||||
- ConnectionStrings__DefaultConnection=Server=identity.data;Database=aspnet-Microsoft.eShopOnContainers;User Id=sa;Password=Pass@word
|
- ConnectionStrings__DefaultConnection=Server=identity.data;Database=Microsoft.eShopOnContainers.Services.IdentityDb;User Id=sa;Password=Pass@word
|
||||||
#- MvcClient=http://104.40.62.65:5100 #Remote: VM Needs to have public access at 5105.
|
#- MvcClient=http://104.40.62.65:5100 #Remote: VM Needs to have public access at 5105.
|
||||||
- MvcClient=http://localhost:5100 #Local: You need a entry in windows host file to run identity in local docker.
|
- MvcClient=http://localhost:5100 #Local: You need a entry in windows host file to run identity in local docker.
|
||||||
ports:
|
ports:
|
||||||
@ -13,7 +13,7 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- identity.data
|
- identity.data
|
||||||
|
|
||||||
identity.data:
|
sql.data:
|
||||||
image: microsoft/mssql-server-linux
|
image: microsoft/mssql-server-linux
|
||||||
environment:
|
environment:
|
||||||
- SA_PASSWORD=Pass@word
|
- SA_PASSWORD=Pass@word
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Ordering.Api.Application.Commands
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using MediatR;
|
||||||
|
using Domain;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class NewOrderRequest
|
||||||
|
:IAsyncRequest<bool>
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly List<OrderItem> _orderItems;
|
||||||
|
public string City { get; set; }
|
||||||
|
|
||||||
|
public string Street { get; set; }
|
||||||
|
|
||||||
|
public string State { get; set; }
|
||||||
|
|
||||||
|
public string Country { get; set; }
|
||||||
|
|
||||||
|
public string ZipCode { get; set; }
|
||||||
|
|
||||||
|
public string CardNumber { get; set; }
|
||||||
|
|
||||||
|
public string CardHolderName { get; set; }
|
||||||
|
|
||||||
|
public DateTime CardExpiration { get; set; }
|
||||||
|
|
||||||
|
public string CardSecurityNumber { get; set; }
|
||||||
|
|
||||||
|
public int CardTypeId { get; set; }
|
||||||
|
|
||||||
|
public string Buyer { get; set; }
|
||||||
|
|
||||||
|
public IEnumerable<OrderItem> OrderItems => _orderItems;
|
||||||
|
|
||||||
|
public void AddOrderItem(OrderItem item)
|
||||||
|
{
|
||||||
|
_orderItems.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NewOrderRequest()
|
||||||
|
{
|
||||||
|
_orderItems = new List<OrderItem>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,118 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Ordering.Api.Application.Commands
|
||||||
|
{
|
||||||
|
using Domain.Repositories;
|
||||||
|
using MediatR;
|
||||||
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Domain;
|
||||||
|
|
||||||
|
public class NewOrderRequestHandler
|
||||||
|
: IAsyncRequestHandler<NewOrderRequest, bool>
|
||||||
|
{
|
||||||
|
private readonly IBuyerRepository _buyerRepository;
|
||||||
|
private readonly IOrderRepository _orderRepository;
|
||||||
|
|
||||||
|
public NewOrderRequestHandler(IBuyerRepository buyerRepository,IOrderRepository orderRepository)
|
||||||
|
{
|
||||||
|
if (buyerRepository == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(buyerRepository));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orderRepository == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(orderRepository));
|
||||||
|
}
|
||||||
|
|
||||||
|
_buyerRepository = buyerRepository;
|
||||||
|
_orderRepository = orderRepository;
|
||||||
|
}
|
||||||
|
public async Task<bool> Handle(NewOrderRequest message)
|
||||||
|
{
|
||||||
|
//find buyer/payment or add a new one buyer/payment
|
||||||
|
|
||||||
|
var buyer = await _buyerRepository.FindAsync(message.Buyer);
|
||||||
|
|
||||||
|
if (buyer == null)
|
||||||
|
{
|
||||||
|
buyer = CreateBuyer(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
var payment = GetExistingPaymentOrAddANewOne(buyer, message);
|
||||||
|
|
||||||
|
await _buyerRepository.UnitOfWork
|
||||||
|
.SaveChangesAsync();
|
||||||
|
|
||||||
|
//create order for buyer and payment method
|
||||||
|
|
||||||
|
var order = CreateOrder(buyer.Id, payment.Id, 0);
|
||||||
|
order.SetAddress( new Address()
|
||||||
|
{
|
||||||
|
City = message.City,
|
||||||
|
State = message.State,
|
||||||
|
Street = message.Street,
|
||||||
|
ZipCode = message.ZipCode
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (var item in message.OrderItems)
|
||||||
|
{
|
||||||
|
order.AddOrderItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
_orderRepository.Add(order);
|
||||||
|
|
||||||
|
var result = await _orderRepository.UnitOfWork
|
||||||
|
.SaveChangesAsync();
|
||||||
|
|
||||||
|
return result > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Payment GetExistingPaymentOrAddANewOne(Buyer buyer, NewOrderRequest message)
|
||||||
|
{
|
||||||
|
Payment payment = PaymentAlreadyExist(buyer, message);
|
||||||
|
|
||||||
|
if (payment == null)
|
||||||
|
{
|
||||||
|
payment = CreatePayment(message);
|
||||||
|
buyer.Payments.Add(payment);
|
||||||
|
}
|
||||||
|
|
||||||
|
return payment;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Payment PaymentAlreadyExist(Domain.Buyer buyer, NewOrderRequest message)
|
||||||
|
{
|
||||||
|
return buyer.Payments
|
||||||
|
.SingleOrDefault(p =>
|
||||||
|
{
|
||||||
|
return p.CardHolderName == message.CardHolderName
|
||||||
|
&&
|
||||||
|
p.CardNumber == message.CardNumber
|
||||||
|
&&
|
||||||
|
p.Expiration == message.CardExpiration
|
||||||
|
&&
|
||||||
|
p.SecurityNumber == message.CardSecurityNumber;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Buyer CreateBuyer(NewOrderRequest message)
|
||||||
|
{
|
||||||
|
return _buyerRepository.Add(
|
||||||
|
new Buyer(message.Buyer));
|
||||||
|
}
|
||||||
|
|
||||||
|
Order CreateOrder(int buyerId, int paymentId, int addressId)
|
||||||
|
{
|
||||||
|
return new Order(buyerId, paymentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Payment CreatePayment(NewOrderRequest message)
|
||||||
|
{
|
||||||
|
return new Payment(message.CardNumber, message.CardSecurityNumber, message.CardHolderName, message.CardExpiration, message.CardTypeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Ordering.Api.Application.Decorators
|
||||||
|
{
|
||||||
|
using Extensions.Logging;
|
||||||
|
using MediatR;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public class LogDecorator<TRequest, TResponse>
|
||||||
|
: IAsyncRequestHandler<TRequest, TResponse>
|
||||||
|
where TRequest : IAsyncRequest<TResponse>
|
||||||
|
{
|
||||||
|
private readonly IAsyncRequestHandler<TRequest, TResponse> _inner;
|
||||||
|
private readonly ILogger<LogDecorator<TRequest, TResponse>> _logger;
|
||||||
|
|
||||||
|
|
||||||
|
public LogDecorator(
|
||||||
|
IAsyncRequestHandler<TRequest, TResponse> inner,
|
||||||
|
ILogger<LogDecorator<TRequest, TResponse>> logger)
|
||||||
|
{
|
||||||
|
_inner = inner;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<TResponse> Handle(TRequest message)
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"Executing command {_inner.GetType().FullName}");
|
||||||
|
|
||||||
|
var response = await _inner.Handle(message);
|
||||||
|
|
||||||
|
_logger.LogInformation($"Succedded executed command {_inner.GetType().FullName}");
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Ordering.Api.Application.Queries
|
||||||
|
{
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public interface IOrderQueries
|
||||||
|
{
|
||||||
|
Task<dynamic> GetOrder(int id);
|
||||||
|
|
||||||
|
Task<dynamic> GetOrders();
|
||||||
|
|
||||||
|
Task<dynamic> GetCardTypes();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Ordering.Api.Application.Queries
|
||||||
|
{
|
||||||
|
using Dapper;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class OrderQueries
|
||||||
|
:IOrderQueries
|
||||||
|
{
|
||||||
|
private string _connectionString = string.Empty;
|
||||||
|
|
||||||
|
public OrderQueries(IConfiguration configuration)
|
||||||
|
{
|
||||||
|
_connectionString = configuration["ConnectionString"];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<dynamic> GetOrder(int id)
|
||||||
|
{
|
||||||
|
using (var connection = new SqlConnection(_connectionString))
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
|
||||||
|
var result = await connection.QueryAsync<dynamic>(
|
||||||
|
@"select o.[Id] as ordernumber,o.OrderDate as date, os.Name as status,
|
||||||
|
oi.ProductName as productname, oi.Units as units, oi.UnitPrice as unitprice, oi.PictureUrl as pictureurl,
|
||||||
|
oa.Street as street, oa.City as city, oa.Country as country, oa.State as state, oa.ZipCode as zipcode
|
||||||
|
FROM ordering.Orders o
|
||||||
|
LEFT JOIN ordering.Orderitems oi ON o.Id = oi.orderid
|
||||||
|
LEFT JOIN ordering.orderstatus os on o.StatusId = os.Id
|
||||||
|
LEFT JOIN ordering.address oa on o.ShippingAddressId = oa.Id
|
||||||
|
WHERE o.Id=@id"
|
||||||
|
, new { id }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.AsList().Count == 0)
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
|
||||||
|
return MapOrderItems(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<dynamic> GetOrders()
|
||||||
|
{
|
||||||
|
using (var connection = new SqlConnection(_connectionString))
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
|
||||||
|
return await connection.QueryAsync<dynamic>(@"SELECT o.[Id] as ordernumber,o.[OrderDate] as [date],os.[Name] as [status],SUM(oi.units*oi.unitprice) as total
|
||||||
|
FROM [ordering].[Orders] o
|
||||||
|
LEFT JOIN[ordering].[orderitems] oi ON o.Id = oi.orderid
|
||||||
|
LEFT JOIN[ordering].[orderstatus] os on o.StatusId = os.Id
|
||||||
|
GROUP BY o.[Id], o.[OrderDate], os.[Name]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<dynamic> GetCardTypes()
|
||||||
|
{
|
||||||
|
using (var connection = new SqlConnection(_connectionString))
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
|
||||||
|
return await connection.QueryAsync<dynamic>("SELECT * FROM ordering.cardtypes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private dynamic MapOrderItems(dynamic result)
|
||||||
|
{
|
||||||
|
dynamic order = new ExpandoObject();
|
||||||
|
|
||||||
|
order.ordernumber = result[0].ordernumber;
|
||||||
|
order.date = result[0].date;
|
||||||
|
order.status = result[0].status;
|
||||||
|
order.street = result[0].street;
|
||||||
|
order.city = result[0].city;
|
||||||
|
order.zipcode = result[0].zipcode;
|
||||||
|
order.country = result[0].country;
|
||||||
|
|
||||||
|
order.orderitems = new List<dynamic>();
|
||||||
|
order.total = 0;
|
||||||
|
|
||||||
|
foreach (dynamic item in result)
|
||||||
|
{
|
||||||
|
dynamic orderitem = new ExpandoObject();
|
||||||
|
orderitem.productname = item.productname;
|
||||||
|
orderitem.units = item.units;
|
||||||
|
orderitem.unitprice = item.unitprice;
|
||||||
|
orderitem.pictureurl = item.pictureurl;
|
||||||
|
|
||||||
|
order.total += item.units * item.unitprice;
|
||||||
|
order.orderitems.Add(orderitem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers
|
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers
|
||||||
{
|
{
|
||||||
using Application.Commands;
|
using Api.Application.Commands;
|
||||||
using Application.Queries;
|
using Api.Application.Queries;
|
||||||
using AspNetCore.Authorization;
|
using AspNetCore.Authorization;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
@ -11,7 +11,7 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
[Route("api/v1/[controller]")]
|
[Route("api/v1/[controller]")]
|
||||||
[Authorize]
|
//[Authorize]
|
||||||
public class OrdersController : Controller
|
public class OrdersController : Controller
|
||||||
{
|
{
|
||||||
private readonly IMediator _mediator;
|
private readonly IMediator _mediator;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.AutofacModules
|
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.AutofacModules
|
||||||
{
|
{
|
||||||
using Application.Queries;
|
using Api.Application.Queries;
|
||||||
using Autofac;
|
using Autofac;
|
||||||
using Domain.Repositories;
|
using Domain.Repositories;
|
||||||
using Ordering.Infrastructure.Repositories;
|
using Ordering.Infrastructure.Repositories;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.AutofacModules
|
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.AutofacModules
|
||||||
{
|
{
|
||||||
using Application.Commands;
|
using Api.Application.Commands;
|
||||||
using Application.Decorators;
|
using Api.Application.Decorators;
|
||||||
using Autofac;
|
using Autofac;
|
||||||
using Autofac.Core;
|
using Autofac.Core;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
|
@ -19,16 +19,16 @@
|
|||||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
|
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
|
||||||
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.1",
|
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.1",
|
||||||
"Microsoft.EntityFrameworkCore": "1.0.1",
|
"Microsoft.EntityFrameworkCore": "1.0.1",
|
||||||
"Microsoft.EntityFrameworkCore.Design" : "1.0.0-preview2-final",
|
"Microsoft.EntityFrameworkCore.Design": "1.0.0-preview2-final",
|
||||||
"Microsoft.EntityFrameworkCore.SqlServer.Design": "1.0.1",
|
"Microsoft.EntityFrameworkCore.SqlServer.Design": "1.0.1",
|
||||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||||
"Swashbuckle": "6.0.0-beta902",
|
"Swashbuckle": "6.0.0-beta902",
|
||||||
"MediatR": "2.1.0",
|
"MediatR": "2.1.0",
|
||||||
"Ordering.Domain": "1.0.0-*",
|
"Ordering.Domain": "1.0.0-*",
|
||||||
"Ordering.Application": "1.0.0-*",
|
|
||||||
"Ordering.Infrastructure": "1.0.0-*",
|
"Ordering.Infrastructure": "1.0.0-*",
|
||||||
"System.Reflection": "4.3.0",
|
"System.Reflection": "4.3.0",
|
||||||
"IdentityServer4.AccessTokenValidation": "1.0.1-rc3"
|
"IdentityServer4.AccessTokenValidation": "1.0.1-rc3",
|
||||||
|
"Dapper": "1.50.2"
|
||||||
},
|
},
|
||||||
"tools": {
|
"tools": {
|
||||||
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",
|
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",
|
||||||
|
@ -65,7 +65,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
|
|||||||
|
|
||||||
order.CardNumber = user.CardNumber;
|
order.CardNumber = user.CardNumber;
|
||||||
order.CardHolderName = user.CardHolderName;
|
order.CardHolderName = user.CardHolderName;
|
||||||
//order.CardExpiration = user.Expiration;
|
order.CardExpiration = new DateTime(1,int.Parse(user.Expiration.Split('/')[0]), int.Parse("20" + user.Expiration.Split('/')[1]));
|
||||||
order.CardSecurityNumber = user.SecurityNumber;
|
order.CardSecurityNumber = user.SecurityNumber;
|
||||||
|
|
||||||
return order;
|
return order;
|
||||||
|
2
src/Web/WebMVC/wwwroot/css/site.min.css
vendored
2
src/Web/WebMVC/wwwroot/css/site.min.css
vendored
File diff suppressed because one or more lines are too long
@ -18,7 +18,7 @@ namespace eShopConContainers.WebSPA
|
|||||||
.UseConfiguration(config)
|
.UseConfiguration(config)
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
.UseIISIntegration()
|
.UseIISIntegration()
|
||||||
//.UseUrls("http://localhost:1250/")
|
.UseUrls("http://localhost:5104/")
|
||||||
.UseStartup<Startup>()
|
.UseStartup<Startup>()
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user