آموزش جامع ASP.NET Core - صفر تا صد

این آموزش شما را از مفاهیم پایه تا پیشرفته ASP.NET Core با مثال‌های عملی و پروژه فروشگاه آنلاین هدایت می‌کند. مناسب برای مبتدیان و حرفه‌ای‌ها.

فصل اول: مقدمه و مفاهیم پایه

ASP.NET Core چیست؟

ASP.NET Core فریم‌ورک متن‌باز و کراس‌پلتفرم مایکروسافت است که برای ساخت برنامه‌های وب مدرن، APIها، و برنامه‌های بلادرنگ استفاده می‌شود. این فریم‌ورک بر پایه .NET ساخته شده و از زبان C# پشتیبانی می‌کند.

نکته: ASP.NET Core جایگزین ASP.NET Framework شده و روی ویندوز، لینوکس، و مک اجرا می‌شود.

تفاوت با ASP.NET Web Forms

Web Forms مدل قدیمی مبتنی بر رویداد بود که پیچیدگی‌هایی در توسعه و نگهداری داشت. ASP.NET Core MVC از معماری مدرن با جداسازی لایه‌ها (Model، View، Controller) استفاده می‌کند که توسعه را ساده‌تر و تست‌پذیر می‌کند.

چرا ASP.NET Core؟

پیش‌نیازها

دانش پایه C#، HTML، CSS، JavaScript، و آشنایی با SQL Server برای کار با پایگاه داده.

فصل دوم: راه‌اندازی محیط توسعه

ابزارهای مورد نیاز

برای شروع توسعه، ابزارهای زیر ضروری هستند:

  1. Visual Studio 2022 Community: محیط توسعه یکپارچه رایگان.
  2. .NET 8 SDK: شامل Runtime و CLI برای توسعه.
  3. SQL Server: برای مدیریت پایگاه داده (اختیاری).
  4. مرورگر: کروم یا فایرفاکس برای تست.

نصب ابزارها

1. دانلود Visual Studio از visualstudio.microsoft.com و انتخاب workloadهای "ASP.NET and web development" و ".NET desktop development".

2. نصب .NET 8 SDK از dotnet.microsoft.com.

بررسی نصب

برای اطمینان از نصب صحیح، در ترمینال اجرا کنید:

dotnet --version

این دستور نسخه نصب‌شده .NET را نمایش می‌دهد (مثلاً 8.0.x).

فصل سوم: اولین پروژه ASP.NET Core

ایجاد پروژه

برای ساخت پروژه:

  1. Visual Studio را باز کنید و "Create a new project" را انتخاب کنید.
  2. قالب "ASP.NET Core Web App (Model-View-Controller)" را انتخاب کنید.
  3. نام پروژه (مثلاً MyWebApp) و نسخه .NET 8 را مشخص کنید.

یا از CLI:

dotnet new webapp -n MyWebApp
cd MyWebApp

ساختار پروژه

پروژه شامل پوشه‌ها و فایل‌های زیر است:

اجرای پروژه

با دکمه F5 در Visual Studio یا دستور زیر:

dotnet run

مرورگر باز شده و آدرس https://localhost:5001 را نمایش می‌دهد.

فصل چهارم: معماری MVC

اجزای MVC

MVC شامل سه بخش است:

مثال عملی

مدل

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

این کلاس یک محصول با شناسه، نام، و قیمت را تعریف می‌کند.

کنترلر

using Microsoft.AspNetCore.Mvc;
public class HomeController : Controller
{
    public IActionResult Index()
    {
        ViewData["Message"] = "خوش آمدید به ASP.NET Core!";
        return View();
    }
}

این کنترلر داده‌ای را به View ارسال می‌کند.

View (Views/Home/Index.cshtml)

@{
    ViewData["Title"] = "صفحه اصلی";
}
<h1>@ViewData["Message"]</h1>

این View پیام خوش‌آمدگویی را نمایش می‌دهد.

فصل پنجم: Razor Syntax

کاربرد

Razor امکان ترکیب کد C# با HTML را فراهم می‌کند. از @ برای درج کد استفاده می‌شود.

مثال

