Maggsoft Framework, ASP.NET Core 8 tabanlı modern web uygulamaları geliştirmek için tasarlanmış kapsamlı bir framework'tür. Clean Architecture prensiplerini takip eden, modüler yapıda ve çoklu veritabanı desteği sunan bir çözümdür.
- 🚀 Hızlı Geliştirme: Hazır bileşenler ve extension'lar ile hızlı proje geliştirme
- 🧩 Modüler Yapı: Bağımsız ve yeniden kullanılabilir modüller
- 🗄️ Çoklu Veritabanı Desteği: MSSQL, PostgreSQL, SQLite, MongoDB desteği
- 📡 Event-Driven Architecture: Mikroservis mimarisi için event bus desteği
- ⚡ Caching: Memory ve Redis cache desteği
- 🔧 AOP (Aspect-Oriented Programming): Cross-cutting concerns için aspect desteği
- 🏗️ Clean Architecture: Katmanlı mimari ve dependency injection
maggsoft-framework-project (13 projects)
├── Libraries/ # Core kütüphaneler (9 projects)
│ ├── Data/ # Veritabanı katmanı (1 project)
│ │ └── Maggsoft.Data.Mssql/ # MSSQL desteği
│ ├── Endpoints/ # Endpoint katmanı (2 projects)
│ │ ├── Maggsoft.Endpoints.Api/ # API Endpoints
│ │ └── Maggsoft.Endpoints.BackgroundServicesApi/ # Background Services API
│ ├── SmsProvider/ # SMS Provider (1 project)
│ │ └── Maggsoft.SmsProviders/ # SMS servis sağlayıcıları
│ ├── Maggsoft.BackgroundServices/ # Background Services
│ ├── Maggsoft.IdentityManager/ # Identity Management
│ ├── Maggsoft.Mssql/ # MSSQL Repository
│ └── Maggsoft.Mssql.Services/ # MSSQL Services
├── Presentation/ # Sunum katmanı (4 projects)
│ ├── Api/ # API projeleri (2 projects)
│ │ ├── Maggsoft.Api/ # Ana API projesi
│ │ └── Maggsoft.BackgroundServices.API/ # Background Services API
│ └── Web/ # Web projeleri (2 projects)
│ ├── Maggsoft.Web/ # Ana Web projesi
│ └── Maggsoft.Web.Framework/ # Web Framework
└── Solution Items/ # Konfigürasyon dosyaları
├── api-deploy.yml # API deployment
├── api-deploy-stage.yml # API staging deployment
├── Directory.Packages.props # NuGet paket yönetimi
├── job-deploy.yml # Background job deployment
├── nuget.config # NuGet konfigürasyonu
├── web-deploy.yml # Web deployment
└── web-deploy-stage.yml # Web staging deployment
# Yeni bir ASP.NET Core Web API projesi oluştur
dotnet new webapi -n MyMaggsoftProject
# Proje dizinine git
cd MyMaggsoftProject<!-- Core paketler -->
<PackageReference Include="Maggsoft.Core" Version="2.1.3" />
<PackageReference Include="Maggsoft.Data" Version="2.1.7" />
<PackageReference Include="Maggsoft.Mssql" Version="2.1.0" />
<PackageReference Include="Maggsoft.Framework" Version="2.3.9" />
<!-- Cache paketleri -->
<PackageReference Include="Maggsoft.Cache.MemoryCache" Version="2.0.7" />
<PackageReference Include="Maggsoft.Cache.Redis" Version="2.0.3" />
<!-- Event Bus paketleri -->
<PackageReference Include="Maggsoft.EventBus" Version="1.1.0" />
<PackageReference Include="Maggsoft.EventBus.RabbitMQ" Version="1.0.17" />
<!-- AOP paketi -->
<PackageReference Include="Maggsoft.Aspect.Core" Version="1.0.15" />
<!-- Servis paketleri -->
<PackageReference Include="Maggsoft.Services" Version="2.0.8" />
<PackageReference Include="Maggsoft.Endpoints" Version="2.0.7" />
<PackageReference Include="Maggsoft.Logging" Version="1.0.6" />using Maggsoft.Framework.Systems;
var builder = WebApplication.CreateBuilder(args);
// Infrastructure konfigürasyonu (tüm konfigürasyonları tek seferde yapar)
builder.Services.AddInfrastructure(builder.Configuration);
// Veritabanı konfigürasyonu
builder.Services.AddMssqlConfig<AppContext>(builder.Configuration)
.AddFluentMigratorConfig(builder.Configuration);
// Cache konfigürasyonu
builder.Services.AddMaggsoftDistributedMemoryCache(typeof(IService));
// Event bus konfigürasyonu
builder.Services.AddEventBus(builder.Configuration);
builder.Services.RegisterEventConsumer();
var app = builder.Build();
// Infrastructure middleware'leri
app.AddInfrastructure();
// Veritabanı migration
app.AddUpMigrate();
app.Run();public class User : IBaseEntity<int>
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatorIP { get; set; }
public Guid CreatorUserId { get; set; }
public DateTime? UpdatedDate { get; set; }
public string UpdatedIP { get; set; }
public Guid? UpdatedByUserId { get; set; }
}public interface IUserService : IService
{
Task<User> GetUserAsync(int id);
Task<List<User>> GetAllUsersAsync();
Task<User> CreateUserAsync(User user);
}
public class UserService : IUserService
{
private readonly IMssqlRepository<User> _userRepository;
private readonly ICache _cache;
public UserService(IMssqlRepository<User> userRepository, ICache cache)
{
_userRepository = userRepository;
_cache = cache;
}
public async Task<User> GetUserAsync(int id)
{
var cacheKey = $"user_{id}";
return await _cache.GetAsync<User>(cacheKey, TimeSpan.FromMinutes(30), async () =>
{
return await _userRepository.FindByIdAsync(id);
});
}
// Diğer metodlar...
}[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
[HttpGet]
public async Task<IActionResult> GetUsers()
{
var users = await _userService.GetAllUsersAsync();
return Ok(Result<List<User>>.Success(users));
}
[HttpGet("{id}")]
public async Task<IActionResult> GetUser(int id)
{
var user = await _userService.GetUserAsync(id);
if (user == null)
return NotFound(Result<User>.Failure("Kullanıcı bulunamadı"));
return Ok(Result<User>.Success(user));
}
}{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=MyProject;Trusted_Connection=true;MultipleActiveResultSets=true"
},
"TokenOptions": {
"AccessTokenExpiration": 60,
"ApiName": "Maggsoft API",
"ApiVersion": "v1",
"ApiBaseUrl": "https://localhost:5001",
"IdentityServerBaseUrl": "https://identity.example.com",
"OidcSwaggerUIClientId": "maggsoft_api_swaggerui",
"OidcApiName": "maggsoft_api",
"AdministrationRole": "Administrator",
"RequireHttpsMetadata": true,
"CorsAllowAnyOrigin": true,
"CorsAllowOrigins": [],
"IgnoreUrls": [],
"SecurityKey": "your-secret-key-here"
},
"ApiVersion": {
"MajorVersion": "1",
"MinorVersion": "0"
},
"IPFilter": {
"WhitelistedIPs": ["192.168.1.1"],
"BlockedIPs": [],
"AllowedIPRanges": ["192.168.1.0/24"],
"BlockedIPRanges": [],
"MaxRequestsPerMinute": 100,
"DefaultAllow": true,
"ExemptPaths": ["/health", "/metrics"]
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning"
}
},
"AllowedHosts": "*"
}- Result Pattern: Standart API yanıt formatı
- Repository Pattern: Generic repository implementasyonu
- Extension Methods: String, DateTime, Enumerable extension'ları
- Error Handling: Merkezi hata yönetimi
- Base Entity: Audit bilgileri ile temel entity sınıfı
- Multi-Database Support: MSSQL, PostgreSQL, SQLite, MongoDB
- Migration System: FluentMigrator entegrasyonu
- Unit of Work: Transaction yönetimi
- Memory Cache: In-memory caching
- Redis Cache: Distributed caching
- Cache Patterns: Get-or-set, sliding expiration
- Cache Invalidation: Pattern-based invalidation
- Integration Events: Mikroservisler arası iletişim
- Event Handlers: Async event processing
- Event Publishing: Publish-subscribe pattern
- Multiple Transport: RabbitMQ, Azure Service Bus
- Logging Aspects: Otomatik loglama
- Cache Aspects: Method-level caching
- Validation Aspects: Cross-cutting validation
- Custom Aspects: Özelleştirilebilir aspect'ler
- Infrastructure Setup: Tek seferde tüm konfigürasyon
- Middleware Pipeline: Exception, API Response, IP Filter
- Security: JWT Authentication, IP Filtering
- API Documentation: Swagger entegrasyonu
- Validation: FluentValidation auto-validation
- Compression: Response compression (Brotli, Gzip)
- Excel Export: OpenXML tabanlı Excel export
// Event tanımlama
public class UserCreatedEvent : IntegrationEvent
{
public int UserId { get; set; }
public string Email { get; set; }
}
// Event handler
public class UserCreatedEventHandler : IIntegrationEventHandler<UserCreatedEvent>
{
public async Task HandleAsync(UserCreatedEvent @event)
{
// Email gönderme, bildirim gönderme vb.
await SendWelcomeEmailAsync(@event.Email);
}
}
// Event publishing
await _eventPublisher.PublishAsync(new UserCreatedEvent
{
UserId = user.Id,
Email = user.Email
});public class UserService
{
[LoggingAspect]
[CacheAspect]
public async Task<User> GetUserAsync(int id)
{
return await _userRepository.FindByIdAsync(id);
}
}[HttpGet("export")]
public IActionResult ExportUsers()
{
var users = _userService.GetAllUsers();
var excelData = ExcelOperations.ExportToExcel(users, "Kullanıcılar");
return File(excelData, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "users.xlsx");
}maggsoft-framework-project/
├── Libraries/ # Core kütüphaneler
│ ├── Data/ # Veritabanı katmanı
│ │ └── Maggsoft.Data.Mssql/ # MSSQL desteği
│ ├── Endpoints/ # Endpoint katmanı
│ │ ├── Maggsoft.Endpoints.Api/ # API Endpoints
│ │ └── Maggsoft.Endpoints.BackgroundServicesApi/ # Background Services API
│ ├── SmsProvider/ # SMS Provider
│ │ └── Maggsoft.SmsProviders/ # SMS servis sağlayıcıları
│ ├── Maggsoft.BackgroundServices/ # Background Services
│ ├── Maggsoft.IdentityManager/ # Identity Management
│ ├── Maggsoft.Mssql/ # MSSQL Repository
│ └── Maggsoft.Mssql.Services/ # MSSQL Services
├── Presentation/ # Sunum katmanı
│ ├── Api/ # API projeleri
│ │ ├── Maggsoft.Api/ # Ana API projesi
│ │ └── Maggsoft.BackgroundServices.API/ # Background Services API
│ └── Web/ # Web projeleri
│ ├── Maggsoft.Web/ # Ana Web projesi
│ └── Maggsoft.Web.Framework/ # Web Framework
└── Solution Items/ # Konfigürasyon dosyaları
├── api-deploy.yml # API deployment
├── api-deploy-stage.yml # API staging deployment
├── Directory.Packages.props # NuGet paket yönetimi
├── job-deploy.yml # Background job deployment
├── nuget.config # NuGet konfigürasyonu
├── web-deploy.yml # Web deployment
└── web-deploy-stage.yml # Web staging deployment
- Dependency Injection: Interface-based programming
- Error Handling: Custom exceptions ve global exception handling
- Validation: FluentValidation ile input validation
- Logging: Structured logging ile detaylı loglama
- Caching: Stratejik cache kullanımı
- Security: JWT authentication ve IP filtering
| Paket | Açıklama | Versiyon |
|---|---|---|
Maggsoft.Core |
Temel sınıflar ve extension'lar | 2.1.3 |
Maggsoft.Data |
Base entity'ler ve data katmanı | 2.1.7 |
Maggsoft.Mssql |
MSSQL desteği | 2.1.0 |
Maggsoft.Npgsql |
PostgreSQL desteği | 1.0.6 |
Maggsoft.Sqlite |
SQLite desteği | 2.0.9 |
Maggsoft.Mongo |
MongoDB desteği | 1.0.5 |
Maggsoft.Cache.MemoryCache |
Memory cache | 2.0.7 |
Maggsoft.Cache.Redis |
Redis cache | 2.0.3 |
Maggsoft.EventBus |
Event bus core | 1.1.0 |
Maggsoft.EventBus.RabbitMQ |
RabbitMQ transport | 1.0.17 |
Maggsoft.Aspect.Core |
AOP desteği | 1.0.15 |
Maggsoft.Framework |
Web framework | 2.3.9 |
Maggsoft.Services |
Servis katmanı | 2.0.8 |
Maggsoft.Endpoints |
Endpoint katmanı | 2.0.7 |
Maggsoft.Logging |
Logging sistemi | 1.0.6 |
- Bu repository'yi fork edin
- Feature branch oluşturun (
git checkout -b feature/amazing-feature) - Değişikliklerinizi commit edin (
git commit -m 'Add amazing feature') - Branch'inizi push edin (
git push origin feature/amazing-feature) - Pull Request oluşturun
Bu proje MIT lisansı altında lisanslanmıştır. Detaylar için LICENSE dosyasına bakın.
- FileManager ve DrivingLicenseExamSystem projelerinden esinlenilmiştir
- ASP.NET Core ekibine teşekkürler
- Topluluk katkılarına teşekkürler
- GitHub: maggsoft
- Issues: GitHub Issues
API yanıtlarını standartlaştırmak için kullanılan generic result sınıfları.
// Başarılı yanıt örneği
var result = Result<User>.Success(user);
var resultWithMessage = Result<User>.Success(user, "Kullanıcı başarıyla getirildi");
// Hata yanıtı örneği
var errorResult = Result<User>.Failure("Kullanıcı bulunamadı");
var multipleErrors = Result<User>.Failure(["Hata 1", "Hata 2"]);
// Kullanım örneği
public async Task<Result<User>> GetUserByIdAsync(int id)
{
var user = await _userRepository.FindByIdAsync(id);
if (user == null)
return Result<User>.Failure("Kullanıcı bulunamadı");
return Result<User>.Success(user, "Kullanıcı başarıyla getirildi");
}Result sınıfları şu temel interface'i implement eder:
public interface IResult
{
string Message { get; set; } // Başarı veya hata mesajı
List<string> Errors { get; set; } // Hata listesi
bool IsSuccess { get; set; } // İşlem başarı durumu
}
// Result<T> için ek property
public T Data { get; set; } // İşlem sonucu dataGeneric repository pattern implementasyonu.
public interface IRepository<T> where T : IEntity
{
// READ Operations
IQueryable<T> Get();
Task<IEnumerable<T>> GetAsync();
T Find(Expression<Func<T, bool>> where);
Task<T> FindAsync(Expression<Func<T, bool>> where);
T FindById(object id);
Task<T> FindByIdAsync(object id);
// WRITE Operations
T Add(T entity);
Task<T> AddAsync(T entity);
void AddRange(IEnumerable<T> entities);
Task<IEnumerable<T>> AddRangeAsync(IEnumerable<T> entities);
T Update(T entity);
Task<T> UpdateAsync(T entity);
T Delete(T entity);
Task<T> DeleteAsync(T entity);
// Utility Operations
int Count();
int Count(Expression<Func<T, bool>> @where);
Task<int> CountAsync();
Task<int> CountAsync(Expression<Func<T, bool>> @where);
bool Any();
bool Any(Expression<Func<T, bool>> @where);
Task<bool> AnyAsync();
Task<bool> AnyAsync(Expression<Func<T, bool>> @where);
}Framework'te birçok extension method bulunmaktadır:
// String işlemleri için extension'lar
var slug = "Merhaba Dünya".ToSlug(); // merhaba-dunya
var isEmail = "test@example.com".IsEmail(); // true
var isPhone = "+905551234567".IsPhone(); // true// Tarih işlemleri için extension'lar
var startOfWeek = DateTime.Now.StartOfWeek();
var endOfMonth = DateTime.Now.EndOfMonth();
var isWeekend = DateTime.Now.IsWeekend();// Koleksiyon işlemleri için extension'lar
var distinctBy = users.DistinctBy(x => x.Email);
var chunked = users.Chunk(10);// Genel extension method'lar
var isDefault = value.IsDefault<T>();
var alphaLengthWise = data.AlphaLengthWise();
var isNotNull = obj.IsNotNull();
var hasFilter = filters.HasFilter();
var isGreaterThanZero = count.IsGreaterThanZero();
var cloned = list.Clone<T>();Tüm entity'ler için temel sınıf.
public interface IBaseEntity<TKey> : IBaseEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
TKey Id { get; set; }
[Required]
DateTime CreatedDate { get; set; }
[Required]
[StringLength(50)]
string CreatorIP { get; set; }
[Required]
Guid CreatorUserId { get; set; }
DateTime? UpdatedDate { get; set; }
string UpdatedIP { get; set; }
Guid? UpdatedByUserId { get; set; }
}// Startup.cs'de konfigürasyon
services.AddMssqlConfig<AppContext>(Configuration)
.AddFluentMigratorConfig(Configuration);
// Repository kullanımı
services.AddScoped<IMssqlRepository<User>, Repository<User>>();
services.AddScoped<IUnitOfWork, UnitOfWork>();// Startup.cs'de konfigürasyon
services.AddNpgsqlConfig<AppContext>(Configuration);
// Repository kullanımı
services.AddScoped<INpgsqlRepository<User>, NpgsqlRepository<User>>();// Startup.cs'de konfigürasyon
services.AddSqliteConfig<AppContext>(Configuration);
// Repository kullanımı
services.AddScoped<ISqliteRepository<User>, SqliteRepository<User>>();// Startup.cs'de konfigürasyon
services.AddMongoConfig(Configuration);
// Repository kullanımı
services.AddScoped<IMongoRepository<User>, MongoRepository<User>>();// Startup.cs'de konfigürasyon
services.AddMaggsoftDistributedMemoryCache(typeof(IService));
// Kullanım örneği
public class UserService
{
private readonly ICache _cache;
public UserService(ICache cache)
{
_cache = cache;
}
public async Task<User> GetUserAsync(int id)
{
var cacheKey = $"user_{id}";
return await _cache.GetAsync<User>(cacheKey, TimeSpan.FromMinutes(30), async () =>
{
// Veritabanından kullanıcı getir
return await _userRepository.FindByIdAsync(id);
});
}
public async Task SetUserAsync(User user)
{
var cacheKey = $"user_{user.Id}";
await _cache.SetAsync(cacheKey, TimeSpan.FromMinutes(30), true, user);
}
public async Task RemoveUserAsync(int id)
{
var cacheKey = $"user_{id}";
await _cache.RemoveAsync(cacheKey);
}
public async Task RemoveByPatternAsync(string pattern)
{
await _cache.RemoveByPatternAsync(pattern);
}
public async Task ClearAsync()
{
await _cache.ClearAsync();
}
}// Startup.cs'de konfigürasyon
services.AddMaggsoftDistributedRedisCache(Configuration);
// Kullanım Memory Cache ile aynıdır// Integration Event
public class UserCreatedEvent : IntegrationEvent
{
public int UserId { get; set; }
public string Email { get; set; }
public string Name { get; set; }
}
// Event Handler
public class UserCreatedEventHandler : IIntegrationEventHandler<UserCreatedEvent>
{
private readonly ILogger<UserCreatedEventHandler> _logger;
public UserCreatedEventHandler(ILogger<UserCreatedEventHandler> logger)
{
_logger = logger;
}
public async Task HandleAsync(UserCreatedEvent @event)
{
_logger.LogInformation($"Yeni kullanıcı oluşturuldu: {@event.Email}");
// Email gönderme, bildirim gönderme vb. işlemler
await SendWelcomeEmailAsync(@event.Email);
}
}public class UserService
{
private readonly IEventPublisher _eventPublisher;
public UserService(IEventPublisher eventPublisher)
{
_eventPublisher = eventPublisher;
}
public async Task<User> CreateUserAsync(User user)
{
// Kullanıcı oluştur
var createdUser = await _userRepository.AddAsync(user);
// Event yayınla
var userCreatedEvent = new UserCreatedEvent
{
UserId = createdUser.Id,
Email = createdUser.Email,
Name = createdUser.Name
};
await _eventPublisher.PublishAsync(userCreatedEvent);
return createdUser;
}
}// Startup.cs'de
services.AddEventBus(Configuration);
// Event handler'ları kaydet
services.RegisterEventConsumer();[AttributeUsage(AttributeTargets.Method)]
public class LoggingAspectAttribute : AspectAttribute
{
public override IAspect CreateAspect()
{
return new LoggingAspect();
}
}
public class LoggingAspect : IAspect
{
private ILogger _logger;
public AspectAttribute LoadDependencies(IServiceProvider serviceProvider)
{
_logger = serviceProvider.GetService<ILogger>();
return new LoggingAspectAttribute();
}
public void OnBefore(MethodExecutionArgs args)
{
_logger.LogInformation($"Metod başlatıldı: {args.MethodName}");
}
public void OnAfter(MethodExecutionArgs args)
{
_logger.LogInformation($"Metod tamamlandı: {args.MethodName}");
}
public void OnException(MethodExecutionArgs args)
{
_logger.LogError($"Metod hatası: {args.MethodName}, Hata: {args.Exception.Message}");
}
public void OnSuccess(MethodExecutionArgs args)
{
_logger.LogInformation($"Metod başarılı: {args.MethodName}");
}
}public class UserService
{
[LoggingAspect]
public async Task<User> GetUserAsync(int id)
{
return await _userRepository.FindByIdAsync(id);
}
[LoggingAspect]
[CacheAspect]
public async Task<List<User>> GetAllUsersAsync()
{
return await _userRepository.GetAsync();
}
}Framework'te tüm konfigürasyonları tek seferde yapmak için AddInfrastructure extension method'u bulunmaktadır:
// Program.cs'de veya Startup.cs'de
services.AddInfrastructure(configuration);
// Bu method şu konfigürasyonları yapar:
// - Controllers ve JSON options
// - CORS konfigürasyonu
// - API Versioning
// - Swagger
// - Service registration
// - Exception handler
// - Problem details
// - Response compression
// - Global response middleware
// - Model state response factory
// WebApplication için de extension method:
app.AddInfrastructure();Global exception handling için kullanılır.
// Startup.cs'de konfigürasyon
app.UseExceptionHandler("/Error");
// Program.cs'de
builder.Services.AddExceptionHandler<ExceptionMiddleware>();API yanıtlarını standartlaştırmak için kullanılır.
// Startup.cs'de
app.UseMiddleware<ApiResponseMiddleware>();IP bazlı erişim kontrolü için kullanılır.
// Startup.cs'de
app.UseMiddleware<IPFilterMiddleware>();// Startup.cs'de konfigürasyon
services.AddJwtAuthentication(Configuration);
// Controller'da kullanım
[Authorize]
[ApiController]
public class UserController : ControllerBase
{
[HttpGet]
public async Task<IActionResult> GetUsers()
{
// Implementation
}
}// Startup.cs'de CORS konfigürasyonu
services.AddAdminApiCors(TokenOptions); // TokenOptions ile CORS ayarları
app.UseCorsConfig();
// AddAdminApiCors method'u şu ayarları yapar:
// - TokenOptions.CorsAllowAnyOrigin = true ise AllowAnyOrigin()
// - TokenOptions.CorsAllowOrigins array'i ile özel origin'ler
// - SetIsOriginAllowed((host) => true)
// - AllowAnyHeader()
// - AllowAnyMethod()
// - AccessControlAllowHeaders: "Content-Type"
// UseCorsConfig method'u şu CORS ayarlarını yapar:
// - AllowAnyHeader()
// - AllowAnyMethod()
// - SetIsOriginAllowed((host) => true)
// - AllowCredentials()// Startup.cs'de API Versioning konfigürasyonu
services.AddApiVersioningConfig(configuration);
// Bu extension method API versioning için gerekli servisleri ekler
// appsettings.json'da version bilgileri:
{
"ApiVersion": {
"MajorVersion": "1",
"MinorVersion": "0"
}
}// Startup.cs'de
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Maggsoft API", Version = "v1" });
// JWT authentication için
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
});
});// Startup.cs'de FluentValidation konfigürasyonu
services.AddFluentValidationAutoValidation();
// Validator örneği
public class CreateUserDtoValidator : AbstractValidator<CreateUserDto>
{
public CreateUserDtoValidator()
{
RuleFor(x => x.Name)
.NotEmpty().WithMessage("İsim boş olamaz")
.MaximumLength(100).WithMessage("İsim 100 karakterden uzun olamaz");
RuleFor(x => x.Email)
.NotEmpty().WithMessage("Email boş olamaz")
.EmailAddress().WithMessage("Geçerli bir email adresi giriniz");
}
}// Startup.cs'de Problem Details konfigürasyonu
services.AddProblemDetails();
// Bu servis, HTTP hata yanıtlarını RFC 7807 Problem Details formatında döndürür
// Örnek yanıt:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"Email": ["Email alanı zorunludur"]
}
}// Startup.cs'de Global Response Middleware konfigürasyonu
services.AddGlobalResponseMiddlewareWithOptions(p => p.IgnoreAcceptHeader = ["image/", "txt"]);
// Bu middleware, tüm API yanıtlarını standart Result<T> formatına dönüştürür
// IgnoreAcceptHeader ile belirtilen content type'lar için dönüşüm yapılmaz
// Örnek kullanım:
public class IgnoreResponseOption
{
public string[] IgnoreAcceptHeader { get; set; } = ["image/"];
}// Program.cs'de Exception Handler konfigürasyonu
builder.Services.AddExceptionHandler<ExceptionMiddleware>();
// Bu servis, global exception handling için kullanılır
// Tüm yakalanmamış exception'ları yakalar ve standart formatta yanıt döner// Startup.cs'de JSON konfigürasyonu
services.AddControllers().AddJsonOptionsConfig();
// Bu extension method şu ayarları yapar:
// - PropertyNameCaseInsensitive = true
// - PropertyNamingPolicy = null
// - AllowTrailingCommas = true
// - DecimalToStringConverter ekler
// - TimeSpanConverter ekler
// Custom JSON Converter'lar:
public class DecimalToStringConverter : JsonConverter<decimal>
{
public override decimal Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
{
// Türkçe kültür ayarları ile decimal parsing
var cultureInfo = CultureInfo.CreateSpecificCulture("tr-TR");
// Implementation...
}
public override void Write(Utf8JsonWriter writer, decimal value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}// Startup.cs'de Response Compression konfigürasyonu
services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
options.MimeTypes = ResponseCompressionDefaults.MimeTypes;
});
services.Configure<BrotliCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.Optimal;
});
services.Configure<GzipCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.SmallestSize;
});// Startup.cs'de Model State Response Factory konfigürasyonu
services.Configure<ApiBehaviorOptions>(options =>
{
options.InvalidModelStateResponseFactory = ctx => new ModelStateFeatureFilter();
});
// Bu factory, validation hatalarını standart Result formatında döner
public class ModelStateFeatureFilter : IActionResult
{
public Task ExecuteResultAsync(ActionContext context)
{
var modelState = context.ModelState.GetErrorMessages();
throw new ModelStateException(JsonConvert.SerializeObject(modelState));
}
}IP bazlı erişim kontrolü için gelişmiş bir middleware'dir. Belirli IP adreslerine erişim izni verme, engelleme ve IP aralıklarını kontrol etme özellikleri sunar.
- Whitelist/Blacklist: Belirli IP adreslerine izin verme veya engelleme
- CIDR Desteği: IP aralıklarını CIDR formatında tanımlama
- Path Muafiyeti: Belirli endpoint'leri IP kontrolünden muaf tutma
- Strict Mode: Sadece whitelist'teki IP'lere erişim izni verme
- Rate Limiting: Dakika başına maksimum istek sayısı kontrolü
- Logging: IP erişim logları ve güvenlik olayları
// Startup.cs'de IP Filter konfigürasyonu
services.Configure<IPFilterOptions>(configuration.GetSection("IPFilter"));
// Middleware kullanımı
app.UseMiddleware<IPFilterMiddleware>();
// Veya extension method ile
app.UseIPFilter();{
"IPFilter": {
"WhitelistedIPs": ["192.168.1.1", "10.0.0.1", "::1"],
"BlockedIPs": ["192.168.1.100", "10.0.0.50"],
"AllowedIPRanges": ["192.168.1.0/24", "10.0.0.0/8"],
"BlockedIPRanges": ["172.16.0.0/12"],
"MaxRequestsPerMinute": 100,
"DefaultAllow": true,
"ExemptPaths": ["/health", "/metrics", "/api/status"],
"StrictMode": false
}
}public class IPFilterOptions
{
/// <summary>
/// İzin verilen IP adresleri listesi (Whitelist)
/// </summary>
public List<string> WhitelistedIPs { get; set; } = new();
/// <summary>
/// İzin verilen IP adresleri listesi (Legacy)
/// </summary>
public List<string> AllowedIPs { get; set; } = new();
/// <summary>
/// Yasaklanan IP adresleri listesi (Blacklist)
/// </summary>
public List<string> BlockedIPs { get; set; } = new();
/// <summary>
/// İzin verilen IP aralıkları (CIDR formatında)
/// </summary>
public List<string> AllowedIPRanges { get; set; } = new();
/// <summary>
/// Yasaklanan IP aralıkları (CIDR formatında)
/// </summary>
public List<string> BlockedIPRanges { get; set; } = new();
/// <summary>
/// Dakika başına izin verilen maksimum istek sayısı
/// </summary>
public int MaxRequestsPerMinute { get; set; } = 100;
/// <summary>
/// Varsayılan izin politikası (true: izin ver, false: engelle)
/// </summary>
public bool DefaultAllow { get; set; } = true;
/// <summary>
/// IP filtreleme için muaf tutulacak path'ler
/// </summary>
public List<string> ExemptPaths { get; set; } = new();
/// <summary>
/// Strict Mode: Sadece WhitelistedIPs ve AllowedIPs listesindeki IP'ler erişebilir
/// </summary>
public bool StrictMode { get; set; } = false;
}Strict Mode aktif edildiğinde, sadece WhitelistedIPs ve AllowedIPs listesindeki IP adresleri erişebilir. Bu mod, güvenlik seviyesini maksimuma çıkarır.
// Strict Mode aktif
{
"IPFilter": {
"StrictMode": true,
"WhitelistedIPs": ["192.168.1.100", "10.0.0.10"],
"AllowedIPs": ["127.0.0.1", "::1"],
"DefaultAllow": false // Strict Mode'da bu ayar önemsizdir
}
}Strict Mode Davranışı:
- ✅
WhitelistedIPslistesindeki IP'ler erişebilir - ✅
AllowedIPslistesindeki IP'ler erişebilir - ❌
BlockedIPslistesindeki IP'ler erişemez - ❌ IP aralıkları (CIDR) kontrol edilmez
- ❌
DefaultAllowpolitikası devre dışı kalır - ❌ Sadece whitelist'te olmayan tüm IP'ler engellenir
// Sadece belirli IP'lere izin ver
services.Configure<IPFilterOptions>(options =>
{
options.WhitelistedIPs = ["192.168.1.100", "10.0.0.10"];
options.DefaultAllow = false; // Sadece whitelist'teki IP'ler
});// Production ortamında sıkı güvenlik
services.Configure<IPFilterOptions>(options =>
{
options.StrictMode = true; // En yüksek güvenlik seviyesi
options.WhitelistedIPs = ["203.0.113.1", "198.51.100.1"]; // Sadece production IP'leri
options.ExemptPaths = ["/health", "/metrics"]; // Monitoring endpoint'leri muaf
});// Development ortamında esnek ayarlar
services.Configure<IPFilterOptions>(options =>
{
options.WhitelistedIPs = ["127.0.0.1", "::1", "192.168.1.0/24"];
options.DefaultAllow = true; // Geliştirici IP'leri için esnek
options.ExemptPaths = ["/swagger", "/health"];
});// Program.cs'de
builder.Services.AddIPFilter(options =>
{
options.StrictMode = true;
options.WhitelistedIPs = ["192.168.1.100", "10.0.0.10"];
options.ExemptPaths = ["/health", "/metrics"];
});
var app = builder.Build();
// Middleware'i ekle
app.UseIPFilter();{
"IPFilter": {
"StrictMode": true,
"WhitelistedIPs": ["10.0.1.10", "10.0.1.11"], // Sadece API Gateway IP'leri
"ExemptPaths": ["/health", "/metrics"]
}
}{
"IPFilter": {
"StrictMode": true,
"WhitelistedIPs": ["192.168.1.50", "192.168.1.51"], // Sadece admin IP'leri
"ExemptPaths": ["/api/public/*"] // Public endpoint'ler muaf
}
}{
"IPFilter": {
"StrictMode": false,
"WhitelistedIPs": ["203.0.113.0/24"], // Tenant A IP aralığı
"BlockedIPs": ["198.51.100.0/24"], // Tenant B IP aralığı
"DefaultAllow": false
}
}IP Filter Middleware, tüm güvenlik olaylarını loglar:
// Log örnekleri
_logger.LogInformation("IP adresi izin verildi: {IpAddress}", ipAddress);
_logger.LogWarning("IP adresi engellendi: {IpAddress}", ipAddress);
_logger.LogInformation("Strict Mode aktif: IP {IpAddress} sadece whitelist kontrolü yapılıyor", ipAddress);- IP Parsing: Hızlı IP adresi parsing ve validation
- CIDR Hesaplama: Optimize edilmiş subnet hesaplamaları
- Memory Efficient: Minimal memory kullanımı
- Async Processing: Non-blocking async operations
// IP erişim engellendiğinde dönen yanıt
{
"error": "Bu IP adresinden erişim engellendi",
"ipAddress": "192.168.1.100"
}- Production'da Strict Mode Kullanın: En yüksek güvenlik seviyesi için
- Monitoring Endpoint'leri Muaf Tutun:
/health,/metricsgibi - IP Aralıklarını Kullanın: Tek tek IP yerine CIDR formatında
- Regular Log Review: Güvenlik loglarını düzenli kontrol edin
- Fail-Safe Default:
DefaultAllow: falseile güvenli varsayılan - Exempt Path'leri Sınırlayın: Sadece gerekli endpoint'leri muaf tutun
// Startup.cs'de Request Pipeline konfigürasyonu
app.ConfigureRequestPipeline();
// Bu extension method, MaggsoftContext üzerinden request pipeline'ı konfigüre eder
// Özelleştirilmiş middleware'ler ve pipeline ayarları için kullanılır// HTTP Request için extension method'lar
public static class HttpRequestExtensions
{
// Request'in local olup olmadığını kontrol eder
public static bool IsLocal(this HttpRequest request)
{
// Implementation...
}
// Request'in AJAX olup olmadığını kontrol eder
public static bool IsAjaxRequest(this HttpRequest request)
{
// Implementation...
}
}// appsettings.json'da API Token ayarları:
{
"TokenOptions": {
"AccessTokenExpiration": 60,
"ApiName": "Maggsoft API",
"ApiVersion": "v1",
"ApiBaseUrl": "https://localhost:5001",
"IdentityServerBaseUrl": "https://identity.example.com",
"OidcSwaggerUIClientId": "maggsoft_api_swaggerui",
"OidcApiName": "maggsoft_api",
"AdministrationRole": "Administrator",
"RequireHttpsMetadata": true,
"CorsAllowAnyOrigin": true,
"CorsAllowOrigins": [],
"IgnoreUrls": [],
"SecurityKey": "your-secret-key-here"
}
}
// API Token Options sınıfı:
public class ApiTokenOptions
{
public string ApiName { get; set; }
public string ApiVersion { get; set; }
public string IdentityServerBaseUrl { get; set; }
public string ApiBaseUrl { get; set; }
public string OidcSwaggerUIClientId { get; set; }
public bool RequireHttpsMetadata { get; set; }
public string OidcApiName { get; set; }
public string AdministrationRole { get; set; }
public bool CorsAllowAnyOrigin { get; set; }
public string[] CorsAllowOrigins { get; set; }
public int AccessTokenExpiration { get; set; }
public string SecurityKey { get; set; }
public string[] IgnoreUrls { get; set; }
}// Excel export işlemleri için helper sınıfı
public static class ExcelOperations
{
// Generic liste'yi Excel'e export etme
public static byte[] ExportToExcel<T>(IEnumerable<T> data)
{
return ExportToExcel(data, "Sheet1");
}
// Özel sheet adı ile export
public static byte[] ExportToExcel<T>(IEnumerable<T> data, string sheetName)
{
// OpenXML kullanarak Excel dosyası oluşturma
// Implementation...
}
}
// Controller'da kullanım:
[HttpGet("export")]
public IActionResult ExportUsers()
{
var users = _userService.GetAllUsers();
var excelData = ExcelOperations.ExportToExcel(users, "Kullanıcılar");
return File(excelData, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "users.xlsx");
}// API versioning hatalarını özelleştirmek için
public class ApiVersioningErrorResponseProvider : DefaultErrorResponseProvider
{
public override IActionResult CreateResponse(ErrorResponseContext context)
{
throw new ApiVersioningException(context.Message);
}
}
// Bu provider, API versioning hatalarını standart exception formatında döner// Linux/Unix shell komutlarını çalıştırmak için
public static class ShellHelpers
{
public static string Bash(this string cmd)
{
var escapedArgs = cmd.Replace("\"", "\\\"");
if (File.Exists("/bin/bash"))
{
var process = new Process()
{
StartInfo = new ProcessStartInfo
{
FileName = "/bin/bash",
Arguments = $"-c \"{escapedArgs}\"",
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
}
};
process.Start();
var result = process.StandardOutput.ReadToEnd();
process.WaitForExit();
return result;
}
return string.Empty;
}
}
// Kullanım örneği:
var result = "ls -la".Bash();// Startup.cs'de Status Code Pages konfigürasyonu
app.UseStatusCodePages(new StatusCodePagesOptions()
{
HandleAsync = (ctx) =>
{
if (ctx.HttpContext.Response.StatusCode == 404)
{
throw new NotFoundException($"Not Found Page");
}
return Task.FromResult(0);
}
});
// Bu konfigürasyon, 404 gibi HTTP hata kodlarını yakalar ve standart exception formatında döner// Production ortamında local request'leri engelleme
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.Use(async (context, next) =>
{
if (context.Request.IsLocal())
{
// Forbidden http status code
context.Response.StatusCode = 403;
return;
}
await next.Invoke();
});
}
// Bu middleware, production ortamında local request'leri güvenlik için engeller// Startup.cs'de
services.RegisterAll<IService>();
// Service interface'i
public interface IUserService : IService
{
Task<User> GetUserAsync(int id);
Task<List<User>> GetAllUsersAsync();
Task<User> CreateUserAsync(User user);
Task<User> UpdateUserAsync(User user);
Task DeleteUserAsync(int id);
}
// Service implementasyonu
public class UserService : IUserService
{
private readonly IMssqlRepository<User> _userRepository;
private readonly ICache _cache;
private readonly IEventPublisher _eventPublisher;
public UserService(
IMssqlRepository<User> userRepository,
ICache cache,
IEventPublisher eventPublisher)
{
_userRepository = userRepository;
_cache = cache;
_eventPublisher = eventPublisher;
}
// Implementation methods...
}// Interface-based programming
public interface IUserService
{
Task<User> GetUserAsync(int id);
}
public class UserService : IUserService
{
// Implementation
}
// Service registration
services.AddScoped<IUserService, UserService>();// Custom exceptions
public class UserNotFoundException : NotFoundException
{
public UserNotFoundException(int userId)
: base($"Kullanıcı bulunamadı: {userId}")
{
}
}
// Exception handling in service
public async Task<Result<User>> GetUserAsync(int id)
{
var user = await _userRepository.FindByIdAsync(id);
if (user == null)
return Result<User>.Failure("Kullanıcı bulunamadı");
return Result<User>.Success(user);
}// FluentValidation kullanımı
public class CreateUserDtoValidator : AbstractValidator<CreateUserDto>
{
public CreateUserDtoValidator()
{
RuleFor(x => x.Name)
.NotEmpty().WithMessage("İsim boş olamaz")
.MaximumLength(100).WithMessage("İsim 100 karakterden uzun olamaz");
RuleFor(x => x.Email)
.NotEmpty().WithMessage("Email boş olamaz")
.EmailAddress().WithMessage("Geçerli bir email adresi giriniz");
}
}// Structured logging
public class UserService
{
private readonly ILogger<UserService> _logger;
public UserService(ILogger<UserService> logger)
{
_logger = logger;
}
public async Task<Result<User>> CreateUserAsync(User user)
{
_logger.LogInformation("Kullanıcı oluşturuluyor: {Email}", user.Email);
try
{
var createdUser = await _userRepository.AddAsync(user);
_logger.LogInformation("Kullanıcı başarıyla oluşturuldu: {UserId}", createdUser.Id);
return Result<User>.Success(createdUser, "Kullanıcı başarıyla oluşturuldu");
}
catch (Exception ex)
{
_logger.LogError(ex, "Kullanıcı oluşturulurken hata oluştu: {Email}", user.Email);
return Result<User>.Failure("Kullanıcı oluşturulurken hata oluştu");
}
}
}public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
// Core services
services.AddControllers();
services.AddHttpContextAccessor();
// Database configuration
services.AddMssqlConfig<AppContext>(Configuration)
.AddFluentMigratorConfig(Configuration);
// AutoMapper
services.AddAutoMapperConfig(p => p.AddProfile<AutoMapping>(), typeof(Startup));
// Event bus
services.AddSingleton<IEventPublisher, EventPublisher>();
services.RegisterEventConsumer();
// Cache
services.AddMaggsoftDistributedMemoryCache(typeof(IService));
// Repositories
services.AddScoped<IMssqlRepository<User>, Repository<User>>();
services.AddScoped<IUnitOfWork, UnitOfWork>();
// Services
services.RegisterAll<IService>();
// Infrastructure konfigürasyonu (tüm konfigürasyonları tek seferde yapar)
services.AddInfrastructure(Configuration);
// JWT Authentication
services.AddJwtAuthentication(Configuration);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI();
}
// Infrastructure konfigürasyonu (tüm middleware'leri tek seferde yapar)
app.AddInfrastructure();
// Database migration
app.AddUpMigrate();
}
}[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
[HttpGet]
public async Task<IActionResult> GetUsers()
{
var users = await _userService.GetAllUsersAsync();
return Ok(Result<List<User>>.Success(users));
}
[HttpGet("{id}")]
public async Task<IActionResult> GetUser(int id)
{
var user = await _userService.GetUserAsync(id);
if (user == null)
return NotFound(Result<User>.Failure("Kullanıcı bulunamadı"));
return Ok(Result<User>.Success(user));
}
[HttpPost]
public async Task<IActionResult> CreateUser([FromBody] CreateUserDto dto)
{
var user = new User
{
Name = dto.Name,
Email = dto.Email
};
var createdUser = await _userService.CreateUserAsync(user);
return CreatedAtAction(nameof(GetUser), new { id = createdUser.Id },
Result<User>.Success(createdUser));
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateUser(int id, [FromBody] UpdateUserDto dto)
{
var user = await _userService.GetUserAsync(id);
if (user == null)
return NotFound(Result<User>.Failure("Kullanıcı bulunamadı"));
user.Name = dto.Name;
user.Email = dto.Email;
var updatedUser = await _userService.UpdateUserAsync(user);
return Ok(Result<User>.Success(updatedUser));
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteUser(int id)
{
await _userService.DeleteUserAsync(id);
return Ok(Result.Success("Kullanıcı başarıyla silindi"));
}
}Maggsoft Framework ile modern ASP.NET Core uygulamaları geliştirin! 🚀
