مرور سریع ASP.NET Core و Web API
جمعبندی نکات کلیدی ASP.NET Core برای مرور شب قبل مصاحبه — از Controller و Middleware تا Authentication/Authorization، CORS و SignalR.
این جزوه مهمترین نکات ASP.NET Core و Web API را که در مصاحبههای برنامهنویسی پرتکرارند، در یک صفحه جمع کرده تا در کمترین زمان مرور کنید. نکات ⭐ (طلایی) پرتکرارترین سؤالات مصاحبه هستند — اگر وقت کم دارید، فقط همانها را بخوانید.
فهرست بخشها
- انواع API (Api Types)0/5
- Authentication در برابر Authorization0/5
- Background Service0/5
- CORS (Cross-Origin Resource Sharing)0/6
- Controller در ASP.NET Core0/5
- JWT Authentication0/4
- Log Level0/3
- Logging Provider0/4
- SignalR0/5
- Middleware در ASP.NET Core - مفاهیم پایه0/4
- Middleware در ASP.NET Core - دستهبندی کاربردی0/4
- روابط بین Modelها در EF Core (Relations)0/5
- Model در ASP.NET Core0/5
- OAuth2 و OpenID Connect0/5
- API Versioning در ASP.NET Core0/5
انواع API (Api Types)0/5
مدلهای مختلف طراحی و ارتباط بین سیستمها که هر کدام برای سناریوی خاصی مناسباند.
REST → ساده و رایج، GraphQL → منعطف، gRPC → سریع بین سرویسها، WebSocket → ارتباط لحظهای، SOAP → قدیمی و سازمانی.
Authentication در برابر Authorization0/5
Authentication یعنی اثبات هویت کاربر (تو کی هستی؟) و Authorization یعنی تعیین سطح دسترسی او (چه کاری مجازی؟)؛ اولی همیشه باید قبل از دومی انجام شود.
[Authorize]
public IActionResult Profile()
{
return View();
}
[Authorize(Roles = "Admin")]
public IActionResult Dashboard()
{
return View();
}
فرض کردن اینکه [Authorize] بهتنهایی سطح دسترسی (نقش) را هم چک میکند؛ بدون Roles یا Policy فقط لاگین بودن بررسی میشود.
new Claim(ClaimTypes.Name, "Ali");
new Claim(ClaimTypes.Email, "ali@gmail.com");
new Claim(ClaimTypes.Role, "Admin");
این دقیقاً همان چیزی است که در ۹۰٪ پروژههای ASP.NET Core با JWT و Identity استفاده میشود.
Background Service0/5
سرویسی که همزمان با اجرای برنامه در پسزمینه اجرا میشود و وابسته به درخواستهای HTTP نیست؛ برای کارهای مداوم یا زمانبندیشده مثل پردازش صف یا ارسال ایمیل دورهای.
public class MyBackgroundService : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
Console.WriteLine("Running background task...");
await Task.Delay(5000, stoppingToken); // هر ۵ ثانیه
}
}
}
builder.Services.AddHostedService<MyBackgroundService>();
نادیده گرفتن stoppingToken در Task.Delay یا در حلقه، که باعث میشود سرویس هنگام Shutdown برنامه بهدرستی متوقف نشود.
CORS (Cross-Origin Resource Sharing)0/6
مکانیزم امنیتی مرورگر که تعیین میکند یک سایت اجازه دارد یا ندارد به سایت دیگری (Origin متفاوت) درخواست بزند.
// هدر پاسخ سرور:
// Access-Control-Allow-Origin: https://siteA.com
// یا
// Access-Control-Allow-Origin: *
builder.Services.AddCors(options =>
{
options.AddPolicy("MyPolicy", policy =>
{
policy.WithOrigins("https://siteA.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
// ...
app.UseCors("MyPolicy");
policy.WithOrigins("https://siteA.com")
.AllowCredentials();
استفاده همزمان از AllowAnyOrigin() و AllowCredentials() که در ASP.NET Core مجاز نیست و خطا میدهد.
سوال رایج مصاحبه: چرا Postman با CORS Error مواجه نمیشود؟ چون CORS فقط در مرورگر چک میشود.
Controller در ASP.NET Core0/5
کلاس اصلی برای مدیریت درخواستهای HTTP (GET, POST, PUT, DELETE) که معمولاً داخل پوشه Controllers قرار میگیرد.
public class HomeController : Controller
{
}
// یا در API:
public class HomeController : ControllerBase
{
}
ارثبری از Controller در پروژههای خالص Web API که باعث اضافه شدن امکانات غیرضروری View میشود؛ باید از ControllerBase استفاده شود.
public IActionResult Index()
{
return View();
}
[Route("api/users")]
public class UserController : ControllerBase
{
[HttpGet]
public IActionResult GetAll() { }
}
public IActionResult Get(int id) { ... }
[HttpPost]
public IActionResult Create([FromBody] User user) { ... }
public IActionResult Search([FromQuery] string name) { ... }
private readonly IUserService _service;
public UserController(IUserService service)
{
_service = service;
}
if (!ModelState.IsValid)
return BadRequest(ModelState);
نوشتن منطق کسبوکار (business logic) مستقیم داخل Controller بهجای انتقال آن به Service layer.
JWT Authentication0/4
روش احراز هویت بدون Session سمت سرور؛ بهجای نشست، یک توکن رمزنگاریشده (JWT) در هر درخواست همراه کاربر ارسال میشود.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "MyApp",
ValidAudience = "MyApp",
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes("THIS_IS_MY_SECRET_KEY_123"))
};
});
builder.Services.AddAuthorization();
app.UseAuthentication();
app.UseAuthorization();
var claims = new[]
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.Role, "Admin")
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("THIS_IS_MY_SECRET_KEY_123"));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "MyApp",
audience: "MyApp",
claims: claims,
expires: DateTime.Now.AddHours(1),
signingCredentials: creds);
return new JwtSecurityTokenHandler().WriteToken(token);
فراموش کردن ترتیب UseAuthentication قبل از UseAuthorization؛ اگر جابهجا شوند Authorization درست کار نمیکند.
// در درخواستهای بعدی:
// Authorization: Bearer YOUR_TOKEN
[Authorize]
[HttpGet]
public IActionResult GetData()
{
return Ok("Protected Data");
}
[Authorize(Roles = "Admin")]
Log Level0/3
درجه اهمیت پیامهایی که در برنامه لاگ گرفته میشود؛ در .NET با Microsoft.Extensions.Logging مدیریت میشود.
// appsettings.json
// "LogLevel": { "Default": "Information" }
// یعنی: Information, Warning, Error, Critical ثبت میشوند؛ Debug و Trace حذف میشوند.
تصور اینکه تنظیم LogLevel روی Information فقط همان یک سطح را نشان میدهد، در حالی که سطوح شدیدتر (Warning به بالا) هم شامل میشوند.
Logging Provider0/4
سرویس/جایی که لاگها را دریافت میکند و ذخیره یا نمایش میدهد؛ مثل Console، File، Debug Window، Application Insights یا Seq.
using Microsoft.Extensions.Logging;
var factory = LoggerFactory.Create(builder =>
{
builder.AddConsole(); // این هم یک Logging Provider است
});
var logger = factory.CreateLogger("MyApp");
logger.LogInformation("Hello World");
var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders(); // حذف پیشفرضها
builder.Logging.AddConsole(); // اضافه کردن Provider
builder.Logging.AddDebug(); // میتوان چند Provider داشت
var app = builder.Build();
app.MapGet("/", (ILogger<Program> logger) =>
{
logger.LogInformation("Request received");
return "Hello";
});
app.Run();
SignalR0/5
ابزار ارتباط بلادرنگ (Real-time) در ASP.NET Core بین سرور و کلاینت که بدون نیاز به Polling یا Ajax تکراری، دادهها را آپدیت میکند.
using Microsoft.AspNetCore.SignalR;
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
builder.Services.AddSignalR();
var app = builder.Build();
app.MapHub<ChatHub>("/chatHub");
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chatHub")
.build();
connection.on("ReceiveMessage", (user, message) => {
console.log(user + ": " + message);
});
connection.start();
connection.invoke("SendMessage", "Ali", "Salam!");
await Groups.AddToGroupAsync(Context.ConnectionId, "Admins");
await Clients.Group("Admins").SendAsync("ReceiveMessage", "system", "hello");
Middleware در ASP.NET Core - مفاهیم پایه0/4
مراحل زنجیرهای پردازش درخواستها قبل از رسیدن به Controller و بعد از آن؛ هر Middleware یک قطعه کد است که هر درخواست HTTP از چند تای آنها عبور میکند.
app.Use(async (context, next) =>
{
// قبل از رفتن به مرحله بعد
await next();
// بعد از برگشت پاسخ
});
// مثال ساده:
app.Use(async (context, next) =>
{
Console.WriteLine("Request incoming");
await next();
Console.WriteLine("Response outgoing");
});
قرار دادن UseAuthorization قبل از UseAuthentication یا UseRouting بعد از تعریف Endpointها که باعث رفتار نادرست pipeline میشود.
Middleware در ASP.NET Core - دستهبندی کاربردی0/4
چون ASP.NET Core دستهبندی رسمی برای انواع Middleware ندارد، میتوان آنها را بر اساس کاربرد به چند گروه ساده تقسیم کرد.
روابط بین Modelها در EF Core (Relations)0/5
Entity Framework Core (EF Core) با استفاده از Navigation Property بین کلاسهای Model ارتباط برقرار میکند و آن را در دیتابیس به ارتباط بین جدولها تبدیل میکند.
public class User
{
public int Id { get; set; }
public Passport Passport { get; set; }
}
public class Passport
{
public int Id { get; set; }
public int UserId { get; set; }
public User User { get; set; }
}
public class Category
{
public int Id { get; set; }
public List<Product> Products { get; set; }
}
public class Product
{
public int Id { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
public class Student
{
public int Id { get; set; }
public List<Course> Courses { get; set; }
}
public class Course
{
public int Id { get; set; }
public List<Student> Students { get; set; }
}
public class StudentCourse
{
public int StudentId { get; set; }
public Student Student { get; set; }
public int CourseId { get; set; }
public Course Course { get; set; }
public int Score { get; set; }
}
public class Product
{
public int CategoryId { get; set; } // Foreign Key
public Category Category { get; set; } // Navigation Property
}
Model در ASP.NET Core0/5
کلاسهایی که معمولاً دادهها را نمایش میدهند (مثل DTO یا Entity) و پایه ارتباط با دیتابیس یا انتقال داده در برنامه هستند.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Product
{
public int Id { get; set; }
[Required]
[StringLength(100)]
public string Name { get; set; }
}
[Key]
public int ProductId { get; set; }
public class Category
{
public int Id { get; set; }
public List<Product> Products { get; set; }
}
public class Product
{
public Category Category { get; set; } // Navigation Property
}
استفاده مستقیم از Entity دیتابیس بهعنوان خروجی API بدون DTO، که میتواند فیلدهای حساس یا داخلی را افشا کند (Over-posting/Under-posting).
public string? Description { get; set; }
OAuth2 و OpenID Connect0/5
OAuth2 پروتکل Authorization برای دادن دسترسی محدود به منابع محافظتشده است؛ OpenID Connect لایهای روی OAuth2 برای Authentication و شناسایی کاربر.
خلاصه یکخطی: OAuth2 = «این برنامه چه کاری اجازه دارد انجام دهد؟»، OpenID Connect = «این کاربر دقیقاً چه کسی است؟»
builder.Services
.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "https://your-identity-server";
options.ClientId = "web-client";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.SaveTokens = true;
});
API Versioning در ASP.NET Core0/5
مکانیزمی برای مدیریت تغییرات در API تا بتوان نسخههای جدید را منتشر کرد بدون اینکه کاربران نسخههای قبلی دچار مشکل شوند.
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/products")]
public class ProductsController : ControllerBase
{
}
// Query String:
// GET /api/products?version=1
// Header:
// GET /api/products
// api-version: 2
<Version>1.0.0</Version>
این تعریف برای اکثر مصاحبههای .NET کاملاً کافی است.