@{
    var message = "سلام ASP.NET Core";
    var now = DateTime.Now;
}
<h2>@message - @now.ToString("yyyy-MM-dd")</h2>

این کد یک پیام و تاریخ جاری را نمایش می‌دهد.

فصل ششم: Entity Framework Core

معرفی

Entity Framework Core (EF Core) یک ORM است که تعامل با پایگاه داده را ساده می‌کند.

نصب پکیج‌ها

dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Design

این پکیج‌ها برای SQL Server و ابزارهای Migration لازم هستند.

تعریف مدل

using System.ComponentModel.DataAnnotations;
public class Product
{
    public int Id { get; set; }
    [Required(ErrorMessage = "نام الزامی است")]
    public string Name { get; set; }
    [Range(1, 1000, ErrorMessage = "قیمت باید بین 1 تا 1000 باشد")]
    public decimal Price { get; set; }
}

مدل شامل اعتبارسنجی با Data Annotations است.

DbContext

using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
}

این کلاس ارتباط با پایگاه داده را مدیریت می‌کند.

پیکربندی

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

اتصال DbContext به DI.

Connection String

در appsettings.json:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;Database=MyAppDb;Trusted_Connection=True;TrustServerCertificate=True;"
  }
}

Migration

dotnet ef migrations add InitialCreate
dotnet ef database update

این دستورات پایگاه داده را بر اساس مدل ایجاد می‌کنند.

فصل هفتم: عملیات CRUD

کنترلر

کنترلر زیر عملیات ایجاد، خواندن، ویرایش، و حذف را پیاده‌سازی می‌کند:

using Microsoft.AspNetCore.Mvc;
public class ProductsController : Controller
{
    private readonly AppDbContext _context;
    public ProductsController(AppDbContext context) => _context = context;
    public IActionResult Index()
    {
        return View(_context.Products.ToList());
    }
    public IActionResult Create() => View();
    [HttpPost]
    public IActionResult Create(Product product)
    {
        if (ModelState.IsValid)
        {
            _context.Products.Add(product);
            _context.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(product);
    }
    public IActionResult Edit(int id)
    {
        var product = _context.Products.Find(id);
        if (product == null) return NotFound();
        return View(product);
    }
    [HttpPost]
    public IActionResult Edit(Product product)
    {
        if (ModelState.IsValid)
        {
            _context.Products.Update(product);
            _context.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(product);
    }
    public IActionResult Delete(int id)
    {
        var product = _context.Products.Find(id);
        if (product != null)
        {
            _context.Products.Remove(product);
            _context.SaveChanges();
        }
        return RedirectToAction("Index");
    }
}

View (Views/Products/Index.cshtml)

@model List<Product>
<h1>محصولات</h1>
<table>
    <tr><th>شناسه</th><th>نام</th><th>قیمت</th><th>عملیات</th></tr>
    @foreach (var product in Model)
    {
        <tr>
            <td>@product.Id</td>
            <td>@product.Name</td>
            <td>@product.Price</td>
            <td>
                <a asp-action="Edit" asp-route-id="@product.Id">ویرایش</a>
                <a asp-action="Delete" asp-route-id="@product.Id">حذف</a>
            </td>
        </tr>
    }
</table>
<a asp-action="Create">افزودن محصول</a>

فرم ایجاد (Views/Products/Create.cshtml)

@model Product
<form asp-action="Create">
    <label asp-for="Name">نام</label>
    <input asp-for="Name" />
    <span asp-validation-for="Name" class="text-danger"></span>
    <label asp-for="Price">قیمت</label>
    <input asp-for="Price" />
    <span asp-validation-for="Price" class="text-danger"></span>
    <button type="submit">ذخیره</button>
</form>

این کدها یک سیستم کامل CRUD برای مدیریت محصولات ارائه می‌دهند.

فصل هشتم: اعتبارسنجی فرم‌ها

Data Annotations

اعتبارسنجی با استفاده از ویژگی‌های [Required] و [Range] در مدل انجام می‌شود.

using System.ComponentModel.DataAnnotations;
public class Product
{
    public int Id { get; set; }
    [Required(ErrorMessage = "نام الزامی است")]
    public string Name { get; set; }
    [Range(1, 1000, ErrorMessage = "قیمت باید بین 1 تا 1000 باشد")]
    public decimal Price { get; set; }
}

نمایش خطاها

در View از تگ‌های اعتبارسنجی استفاده کنید:

@model Product
<form asp-action="Create">
    <label asp-for="Name">نام</label>
    <input asp-for="Name" />
    <span asp-validation-for="Name" class="text-danger"></span>
    <label asp-for="Price">قیمت</label>
    <input asp-for="Price" />
    <span asp-validation-for="Price" class="text-danger"></span>
    <button type="submit">ذخیره</button>
</form>

این کد خطاهای اعتبارسنجی را به کاربر نمایش می‌دهد.

فصل نهم: Web API

ایجاد API

API برای ارائه داده به کلاینت‌های خارجی (مثل اپلیکیشن‌های موبایل) استفاده می‌شود.

using Microsoft.AspNetCore.Mvc;
[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
    private readonly AppDbContext _context;
    public ProductsController(AppDbContext context) => _context = context;
    [HttpGet]
    public ActionResult<IEnumerable<Product>> GetProducts()
    {
        return _context.Products.ToList();
    }
    [HttpGet("{id}")]
    public ActionResult<Product> GetProduct(int id)
    {
        var product = _context.Products.Find(id);
        if (product == null) return NotFound();
        return product;
    }
    [HttpPost]
    public ActionResult<Product> CreateProduct(Product product)
    {
        _context.Products.Add(product);
        _context.SaveChanges();
        return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
    }
    [HttpPut("{id}")]
    public IActionResult UpdateProduct(int id, Product product)
    {
        if (id != product.Id) return BadRequest();
        _context.Products.Update(product);
        _context.SaveChanges();
        return NoContent();
    }
    [HttpDelete("{id}")]
    public IActionResult DeleteProduct(int id)
    {
        var product = _context.Products.Find(id);
        if (product == null) return NotFound();
        _context.Products.Remove(product);
        _context.SaveChanges();
        return NoContent();
    }
}

تست با Swagger

برای تست API، Swagger را اضافه کنید:

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
app.UseSwagger();
app.UseSwaggerUI();

در مرورگر به /swagger بروید.

فصل دهم: احراز هویت و مجوزدهی

Identity

ASP.NET Core Identity برای مدیریت کاربران و نقش‌ها استفاده می‌شود.

dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore

پیکربندی

builder.Services.AddIdentity<IdentityUser, IdentityRole>(options =>
{
    options.Password.RequiredLength = 6;
    options.Password.RequireDigit = true;
})
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();
app.UseAuthentication();
app.UseAuthorization();

ثبت‌نام کاربر

using Microsoft.AspNetCore.Identity;
public class AccountController : Controller
{
    private readonly UserManager<IdentityUser> _userManager;
    public AccountController(UserManager<IdentityUser> userManager) => _userManager = userManager;
    [HttpPost]
    public async Task<IActionResult> Register(string username, string password)
    {
        var user = new IdentityUser { UserName = username, Email = username };
        var result = await _userManager.CreateAsync(user, password);
        if (result.Succeeded) return RedirectToAction("Index", "Home");
        foreach (var error in result.Errors) ModelState.AddModelError("", error.Description);
        return View();
    }
}

JWT برای API

برای احراز هویت API، از JWT استفاده کنید:

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
builder.Services.AddAuthentication("Bearer").AddJwtBearer(options =>
{
    options.TokenValidationParameters = new()
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = "yourdomain.com",
        ValidAudience = "yourdomain.com",
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("YourSecretKey123456789"))
    };
});

این کد توکن‌های JWT را اعتبارسنجی می‌کند.

فصل یازدهم: Middleware

معرفی

Middleware کدهایی هستند که در Pipeline درخواست اجرا می‌شوند، مثل Authentication یا Logging.

مثال Middleware سفارشی

app.Use(async (context, next) =>
{
    Console.WriteLine($"Request: {context.Request.Path} at {DateTime.Now}");
    await next();
    Console.WriteLine($"Response: {context.Response.StatusCode}");
});

این Middleware اطلاعات درخواست و پاسخ را لاگ می‌کند.

فصل دوازدهم: Dependency Injection

معرفی

DI مدیریت وابستگی‌ها را ساده می‌کند و کد را تست‌پذیر می‌کند.

مثال

builder.Services.AddScoped<IProductService, ProductService>();
public interface IProductService
{
    List<Product> GetProducts();
}
public class ProductService : IProductService
{
    private readonly AppDbContext _context;
    public ProductService(AppDbContext context) => _context = context;
    public List<Product> GetProducts() => _context.Products.ToList();
}

سرویس در کنترلر تزریق می‌شود:

public class ProductsController : Controller
{
    private readonly IProductService _service;
    public ProductsController(IProductService service) => _service = service;
    public IActionResult Index()
    {
        return View(_service.GetProducts());
    }
}

فصل سیزدهم: مدیریت وضعیت

Session

برای ذخیره داده‌های موقت کاربر:

builder.Services.AddSession();
app.UseSession();
HttpContext.Session.SetString("User", "Ali");
var user = HttpContext.Session.GetString("User");

TempData

برای انتقال داده بین درخواست‌ها:

TempData["Message"] = "عملیات موفق";
@TempData["Message"]

TempData پس از خواندن حذف می‌شود.

فصل چهاردهم: SignalR

معرفی

SignalR برای برنامه‌های بلادرنگ مثل چت یا نوتیفیکیشن استفاده می‌شود.

نصب

dotnet add package Microsoft.AspNetCore.SignalR

ایجاد Hub

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}
app.MapHub<ChatHub>("/chathub");

کلاینت

<script src="/lib/signalr/signalr.js"></script>
<script>
    const connection = new signalR.HubConnectionBuilder()
        .withUrl("/chathub")
        .build();
    connection.on("ReceiveMessage", (user, message) => {
        console.log(`${user}: ${message}`);
    });
    connection.start().catch(err => console.error(err));
</script>

این کد یک سیستم چت ساده ایجاد می‌کند.

فصل پانزدهم: Caching

MemoryCache

برای بهبود عملکرد با ذخیره داده‌ها در حافظه:

builder.Services.AddMemoryCache();
public class HomeController : Controller
{
    private readonly IMemoryCache _cache;
    public HomeController(IMemoryCache cache) => _cache = cache;
    public IActionResult Index()
    {
        string time;
        if (!_cache.TryGetValue("time", out time))
        {
            time = DateTime.Now.ToString();
            _cache.Set("time", time, TimeSpan.FromMinutes(5));
        }
        ViewBag.Time = time;
        return View();
    }
}

داده تا ۵ دقیقه در حافظه ذخیره می‌شود.

فصل شانزدهم: Logging

ILogger

برای ثبت رخدادها و دیباگ:

using Microsoft.Extensions.Logging;
public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    public HomeController(ILogger<HomeController> logger) => _logger = logger;
    public IActionResult Index()
    {
        _logger.LogInformation("Index page visited at {time}", DateTime.Now);
        return View();
    }
}

لاگ‌ها در کنسول یا فایل ذخیره می‌شوند.

فصل هفدهم: امنیت

جلوگیری از XSS

Razor به‌صورت پیش‌فرض ورودی‌ها را Encode می‌کند. از @Html.Raw با احتیاط استفاده کنید.

جلوگیری از CSRF

<form asp-action="Create">
    <input name="__RequestVerificationToken" type="hidden" />
    <button type="submit">ارسال</button>
</form>

ASP.NET Core توکن CSRF را خودکار تولید می‌کند.

جلوگیری از SQL Injection

استفاده از EF Core یا پارامترهای SQL مانع تزریق کد می‌شود.

فصل هجدهم: استقرار

انتشار

dotnet publish -c Release -o ./publish

IIS

1. نصب ASP.NET Core Hosting Bundle.

2. کپی فایل‌های publish به سرور.

3. تنظیم Application Pool در IIS.

Docker

FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY ./publish .
ENTRYPOINT ["dotnet", "MyApp.dll"]
docker build -t myapp .
docker run -d -p 8080:80 myapp

این Dockerfile برنامه را در کانتینر اجرا می‌کند.

