使用 Aspire 启动分布式微服务

This commit is contained in:
hello 2024-11-15 22:42:18 +08:00
parent 81d8f1b3f9
commit b9a6d002ca
7 changed files with 66 additions and 14 deletions

View File

@ -13,7 +13,7 @@ namespace HelloShop.AppHost.Extensions
{ {
public static class DaprSidecarResourceBuilderExtensions public static class DaprSidecarResourceBuilderExtensions
{ {
public static IResourceBuilder<IDaprSidecarResource> WithReference(this IResourceBuilder<IDaprSidecarResource> builder, IResourceBuilder<IResourceWithConnectionString> resourceBuilder, int waitInSeconds = 5) public static IResourceBuilder<IDaprSidecarResource> WithReference(this IResourceBuilder<IDaprSidecarResource> builder, IResourceBuilder<IResourceWithConnectionString> resourceBuilder, int waitInSeconds = 10)
{ {
builder.WithAnnotation(new EnvironmentCallbackAnnotation(async context => builder.WithAnnotation(new EnvironmentCallbackAnnotation(async context =>
{ {

View File

@ -2,16 +2,20 @@
// See the license file in the project root for more information. // See the license file in the project root for more information.
using HelloShop.IdentityService.Entities; using HelloShop.IdentityService.Entities;
using HelloShop.IdentityService.Infrastructure;
using HelloShop.ServiceDefaults.Infrastructure; using HelloShop.ServiceDefaults.Infrastructure;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace HelloShop.IdentityService.DataSeeding namespace HelloShop.IdentityService.DataSeeding
{ {
public class UserDataSeedingProvider(UserManager<User> userManager, RoleManager<Role> roleManager) : IDataSeedingProvider public class UserDataSeedingProvider(UserManager<User> userManager, RoleManager<Role> roleManager) : IDataSeedingProvider
{ {
public async Task SeedingAsync(IServiceProvider ServiceProvider, CancellationToken cancellationToken = default) public async Task SeedingAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken = default)
{ {
await serviceProvider.GetRequiredService<IdentityServiceDbContext>().Database.EnsureCreatedAsync(cancellationToken);
var adminRole = await roleManager.Roles.SingleOrDefaultAsync(x => x.Name == "AdminRole", cancellationToken); var adminRole = await roleManager.Roles.SingleOrDefaultAsync(x => x.Name == "AdminRole", cancellationToken);
if (adminRole == null) if (adminRole == null)

View File

@ -15,9 +15,6 @@ namespace HelloShop.IdentityService.Infrastructure
base.OnModelCreating(modelBuilder); base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
} }
} }
} }

View File

@ -3,6 +3,7 @@
using AutoMapper; using AutoMapper;
using HelloShop.OrderingService.Commands.Orders; using HelloShop.OrderingService.Commands.Orders;
using HelloShop.OrderingService.Entities.Orders;
using HelloShop.OrderingService.Models.Orders; using HelloShop.OrderingService.Models.Orders;
namespace HelloShop.OrderingService.AutoMapper namespace HelloShop.OrderingService.AutoMapper
@ -11,8 +12,10 @@ namespace HelloShop.OrderingService.AutoMapper
{ {
public OrdersMapConfiguration() public OrdersMapConfiguration()
{ {
CreateMap<BasketItem, CreateOrderCommand.CreateOrderCommandItem>().ForMember(dest => dest.Units, opts => opts.MapFrom(src => src.Quantity));
CreateMap<CreateOrderRequest, CreateOrderCommand>().ForMember(dest => dest.OrderItems, opt => opt.MapFrom(src => src.Items)); CreateMap<CreateOrderRequest, CreateOrderCommand>().ForMember(dest => dest.OrderItems, opt => opt.MapFrom(src => src.Items));
CreateMap<BasketItem, CreateOrderCommand.CreateOrderCommandItem>().ForMember(dest => dest.Units, opt => opt.MapFrom(src => src.Quantity));
CreateMap<CreateOrderCommand.CreateOrderCommandItem, OrderItem>();
CreateMap<CreateOrderCommand, Address>();
} }
} }
} }

View File

@ -10,7 +10,9 @@ using HelloShop.ServiceDefaults.DistributedEvents.Abstractions;
using HelloShop.ServiceDefaults.DistributedEvents.DaprBuildingBlocks; using HelloShop.ServiceDefaults.DistributedEvents.DaprBuildingBlocks;
using HelloShop.ServiceDefaults.Extensions; using HelloShop.ServiceDefaults.Extensions;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using System.Reflection; using System.Reflection;
using System.Text;
namespace HelloShop.OrderingService.Extensions namespace HelloShop.OrderingService.Extensions
{ {
@ -18,6 +20,17 @@ namespace HelloShop.OrderingService.Extensions
{ {
public static void AddApplicationServices(this IHostApplicationBuilder builder) public static void AddApplicationServices(this IHostApplicationBuilder builder)
{ {
const string issuerSigningKey = ServiceDefaults.Constants.IdentityConstants.IssuerSigningKey;
builder.Services.AddAuthentication().AddJwtBearer(options =>
{
options.TokenValidationParameters.ValidateIssuer = false;
options.TokenValidationParameters.ValidateAudience = false;
options.TokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(Encoding.Default.GetBytes(issuerSigningKey));
});
builder.Services.AddHttpContextAccessor();
builder.Services.AddDataSeedingProviders(); builder.Services.AddDataSeedingProviders();
builder.Services.AddDbContext<OrderingServiceDbContext>(options => builder.Services.AddDbContext<OrderingServiceDbContext>(options =>
@ -30,9 +43,9 @@ namespace HelloShop.OrderingService.Extensions
builder.Services.AddMediatR(options => builder.Services.AddMediatR(options =>
{ {
options.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()); options.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly());
options.AddBehavior(typeof(LoggingBehavior<,>)); options.AddOpenBehavior(typeof(LoggingBehavior<,>));
options.AddBehavior(typeof(ValidatorBehavior<,>)); options.AddOpenBehavior(typeof(ValidatorBehavior<,>));
options.AddBehavior(typeof(TransactionBehavior<,>)); options.AddOpenBehavior(typeof(TransactionBehavior<,>));
}); });
builder.Services.AddModelMapper().AddModelValidator(); builder.Services.AddModelMapper().AddModelValidator();
@ -50,10 +63,14 @@ namespace HelloShop.OrderingService.Extensions
builder.Services.AddHostedService<PaymentWorker>(); builder.Services.AddHostedService<PaymentWorker>();
builder.Services.AddTransient<IDistributedEventService, DistributedEventService<OrderingServiceDbContext>>(); builder.Services.AddTransient<IDistributedEventService, DistributedEventService<OrderingServiceDbContext>>();
builder.Services.AddOpenApi();
} }
public static WebApplication MapApplicationEndpoints(this WebApplication app) public static WebApplication MapApplicationEndpoints(this WebApplication app)
{ {
app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
app.UseOpenApi();
app.UseDataSeedingProviders(); app.UseDataSeedingProviders();
app.MapDaprDistributedEventBus(); app.MapDaprDistributedEventBus();

View File

@ -1,6 +1,37 @@
@HelloShop.OrderingService_HostAddress = http://localhost:5015 @HelloShop.OrderingService_HostAddress = https://localhost:8105
GET {{HelloShop.OrderingService_HostAddress}}/weatherforecast/ POST {{HelloShop.OrderingService_HostAddress}}/api/orders
Accept: application/json Content-Type: application/json
x-request-id: 5ddc1737-6a31-4b4f-bccd-63d0966348a1
Authorization : Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIxIiwidW5pcXVlX25hbWUiOiJhZG1pbiIsInJvbGVpZCI6IjEiLCJuYmYiOjE3MjA1NzY3NDYsImV4cCI6MTc0MjYwODc0NiwiaWF0IjoxNzIwNTc2NzQ2fQ.ju_D3zeGLKqJYVckbb8Y3yNkp40nOqRAJrdOsISs4d4
### {
"country": "USA",
"state": "CA",
"city": "San Francisco",
"street": "123 Market St",
"zipCode": "941032",
"cardAlias": "Jack",
"cardNumber": "4111111111111111",
"cardHolderName": "John Doe",
"cardSecurityNumber": "123456",
"cardExpiration": "2025-12-31T23:59:59Z",
"items": [
{
"productId": 100,
"productName": "Smartphone",
"quantity": 1,
"unitPrice": 699.99,
"pictureUrl": "https://example.com/images/phone-123.jpg"
},
{
"productId": 101,
"productName": "Tablet",
"quantity": 2,
"unitPrice": 499.99,
"pictureUrl": "https://example.com/images/tablet-456.jpg"
}
]
}
###

View File

@ -13,7 +13,7 @@ public class ProductEntityTypeConfiguration : IEntityTypeConfiguration<Product>
{ {
builder.ToTable("Products"); builder.ToTable("Products");
builder.Property(x => x.Name).HasMaxLength(32); builder.Property(x => x.Name).HasMaxLength(64);
builder.Property(x => x.ImageUrl).HasMaxLength(256); builder.Property(x => x.ImageUrl).HasMaxLength(256);