Ledbim.Core 1.1.2

There is a newer version of this package available.
See the version list below for details.
dotnet add package Ledbim.Core --version 1.1.2
                    
NuGet\Install-Package Ledbim.Core -Version 1.1.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Ledbim.Core" Version="1.1.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Ledbim.Core" Version="1.1.2" />
                    
Directory.Packages.props
<PackageReference Include="Ledbim.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Ledbim.Core --version 1.1.2
                    
#r "nuget: Ledbim.Core, 1.1.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Ledbim.Core@1.1.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Ledbim.Core&version=1.1.2
                    
Install as a Cake Addin
#tool nuget:?package=Ledbim.Core&version=1.1.2
                    
Install as a Cake Tool

ProjectBase.Core — Kullanım Rehberi (ASP.NET Core 10 / Clean Architecture)

Bu doküman, ProjectBase.Core kütüphanesini hiç bilmeyen birinin kendi Api / Application / Domain / Infrastructure çözümüne güvenle entegre edebilmesi için hazırlandı.

ProjectBase.Core size şunları “tek yerden, tek standartla” sağlar:

  • Result modeli (tek tip API response)
  • BaseController (Result → IActionResult çevirimi)
  • JWT + BasicAuth (tek “smart scheme” ile)
  • OpenAPI (çoklu doküman + Scalar UI uyumlu security scheme’ler)
  • Global error handling (middleware)
  • HTTP request/response logging + correlation id (middleware)
  • MediatR pipeline behaviors (logging/validation/performance/exception)
  • EF Core için BaseContext (audit + soft delete)
  • Generic repository + pagination/filter/sort yardımcıları
  • Enum → localized message kataloğu (ILocalizedMessages + ICultureCatalog)
  • FileService (IIS FTP üzerinden dosya yükleme/silme, otomatik klasör oluşturma)