فصل نوزدهم: مباحث پیشرفته

Unit Testing (xUnit)

برای تست سرویس‌ها:

dotnet add package xunit
public class ProductServiceTests
{
    [Fact]
    public void GetProducts_ReturnsList()
    {
        var options = new DbContextOptionsBuilder<AppDbContext>()
            .UseInMemoryDatabase("TestDb")
            .Options;
        using var context = new AppDbContext(options);
        context.Products.Add(new Product { Id = 1, Name = "Test", Price = 10 });
        context.SaveChanges();
        var service = new ProductService(context);
        var result = service.GetProducts();
        Assert.Single(result);
    }
}

Clean Architecture

جداسازی لایه‌ها (Domain، Application، Infrastructure) برای کد تمیز و قابل نگهداری.

gRPC

برای سرویس‌های با عملکرد بالا:

dotnet add package Grpc.AspNetCore
service Greeter {
    rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
    string name = 1;
}
message HelloReply {
    string message = 1;
}

CQRS با MediatR

جداسازی دستورات (Commands) و پرس‌وجوها (Queries):

dotnet add package MediatR
public class GetProductQuery : IRequest<Product>
{
    public int Id { get; set; }
}
public class GetProductQueryHandler : IRequestHandler<GetProductQuery, Product>
{
    private readonly AppDbContext _context;
    public GetProductQueryHandler(AppDbContext context) => _context = context;
    public async Task<Product> Handle(GetProductQuery request, CancellationToken cancellationToken)
    {
        return await _context.Products.FindAsync(request.Id);
    }
}

ثبت MediatR:

builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));

فصل بیستم: پروژه عملی - فروشگاه آنلاین

معرفی

یک فروشگاه آنلاین با قابلیت نمایش محصولات، سبد خرید، و احراز هویت.

مدل‌ها

public class Product
{
    public int Id { get; set; }
    [Required(ErrorMessage = "نام الزامی است")]
    public string Name { get; set; }
    public decimal Price { get; set; }
}
public class CartItem
{
    public int Id { get; set; }
    public int ProductId { get; set; }
    public int Quantity { get; set; }
    public Product Product { get; set; }
}

کنترلر سبد خرید

public class CartController : Controller
{
    private readonly AppDbContext _context;
    public CartController(AppDbContext context) => _context = context;
    public IActionResult Index()
    {
        var cart = HttpContext.Session.GetObject<List<CartItem>>("Cart") ?? new List<CartItem>();
        return View(cart);
    }
    [HttpPost]
    public IActionResult AddToCart(int productId, int quantity)
    {
        var cart = HttpContext.Session.GetObject<List<CartItem>>("Cart") ?? new List<CartItem>();
        var product = _context.Products.Find(productId);
        if (product != null)
        {
            cart.Add(new CartItem { ProductId = productId, Quantity = quantity, Product = product });
            HttpContext.Session.SetObject("Cart", cart);
        }
        return RedirectToAction("Index");
    }
}

Session Extension

using System.Text.Json;
public static class SessionExtensions
{
    public static void SetObject(this ISession session, string key, object value)
    {
        session.SetString(key, JsonSerializer.Serialize(value));
    }
    public static T GetObject<T>(this ISession session, string key)
    {
        var value = session.GetString(key);
        return value == null ? default : JsonSerializer.Deserialize<T>(value);
    }
}

View سبد خرید (Views/Cart/Index.cshtml)

@model List<CartItem>
<h1>سبد خرید</h1>
<table>
    <tr><th>محصول</th><th>تعداد</th><th>قیمت</th></tr>
    @foreach (var item in Model)
    {
        <tr>
            <td>@item.Product.Name</td>
            <td>@item.Quantity</td>
            <td>@item.Product.Price</td>
        </tr>
    }
</table>

این پروژه یک فروشگاه ساده با سبد خرید را پیاده‌سازی می‌کند.

فصل بیست‌ویکم: منابع و ادامه مسیر

برای تسلط بیشتر:

پیشنهاد: پروژه‌های واقعی مثل سیستم مدیریت کاربران یا اپلیکیشن‌های بلادرنگ بسازید.