Files
QYZH.InteractiveMagazine/QYZH.InteractiveMagazine.Infrastructure/Extensions/InteractiveMagazineApiDefaultsExtensions.cs
glz f7f505d109 refactor(api): 提取公共API默认配置并修复积分并发问题
1.  新增InteractiveMagazineApiDefaultsExtensions统一注册共享服务,简化WeChatApi和WebApi的Program.cs代码
2.  修复积分增减的并发问题,改用原子更新操作,添加余额校验避免超扣
3.  修复注释乱码问题,将简体中文注释替换为正确文本
4.  新增.editorconfig配置统一代码格式
2026-07-07 18:01:17 +08:00

86 lines
3.5 KiB
C#

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using QYZH.InteractiveMagazine.Common.Helpers;
using QYZH.InteractiveMagazine.Infrastructure.Middleware;
using QYZH.InteractiveMagazine.Infrastructure.RabbitMQ;
using QYZH.InteractiveMagazine.Infrastructure.Redis;
using QYZH.InteractiveMagazine.Infrastructure.SDK;
using QYZH.InteractiveMagazine.Models.Settings;
using System.Text.Json.Serialization;
namespace QYZH.InteractiveMagazine.Infrastructure.Extensions;
/// <summary>
/// API 默认服务注册扩展。
/// </summary>
public static class InteractiveMagazineApiDefaultsExtensions
{
/// <summary>
/// 注册 WebApi 与 WeChatApi 共享的默认服务。
/// </summary>
/// <param name="builder">应用构建器。</param>
/// <returns>应用构建器。</returns>
public static WebApplicationBuilder AddInteractiveMagazineApiDefaults(this WebApplicationBuilder builder)
{
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), "DataProtection")));
builder.Services.AddCSRedisCacheExtension(builder.Configuration.GetSection("RedisSettings"));
builder.Services.AddRabbitMQ(builder.Configuration);
builder.Services.AddControllers(options =>
{
options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true;
options.Filters.Add<ModelValidActionFilterAttribute>();
})
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
options.JsonSerializerOptions.Converters.Add(new JsonConverterUtil.DateTimeConverter());
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
})
.ConfigureApiBehaviorOptions(opt => opt.SuppressModelStateInvalidFilter = true);
builder.Services.AddEndpointsApiExplorer();
builder.AddCorsRegister();
builder.Services.AddHttpClient();
builder.Services.AddHttpContextAccessor();
builder.Services.AddInfrastructureServices(builder.Configuration, builder.Environment);
builder.Services.AddSDKService(builder.Configuration);
builder.Services.Configure<MedalRuleConfigSettings>(builder.Configuration.GetSection("MedalRuleConfig"));
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll", policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
builder.Services.Configure<BrotliCompressionProviderOptions>(options =>
{
options.Level = System.IO.Compression.CompressionLevel.Optimal;
});
builder.Services.Configure<GzipCompressionProviderOptions>(options =>
{
options.Level = System.IO.Compression.CompressionLevel.Fastest;
});
builder.Services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(["image/svg+xml", "application/json", "text/plain"]);
});
return builder;
}
}