Bu repo içinde ayrıca örnek bir çözüm de var (Services/*). İsterseniz birebir aynı kurgu ile ilerleyebilirsiniz; ama ProjectBase.Core tek başına da kullanılabilir.


Yeni özellik: Localized Messages (enum → metin)

Bu repo’da “handler içinde hard-coded text yazmak” yerine, mesajları enum anahtarları üzerinden kültüre göre çözümleyen bir altyapı var:

  • ILocalizedMessages: Get<TEnum>(TEnum key, params object[] args) ile mesajı döner.
  • ICultureCatalog: Her kültür için, enum tiplerini mesaj sözlüklerine map’ler (enumType → (enumValue → text)).
  • Fallback kuralı:
    • Aktif kültürde anahtar bulunamazsa default kültüre düşer (tr-tr)
    • Orada da bulunamazsa key.ToString() döner

DI (önerilen)

Application katmanında (repo örneği: Services/ProjectBase.Application/DependencyInjection.cs) aşağıdaki kayıtlar yapılır:

  • services.AddLocalizations();
  • Her kültür için birer ICultureCatalog implementasyonu:
    • services.AddSingleton<ICultureCatalog, TrCatalog>();
    • services.AddSingleton<ICultureCatalog, EnCatalog>();

Not: AddLocalizations() içinde HttpContext’ten kültür okuyabilmek için HttpContextAccessor da register edilir.

Handler’da kullanım örneği

Repo örneği (Services/ProjectBase.Application/Handlers/Users/UserCreateCommandHandler.cs) kullanıcı zaten varsa:

return Result.Fail(ResultType.Conflict, _localizedMessages.Get(UserMessages.UserAlreadyCreated));

Katalog yapısı (örnek)

  • TrCatalog / EnCatalog: Kültür bazlı “root map”
  • CommonCatalog, UserCatalog: İlgili enum’a ait TR/EN mesaj sözlükleri

Hızlı Başlangıç (Core’u kendi projene ekle)

Ön Koşullar

  • .NET SDK: net10.0
  • ASP.NET Core 10
  • (EF kullanacaksanız) bir veritabanı sağlayıcısı (repo örneği: SQL Server)

1) Dosyaları/Projeleri çözümüne ekle

Bu repo’da ProjectBase.Core paketlerini ProjectBase.Packages üzerinden alıyor.

  • Önerilen yöntem (Project Reference):
    • Çözümünüze ProjectBase.Core ve ProjectBase.Packages projelerini ekleyin.
    • Root’taki Directory.Build.props dosyasını da çözüm köküne taşıyın/kopyalayın. (OpenAPI source generator interceptor namespace’i için)

2) Referansları ver

Bu core’u “sarmal” (chain) referans yapısıyla kullanabilirsiniz. Önerilen Clean Architecture referans zinciri:

  • Domain → Core
  • Infrastructure → Domain
  • Application → Infrastructure
  • Api → Application

Bu sayede Api projesi Core’u doğrudan referanslamadan (transitive) Core tiplerine ulaşabilir.

Örnek csproj referansları:

<ItemGroup>
  
  <ProjectReference Include="..\ProjectBase.Core\ProjectBase.Core.csproj" />
</ItemGroup>
<ItemGroup>
  
  <ProjectReference Include="..\ProjectBase.Domain\ProjectBase.Domain.csproj" />
</ItemGroup>
<ItemGroup>
  
  <ProjectReference Include="..\ProjectBase.Infrastructure\ProjectBase.Infrastructure.csproj" />
</ItemGroup>
<ItemGroup>
  
  <ProjectReference Include="..\ProjectBase.Application\ProjectBase.Application.csproj" />
</ItemGroup>

Not: Repo örneğinde API, bazı extension’ları doğrudan çağırdığı için (ProjectBase.Core.Extensions) API projesi Core’u da referanslıyor. Siz zincir yapıyı tercih ediyorsanız, API’de çağırdığınız extension’ların Application (veya API’ye en yakın) katmanda “wrapper” metotlarla dışarı açılması daha temiz olur.

3) Program.cs minimum kurulum

Aşağıdaki akış, repo’daki gerçek kurulumla aynıdır:

using ProjectBase.Core.Extensions;
using Scalar.AspNetCore;
using Serilog;

Log.Logger = new LoggerConfiguration()
    .ConfigureLogging()
    .CreateLogger();

var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog(Log.Logger);

var openApiDocuments = builder.Configuration.GetSection("OpenApi:Documents").Get<string[]>() ?? ["v1"];

builder.Services.AddControllers();
builder.Services.AddApiVersion();
builder.Services.AddJwtAuthentication(builder.Configuration);
builder.Services.AddOpenApi(builder.Configuration, openApiDocuments);

var app = builder.Build();

app.MapOpenApi("/openapi/{documentName}.json");
app.MapScalarApiReference(o => o.AddDocuments(openApiDocuments));

app.UseMiddlewares();      // HttpLogging + ExceptionHandling
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();

app.Run();

4) Application katmanı için minimum DI (önerilen)

Bu core, MediatR pipeline ve HTTP logging option’larını da desteklediği için Application tarafında tipik kurulum şöyle olur (repo’da birebir örneği: Services/ProjectBase.Application/DependencyInjection.cs):

using FluentValidation;
using MediatR;
using ProjectBase.Core.Extensions;
using ProjectBase.Core.Logging.Models;

services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(DependencyInjection).Assembly));
services.AddValidatorsFromAssembly(typeof(DependencyInjection).Assembly);
services.Configure<HttpLoggingOptions>(configuration.GetSection("LoggingOptions"));
services.AddPipelineBehaviors();

Zorunlu / Opsiyonel Konfigürasyonlar (appsettings)

JWT (Zorunlu)

AddJwtAuthentication(...) çağrısı JWT section’ını zorunlu bekler.

{
  "JWT": {
    "Audience": "YourAudience",
    "Issuer": "YourIssuer",
    "AccessTokenExpiration": 60,
    "RefreshTokenExpiration": 60,
    "AccessTokenSecurityKey": "YOUR_ACCESS_KEY_32+_CHARS",
    "RefreshTokenSecurityKey": "YOUR_REFRESH_KEY_32+_CHARS",
    "ProviderKey": "Your.Auth"
  }
}

BasicAuth (Opsiyonel)

Authorization: Basic ... geldiğinde otomatik Basic’e düşer. (Korumalı internal endpoint’ler için pratik.)

{
  "BasicAuth": {
    "User": { "Username": "admin", "Password": "secret" }
  }
}

OpenAPI Documents (Opsiyonel)

Çoklu doküman istiyorsanız:

{ "OpenApi": { "Documents": [ "v1", "v2" ] } }

HTTP Logging Options (Opsiyonel ama önerilir)

HttpLoggingMiddleware davranışını LoggingOptions ile kontrol edersiniz. Repo’da binding örneği Services/ProjectBase.Application/DependencyInjection.cs içindedir.

Örnek:

{
  "LoggingOptions": {
    "enableRequestLogging": true,
    "enableResponseLogging": true,
    "maskSensitiveData": true,
    "maxBodyLength": 65536,
    "correlationHeaderName": "X-Correlation-Id",
    "truncateRequestBody": true,
    "maxRequestBodyBytes": 65536,
    "maxResponseBodyBytes": 65536,
    "responseLogLevel": "Information",
    "errorLogLevel": "Error",
    "sensitiveFieldMatchMode": "Contains",
    "maskWith": "****",
    "sensitiveFields": [ "password", "token", "authorization" ],
    "excludePaths": [ "/openapi", "/health" ]
  }
}

“Kullanman gereken” ana metotlar ve ne işe yararlar

BaseController.CreateActionResult(...)

Dosya: ProjectBase.Core/Api/Controllers/BaseController.cs

  • Ne sağlar: Handler’dan dönen Result / Result<T>’yi HTTP response’a çevirir.
  • Nasıl: HTTP status code’u ResultType üzerinden set eder, body olarak result döner.
  • Kullanım: Controller’ı BaseController’dan türetin ve return CreateActionResult(await _mediator.Send(...)); yazın.

Result.Success(...) / Result.Fail(...)

Dosyalar: ProjectBase.Core/Results/Result.cs, ProjectBase.Core/Results/Result {T}.cs

  • Ne sağlar: Uygulama katmanında “başarılı/başarısız” standardı.
  • Kritik kural: Success(...) sadece Success/Created/NoContent gibi success tipleriyle; Fail(...) ise failure tipleriyle çağrılabilir (aksi halde exception fırlatır).

services.AddApiVersion()

Dosya: ProjectBase.Core/Extensions/ApiVersionExtension.cs

  • Ne sağlar: URL segment (api/v1/...) + query (?version=1.0) + header (X-Version) + media-type param (ver) ile versioning.
  • OpenAPI entegrasyonu: GroupNameFormat = "v1", "v2", ... gibi doküman gruplarını üretir.

services.AddJwtAuthentication(configuration)

Dosya: ProjectBase.Core/Extensions/JwtAuthenticationExtension.cs

  • Ne sağlar: Tek bir policy scheme (JWT_OR_BASIC) ile:
    • Header Basic ... ise BasicAuth
    • Değilse JWT Bearer
  • JWT üretimi: JwtTokenGenerator + IJwtTokenGenerator DI’a eklenir.
  • Standart hata body: 401/403 durumlarında Result formatında JSON döner.

services.AddOpenApi(configuration, documents)

Dosya: ProjectBase.Core/Extensions/OpenApiExtension.cs

  • Ne sağlar: Doküman bazlı OpenAPI kaydı (ör. v1, v2) ve Scalar UI için Bearer + Basic security scheme tanımı.
  • Not: Dokümana global security requirement ekler; anonymous endpoint’leriniz için action bazında [AllowAnonymous] kullanabilirsiniz.
Convention-based endpoint docs (Summary/Description otomatik doldurma)

AddOpenApi(...) içinde bir OperationTransformer vardır: Eğer bir action için operation.Summary / operation.Description değerleri explicit olarak verilmediyse, bunları isim konvansiyonu ile bir “docs” sınıfından okumayı dener.

  • Controller namespace → Docs namespace:
    • ProjectBase.Api.Controllers.v1 → ProjectBase.Api.OpenApiDocs.v1
  • Docs type candidate’ları (sırayla dener):
    • {DocsNamespace}.{ControllerName}s.{ControllerName}OpenApiDocs (önerilen, plural folder)
    • {DocsNamespace}.{ControllerName}.{ControllerName}OpenApiDocs (singular folder)
    • {DocsNamespace}.{ControllerName}OpenApiDocs (no folder)
  • Nested type: {ActionName}
  • Alanlar: public const string Summary, public const string Description

Örnek (repo içindeki gerçek dosya):

// Services/ProjectBase.Api/OpenApiDocs/v1/Users/UserOpenApiDocs.cs
namespace ProjectBase.Api.OpenApiDocs.v1.Users;

public static class UserOpenApiDocs
{
    public static class Register
    {
        public const string Summary = "Kullanıcı oluşturma işlemi";
        public const string Description = """
        JWT Bearer token gerektirir.

        - **Name** (`string`): zorunlu, en fazla 64 karakter
        - **Surname** (`string`): zorunlu, en fazla 64 karakter
        - **Mail** (`string`): zorunlu, en fazla 64 karakter, geçerli e-posta formatı
        - **Password** (`string`): zorunlu, en az 8 karakter
        """;
    }
}

Not: Bu mekanizma, action üzerinde Summary/Description zaten verilmişse override etmez; sadece boş olan alanları doldurur.

app.UseMiddlewares()

Dosya: ProjectBase.Core/Extensions/MiddlewareExtension.cs

  • Sıra:
    • HttpLoggingMiddleware: request/response body (uygunsa) loglar, correlation id üretir/taşır.
    • ExceptionHandlingMiddleware: exception’ları yakalar ve JSON Result döner.

services.AddPipelineBehaviors() (MediatR)

Dosya: ProjectBase.Core/Extensions/PipelineBehaviorExtension.cs

  • Ne sağlar: Handler’larınızda tekrar eden cross-cutting işleri otomatikleştirir:
    • LoggingBehaviour<,>
    • ValidationBehaviour<,> (FluentValidation)
    • PerformanceBehaviour<,>
    • UnhandledExceptionBehaviour<,>

new LoggerConfiguration().ConfigureLogging() (Serilog)

Dosya: ProjectBase.Core/Extensions/ConfigureLoggingExtension.cs

  • Ne sağlar: Console + Seq sink’leri ve temel filtreler.
  • Not: Seq URL’i şu an sabit: http://localhost:5341 (isterseniz extension içinde config’e bağlayarak geliştirebilirsiniz).

EF Core: Audit + Soft Delete kullanımı

BaseContext

Dosya: ProjectBase.Core/Data/Contexts/BaseContext.cs

  • Audit: Created* / Updated* alanlarını SaveChangesAsync sırasında otomatik doldurur.
  • Soft delete: Remove(...) çağrısında entity IHardDelete değilse fiziksel silmez, IsDeleted=true yapar.
  • Current user: HttpContext.User claim’lerinden UserName → ClaimTypes.Name → ClaimTypes.NameIdentifier sırasıyla okur.

BaseEntity / BaseEntity<TKey>

Dosya: ProjectBase.Core/Entities/BaseEntity.cs

  • Ne sağlar: Audit alanları + IsDeleted + (generic tipte) Id.

Repository: Core’un sunduğu yüzey (CRUD + paging)

IRepository<T>

Dosya: ProjectBase.Core/Repositories/EfCore/IRepository.cs

  • Add: AddAsync, AddRangeAsync
  • Update: UpdateAsync, UpdateRangeAsync, UpdateAsync(predicate, setPropertyCalls) (bulk)
  • Delete: DeleteAsync(entity), DeleteAsync(predicate), DeleteRangeAsync
  • Get: GetAsync, GetAllAsync, GetAllPagedAsync, GetCountAsync

Repository<T>

Dosya: ProjectBase.Core/Repositories/EfCore/Repository {T}.cs

  • Ne sağlar: EF Core DbSet<T> üzerinden generic implementasyon.
  • Okuma: AsNoTracking() kullanır.
  • Paging: CountAsync + Skip/Take.

Bulk Update (UpdateAsync predicate + setPropertyCalls)

UpdateAsync(entity) ve UpdateRangeAsync(entities) change tracker üzerinden çalışır; SaveChangesAsync sırasında audit alanları (UpdatedDate, UpdatedBy) otomatik doldurulur. Bulk update senaryosunda ise EF Core ExecuteUpdateAsync kullanılır; bu metot change tracker’ı atladığı için audit alanları normal akışta güncellenmez.

Core’daki UpdateAsync(Expression<Func<T, bool>> predicate, Action<UpdateSettersBuilder<T>> setPropertyCalls) overload’u bu durumu çözer:

  • Ne yapar: ExecuteUpdateAsync ile predicate’e uyan tüm satırları tek sorguda günceller.
  • Audit: UpdatedDate ve UpdatedBy otomatik eklenir (BaseContext.GetCurrentUser() ile; SaveChangesAsync ile aynı mantık).
  • Dönüş: Result<int> — güncellenen satır sayısı.

Kullanım örneği:

// Tek property güncelleme
var result = await _repository.UpdateAsync(
    x => x.CategoryId == categoryId,
    s => s.SetProperty(e => e.IsProcessed, true));

// Birden fazla property
var result = await _repository.UpdateAsync(
    x => x.Status == "Pending",
    s =>
    {
        s.SetProperty(e => e.Status, "Active");
        s.SetProperty(e => e.ProcessedAt, DateTime.Now);
    });

if (result.IsSuccess)
    var updatedCount = result.Data; // Güncellenen satır sayısı

Not: UpdateSettersBuilder<T> EF Core 10 API’sine aittir. UpdatedDate ve UpdatedBy her çağrıda otomatik set edilir; kullanıcının setPropertyCalls içinde bu alanları vermesi gerekmez.


Dapper: Handler içinde hızlı SQL (opsiyonel)

Bu repo’da Dapper entegrasyonu, “EF repository desenini bozmadan” handler içinde gerektiğinde ham SQL çalıştırabilmeniz için tasarlandı.

IDapperExecutor

Dosya: ProjectBase.Core/Repositories/Dapper/IDapperExecutor.cs

  • Ne sağlar: Handler’a inject edip QueryAsync<T> / QuerySingleOrDefaultAsync<T> / ExecuteAsync ile Dapper sorgusu çalıştırmanızı sağlar.

IDbConnectionProvider + EfCoreDbConnectionProvider<TContext>

Dosyalar:

  • ProjectBase.Core/Repositories/Dapper/IDbConnectionProvider.cs

  • ProjectBase.Core/Repositories/Dapper/EfCoreDbConnectionProvider.cs

  • Ne sağlar: Dapper’ın kullanacağı DbConnection ve (varsa) DbTransaction bilgisini verir.

  • Kritik özellik: EF Core ile BeginTransactionAsync() açıldıysa, Dapper da aynı connection/transaction üzerinde çalışır. (Tek Commit/Rollback ile yönetim.)

DI kaydı

Dosya: ProjectBase.Core/Repositories/DependencyInjection.cs

Repo örneğinde, Infrastructure katmanında DbContext kurulumundan sonra şöyle bağlanır:

services.AddRepositories<ApplicationContext>(); // Dapper: IDbConnectionProvider + IDapperExecutor

Not: AddRepositories<TContext> generic olduğu için kendi context’inizi verirsiniz (ör. MyAppContext).

Handler’da kullanım örneği (transaction ile)

Transaction gerekiyorsa standardınız IUnitOfWork olduğu için, sadece Dapper çalıştıracak olsanız bile transaction’ı UoW ile açıp yönetebilirsiniz:

await uow.BeginTransactionAsync();
try
{
    var r = await dapper.ExecuteAsync("UPDATE Users SET Name=@Name WHERE Id=@Id", new { Id = userId, Name = "X" }, cancellationToken: ct);
    if (!r.IsSuccess) { await uow.RollbackAsync(); return Result.Fail(ResultType.InternalServerError, "Dapper failed"); }

    await uow.CommitAsync();
    return Result.Success(ResultType.Success, "OK");
}
catch
{
    await uow.RollbackAsync();
    return Result.Fail(ResultType.InternalServerError, "Transaction failed");
}

Not: Transaction açmazsanız Dapper komutları transaction’sız çalışır (SQL Server’da statement bazında atomik; ama “birden fazla statement tek commit/rollback” olmaz).


MongoDB: NoSQL altyapısı (ortak kullanım)

Ledbim.Core, MongoDB kullanımı için hazır altyapı sağlar. EF Core repository desenine benzer şekilde IMongoRepository<T> ile çalışır.

MongoBaseEntity / MongoBaseEntityWithObjectId / MongoBaseEntity<TKey>

Dosya: Ledbim.Core/Entities/Mongo/MongoBaseEntity.cs - Audit alanları ve soft delete içerir.

IMongoRepository<T>

Dosya: Ledbim.Core/Repositories/Mongo/IMongoRepository.cs - AddAsync, UpdateAsync, DeleteAsync, GetAsync, GetAllPagedAsync vb.

DI kaydı

appsettings.json: "MongoDb": { "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "LedbimDb" }

Program.cs: builder.Services.AddMongoDb(builder.Configuration); builder.Services.AddMongoRepository<MyDocument>();


HTTP: Dış servislere ortak client (Result<T> dönen)

Handler içinde her seferinde HttpClient inject edip serialize / deserialize / error-handling yazmak yerine, Core’da hazır bir wrapper var:

  • IHttpResultClient (Dosya: ProjectBase.Core/Http/IHttpResultClient.cs)
  • HttpResultClient (partial sınıf):
    • ProjectBase.Core/Http/HttpResultClient.cs (ctor + kısa public API)
    • ProjectBase.Core/Http/HttpResultClient.Send.cs (çekirdek send/response akışı)
    • ProjectBase.Core/Http/HttpResultClient.FormData.cs (multipart/form-data upload)
    • ProjectBase.Core/Http/HttpResultClient.Helpers.cs (helper’lar + private tipler)

DI

Infrastructure içinde otomatik eklenir:

services.AddHttpResultClient();

Not: Dış servis için named client tanımlamanız önerilir.

Named HttpClient örneği

API projesinde (örn. Services/ProjectBase.Api/Program.cs) config’ten base address verip named client ekleyebilirsiniz:

builder.Services.AddHttpClient("UserService", c =>
{
    c.BaseAddress = new Uri(builder.Configuration["Integrations:UserService:BaseUrl"]!);
});

Handler’da kullanım örneği

public sealed class UsersQueryHandler(IHttpResultClient http) : IRequestHandler<UsersQuery, Result<List<UserDto>>>
{
    public async Task<Result<List<UserDto>>> Handle(UsersQuery request, CancellationToken ct)
    {
        return await http.GetAsync<List<UserDto>>(
            clientName: "UserService",
            // NOTE: Leading '/' resets BaseAddress path. Prefer relative paths (no leading slash).
            url: "api/users",
            cancellationToken: ct);
    }
}

POST multipart/form-data (Form + File upload)

Dosya upload gibi senaryolar için:

  • Metot: PostFormDataAsync<TResponse>(...)
  • Dosya parçası modeli: FormFilePart (Dosya: ProjectBase.Core/Http/FormFilePart.cs)

Örnek kullanım:

var fields = new Dictionary<string, string?>
{
    ["name"] = "Altin",
    ["age"] = "30"
};

await using var fs = File.OpenRead("c:\\temp\\photo.jpg");

var files = new[]
{
    new FormFilePart(
        Name: "file",              // server tarafında beklenen field adı
        Content: fs,               // stream (file/network/memory)
        FileName: "photo.jpg",     // request'teki filename
        ContentType: "image/jpeg", // opsiyonel
        LeaveOpen: true)           // true: stream kapatma sorumluluğu sende
};

var result = await http.PostFormDataAsync<MyResponse>(
    clientName: "UserService",
    url: "api/users/upload",
    fields: fields,
    files: files,
    cancellationToken: ct);

Not: LeaveOpen=false (default) ise istek tamamlanınca stream dispose edilir (en güvenli varsayılan). LeaveOpen=true ise stream açık kalır; işin bitince sen dispose etmelisin.


FileService: IIS FTP üzerinden dosya yükleme / silme

IIS FTP sunucusuna dosya yüklemek ve silmek için IFileService kullanılır. FluentFTP kütüphanesi ile FTP protokolü üzerinden çalışır (obsolete FtpWebRequest yerine).

IFileService

Dosya: ProjectBase.Core/FileService/Interfaces/IFileService.cs

  • UploadAsync(FileUploadRequest, CancellationToken): IFormFile ile dosya yükler. Klasör yolu yoksa otomatik oluşturur.
  • UploadBase64Async(Base64UploadRequest, CancellationToken): Base64 içerikten dosya yükler.
  • RemoveAsync(string pathOrUrl, CancellationToken): Verilen path/URL’deki dosyayı siler.

Modeller

  • FileUploadRequest: File (IFormFile), Folder (örn. "Fairs/Test1/Test2/Test3")
  • Base64UploadRequest: Base64Content, Folder, Extension (opsiyonel)
  • FileUploadResult: Path (public CDN URL), Extension, SizeBytes

Konfigürasyon (appsettings.json)

{
  "FtpSettings": {
    "FtpAddress": "cdn.example.com",
    "Username": "ftp_user",
    "Password": "ftp_password"
  }
}
  • FtpAddress: IIS FTP host (örn. cdn.example.com veya ftp://cdn.example.com). Dönen Path için https://{host}/... kullanılır.

DI

Application katmanında (DependencyInjection.cs):

services.AddFileService(configuration);

Kullanım örneği

// IFormFile ile yükleme
var request = new FileUploadRequest 
{ 
    File = formFile, 
    Folder = "Fairs/Test1/Test2/Test3" 
};
var result = await _fileService.UploadAsync(request, cancellationToken);
// result.Path = "https://cdn.example.com/Fairs/Test1/Test2/Test3/{guid}.ext"

// Silme
await _fileService.RemoveAsync(result.Path, cancellationToken);

Not: Folder içindeki klasör yapısı (örn. Fairs/Test1/Test2/Test3) yoksa, yüklemeden önce otomatik oluşturulur.


Pagination / Filter / Sort (liste ekranları için)

Core içinde liste ekranlarını standartlaştırmak için hazır modeller ve yardımcılar var:

  • İstek modelleri: ProjectBase.Core/Pagination/*
    • PaginationFilterQuery (page/filter/sort DTO)
    • PagedFilterRequest<T> (repository’ye giden hazır istek)
  • Sonuç modelleri:
    • PagedModel<T> (repository’nin döndürdüğü ham veri + total)
    • PagedResponse<T> ve PagedHelper (API response formatına çevirme)
  • Helper’lar: ProjectBase.Core/Helpers/*
    • FilterQueryHelper (filter’ı Expression<Func<T,bool>> predicate’e çevirme)
    • SortQueryHelper (sort listesini OrderBy/ThenBy zincirine çevirme)

Pratik kullanım kuralı:

  • Client’tan gelen alan isimlerini doğrudan entity alanlarına bağlamayın. Handler içinde bir allow-list / fieldMap oluşturup sadece izinli alanları filtre/sort’a açın.

Helpers: EnumHelper (Display/Parse/Convert)

Core içinde ProjectBase.Core/Helpers/EnumHelper.cs altında, enum’larla çalışmayı kolaylaştıran genel metotlar var:

  • DisplayAttribute okuma:
    • GetDisplayName(...)
    • GetDisplayShortName(...)
    • GetDisplayDescription(...)
  • Genel attribute okuma: GetAttribute<TEnum, TAttribute>(...)
  • Liste üretme (UI/dropdown):
    • GetValues<TEnum>(), GetNames<TEnum>()
    • GetDisplayItems<TEnum>() → (Value, DisplayName) listesi
  • Parse/validate:
    • TryParse<TEnum>(...)
    • TryParseDefined<TEnum>(...)
    • IsDefined(...)
  • Sayısal dönüşüm:
    • ToInt32(...), ToInt64(...)

Not: EnumHelper, DisplayAttribute gibi reflection tabanlı okumalarda tekrar maliyetini azaltmak için küçük bir cache kullanır.


Migrations (örnek akış)

Bu repo’da Infrastructure altında hazır komut dosyaları var:

  • Services/ProjectBase.Infrastructure/_01-migrations.cmd: migration ekler (startup project: API)
  • Services/ProjectBase.Infrastructure/_02-update-database.cmd: database update
  • Services/ProjectBase.Infrastructure/_03-migrations-remove.cmd: son migration’ı siler

Kendi projenizde aynı yaklaşımı kullanacaksanız, startup project ve context adını kendi isimlerinize göre güncelleyin.


Sık Sorulan Sorular / Sorun Giderme

401 dönüyor ama neden?

  • JWT section yok/eksik olabilir (AddJwtAuthentication bunu zorunlu bekler).
  • Token Issuer/Audience/Key uyumsuz olabilir.
  • [Authorize] endpoint’ine token’sız istek atılıyor olabilir.

Soft delete istemiyorum, fiziksel silsin

  • Entity’nize IHardDelete marker interface’ini ekleyin. (Dosya: ProjectBase.Core/Entities/EntityInterfaces.cs)

OpenAPI dokümanımda Bearer/Basic çıkmıyor

  • services.AddOpenApi(..., documents) çağrısını yaptığınızdan emin olun.
  • MapOpenApi("/openapi/{documentName}.json") route’unu map’leyin.
  • Scalar UI için MapScalarApiReference(...) ile dokümanları ekleyin.
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (7)

Showing the top 5 NuGet packages that depend on Ledbim.Core:

Package Downloads
Ledbim.Messaging

MassTransit/RabbitMQ entegrasyonu. IIntegrationEventBus arayüzünün transport-agnostic implementasyonu, consumer logging filtresi ve correlation ID altyapısı içerir. Ledbim.Core üzerine inşa edilmiştir.

Ledbim.Security

JWT ve BasicAuth hybrid kimlik doğrulama, refresh token rotation ve hırsızlık tespiti, AES-256-GCM şifreleme ve PBKDF2-SHA512 parola hashing altyapısı. Ledbim.Core üzerine inşa edilmiştir.

Ledbim.EntityFramework

Entity Framework Core ve Dapper tabanlı veri erişim altyapısı. BaseContext (audit, soft delete, domain event toplama), generic Repository, ITransactionManager, Dapper executor ve dinamik LINQ sorgu desteği içerir. Ledbim.Core üzerine inşa edilmiştir.

Ledbim.AspNetCore

ASP.NET Core entegrasyonu: middleware, Serilog yapılandırması, API versioning, OpenAPI/Scalar, localization ve MediatR pipeline behavior kayıtları içerir. Ledbim.Core üzerine inşa edilmiştir.

Ledbim.Http

Typed HTTP client wrapper. IHttpClientFactory tabanlı, Result pattern dönen IHttpResultClient implementasyonu içerir. GET, POST JSON, POST multipart form data ve generic send desteği sunar. Ledbim.Core üzerine inşa edilmiştir.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.0 1,325 3/28/2026
1.1.3 122 3/26/2026
1.1.2 145 3/2/2026
1.1.1 141 2/23/2026