Files
Complex/Complex.EndPoint/Program.cs
alireza adcee56ce8 fix: update migration timestamp and correct city IDs in data seeder
- Update EF Core migration history timestamp from 20260608225159 to 20260608225845
- Fix CityId values in Complex seed data to use new composite format (provinceId*100+cityId)
  - Tehran: 1 → 801 (provinceId=8, cityId=1)
  - Isfahan: 3 → 401 (provinceId=4, cityId=1)
2026-06-09 02:45:46 +03:30

252 lines
9.7 KiB
C#

using Complex.Application;
using Complex.Application.AppCommon;
using Complex.Application.Basic;
using Complex.Application.Complex;
using Complex.Application.PersonService;
using Complex.Application.Services.Basic;
using Complex.Application.Services.Utility;
using Complex.Infrastructure;
using Complex.Mapping;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Pomelo.EntityFrameworkCore.MySql.Infrastructure;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Reflection;
using System.Text;
using WebApi.Bugeto.Models.Services.Validator;
using Complex.Application.Services.TransactionServices;
using Complex.Application.Services.Announcement;
using Complex.Application.Services.Dashboard;
var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
// Add services to the container.
builder.Services.AddControllers().AddNewtonsoftJson(a => a.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddScoped<IComplexDBContext, ComplexDBContext>();
builder.Services.AddScoped<IPersonService, PersonService>();
builder.Services.AddScoped<IAppCommonService, AppCommonService>();
builder.Services.AddScoped<IBasicService, BasicService>();
builder.Services.AddScoped<IComplexService, ComplexService>();
builder.Services.AddScoped<IUnitService, UnitService>();
builder.Services.AddScoped<CostService, CostService>();
builder.Services.AddScoped<ISiteAccountlService, SiteAccountlService>();
builder.Services.AddScoped<IUserTokenService, UserTokenService>();
builder.Services.AddScoped<ISendUserMessage, SmsService>();
builder.Services.AddScoped<ITokenValidator, TokenValidate>();
builder.Services.AddScoped<ITransactionService, TransactionService>();
builder.Services.AddScoped<IAnnouncementService, AnnouncementService>();
builder.Services.AddScoped<IDashboardService, DashboardService>();
//eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOiIqQCFJVE15QXpNX19fSVRPeGtETSIsIk5hbWUiOiIqQCE4S18xXzFfRm1kcllYWV8xXzFfIiwiRmFtaWx5IjoiKkAhKkAhQWpiWFlfMV8xX011ZHJZSExfMV8xXyIsIm5iZiI6MTcwNjg4ODQyOCwiZXhwIjoxNzA5NDgwNDI4LCJpc3MiOiJuYWJha3NvZnQuaXIiLCJhdWQiOiJDb21wbGV4In0.Hz7fF-bRW3KouPOGgc0p5UVCMQmKkroKzGLdmZeXZeg
builder.Services.AddAuthentication(options =>
{
//options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
//options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
//options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
// Adding Jwt Bearer
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = builder.Configuration["JWTConfig:audience"],
ValidIssuer = builder.Configuration["JWTConfig:issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JWTConfig:Key"]))
};
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
//log
//........
return Task.CompletedTask;
},
OnTokenValidated = context =>
{
//log
var tokenValidatorService = context.HttpContext.RequestServices.GetRequiredService<ITokenValidator>();
return tokenValidatorService.Execute(context);
},
OnChallenge = context =>
{
return Task.CompletedTask;
},
OnMessageReceived = context =>
{
return Task.CompletedTask;
},
OnForbidden = context =>
{
return Task.CompletedTask;
}
};
});
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
builder.Services.AddAutoMapper(typeof(MappingProfile), typeof(EndPointMappingProfile));
var contectionString = builder.Configuration.GetConnectionString("ComplexConnection");
builder.Services.AddEntityFrameworkSqlServer().AddDbContext<ComplexDBContext>(
option => option.UseSqlServer(contectionString), ServiceLifetime.Transient);
/*var mariaContectionString = builder.Configuration.GetConnectionString("MariaDbConnectionString");
builder.Services.AddDbContext<ComplexDBContext>(
dbContextOptions => dbContextOptions
.UseMySql(mariaContectionString, new MySqlServerVersion(new Version(10, 6, 8)))
// The following three options help with debugging, but should
// be changed or removed for production.
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging()
.EnableDetailedErrors()
);
*/
builder.Services.AddApiVersioning(Options =>
{
Options.AssumeDefaultVersionWhenUnspecified = true;
Options.DefaultApiVersion = new ApiVersion(1, 0);
Options.ReportApiVersions = true;
});
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = "Complex",
Version = "v1"
});
c.SwaggerDoc("v2", new OpenApiInfo
{
Title = "Complex",
Version = "v2"
});
c.DocInclusionPredicate((doc, apiDescription) =>
{
if (!apiDescription.TryGetMethodInfo(out MethodInfo methodInfo)) return false;
var version = methodInfo.DeclaringType
.GetCustomAttributes<ApiVersionAttribute>(true)
.SelectMany(attr => attr.Versions);
return version.Any(v => $"v{v.ToString()}" == doc);
});
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Name = "Authorization",
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer 1safsfsdfdfd\"",
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement {
{
new OpenApiSecurityScheme {
Reference = new OpenApiReference {
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] {}
}
});
});
var app = builder.Build();
// Apply pending migrations and create database if not exists
using (var scope = app.Services.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<ComplexDBContext>();
// If the database was previously created with EnsureCreated() (no __EFMigrationsHistory),
// seed the history table so Migrate() knows the initial state
if (!dbContext.Database.GetAppliedMigrations().Any())
{
try
{
// Check if any tables exist (meaning EnsureCreated was used before)
var tableCount = dbContext.Database.ExecuteSqlRaw(
"SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'");
if (tableCount > 0)
{
// Create __EFMigrationsHistory if it doesn't exist and seed it
dbContext.Database.ExecuteSqlRaw(
"IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '__EFMigrationsHistory') " +
"BEGIN " +
"CREATE TABLE [__EFMigrationsHistory] ([MigrationId] nvarchar(150) NOT NULL, [ProductVersion] nvarchar(32) NOT NULL, PRIMARY KEY ([MigrationId])); " +
"END " +
"IF NOT EXISTS (SELECT * FROM __EFMigrationsHistory WHERE MigrationId = '20260608225845_InitialCreate') " +
"INSERT INTO __EFMigrationsHistory (MigrationId, ProductVersion) VALUES ('20260608225845_InitialCreate', '6.0.3')");
}
}
catch
{
// Database doesn't exist yet, Migrate() will create it
}
}
dbContext.Database.Migrate();
// Seed essential reference data and test data
await DataSeeder.SeedAsync(dbContext);
}
app.UseExceptionHandler(c => c.Run(async context =>
{
var exception = context.Features
.Get<IExceptionHandlerPathFeature>()
.Error;
var response = new
{
error = exception.Message + Environment.NewLine + exception.StackTrace + (
exception.InnerException == null ? "" : Environment.NewLine + exception.InnerException.Message +
Environment.NewLine + exception.InnerException.StackTrace)
};
await context.Response.WriteAsJsonAsync(response);
}));
app.UseDefaultFiles();
app.UseStaticFiles();
app.MapFallbackToFile("index.html");
// Configure the HTTP request pipeline.
//if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApi.Bugeto v1"));
//app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();