TGViewer
C# Geeks (.NET) C# Geeks (.NET) @csharpgeeks · 549 subscribers
Post #304 126
کد را به من نشان بده 👨‍💻

من ابتدا بر اساس دامنه (Users) و سپس بر اساس ویژگی (ExportData) سازماندهی می‌کنم. 📂 برخی تیم‌ها مستقیماً Features/ExportUserData را ترجیح می‌دهند، اما من متوجه شده‌ام که گروه‌بندی دامنه زمانی که ویژگی‌های زیادی دارید، کمک می‌کند. ویژگی‌های مرتبط به صورت بصری گروه‌بندی شده باقی می‌مانند.

در اینجا ظاهر برش ویژگی (feature slice) خروجی داده ما با استفاده از یک request، handler و minimal APIها آمده است: 👇

Features/Users/ExportData/ExportUserData.cs

public static class ExportUserData
{
public record Request(Guid UserId) : IRequest<Response>;

public record Response(string DownloadUrl, DateTime ExpiresAt);

public class Handler(
AppDbContext dbContext,
ICloudStorageClient storageClient,
IEmailSender emailSender)
: IRequestHandler<Request, Response>
{
public async Task<Response> Handle(Request request, CancellationToken ct = default)
{
// Get user data
var user = await dbContext.Users
.Include(u => u.Orders)
.Include(u => u.Preferences)
.FirstOrDefaultAsync(u => u.Id == request.UserId, ct);

if (user == null)
{
throw new NotFoundException($"User {request.UserId} not found");
}

// Generate export data
var exportData = new
{
user.Email,
user.Name,
user.CreatedAt,
Orders = user.Orders.Select(o => new { o.Id, o.Total, o.Date }),
Preferences = user.Preferences
};

// Upload to cloud storage
var fileName = $"user-data-{user.Id}-{DateTime.UtcNow:yyyyMMdd}.json";
var expiresAtUtc = DateTime.UtcNow.AddDays(7);

var downloadUrl = await storageClient.UploadAsJsonAsync(
fileName,
exportData,
expiresAtUtc,
ct);

// Send email notification
await emailSender.SendDataExportEmailAsync(user.Email, downloadUrl, ct);

return new Response(downloadUrl, expiresAtUtc);
}
}

// Simple validation using FluentValidation
public sealed class Validator : AbstractValidator<Request>
{
public Validator()
{
RuleFor(r => r.UserId).NotEmpty();
}
}
}

همه چیز مربوط به خروجی گرفتن از داده‌های کاربر در یک مکان قرار دارد: کوئری دیتابیس، اعتبارسنجی، منطق بیزینس، یکپارچه‌سازی با فضای ذخیره‌سازی ابری، و نوتیفیکیشن ایمیل.

endpoint Minimal API سرراست است: 👇
public static class ExportUserDataEndpoint
{
public static void Map(IEndpointRouteBuilder app)
{
app.MapPost("/users/{userId}/export", async (
Guid userId,
IRequestHandler<ExportUserData.Request, ExportUserData.Response> handler) =>
{
var response = await handler.Handle(new ExportUserData.Request(userId));
return Results.Ok(response);
});
}
}

ما حتی می‌توانستیم endpoint را داخل فایل ExportUserData.cs تعریف کنیم اگر می‌خواستیم همه چیز را کنار هم نگه داریم. این بیشتر یک موضوع ترجیح و قراردادهای تیمی است. هر دو رویکرد به خوبی کار می‌کنند. 👍
More from @csharpgeeks
  1. Sep 22, 2026یه مدتی قراره از دنیای NET. فاصله بگیرم، چون وقتشه برم سربازی. راستش نمیدونم این مدت رو چج…
  2. Sep 20, 2026🔥 حالا مشکل اصلی: Alert Storm فرض کن Database از دسترس خارج شده. ۱۰۰ Pod داری. هر Pod می‌…
  3. Sep 20, 2026🚨 طراحی سیستم Monitoring و Alerting در یک سیستم بزرگ فرض کن ساعت ۳ صبح است. سیستم شما با…
  4. Sep 19, 2026#Engineering_Leadership تصمیم نگرفتن هم یک تصمیم است یه چیز عجیب توی تیم‌های مهندسی: گاهی…
  5. Sep 19, 2026☑ چک‌لیست آماده‌سازی تیم، فرایندها و زیرساخت برای توسعه با AI توجه: هیچ چک‌لیستی جهان‌شمول…
  6. Sep 19, 2026📌پایان یک انتظار طولانی: اعتبارسنجی ناهمگام (Async Validation) در NET 11.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →