این آموزش شما را از مفاهیم پایه تا پیشرفته ASP.NET Core با مثالهای عملی و پروژه فروشگاه آنلاین هدایت میکند. مناسب برای مبتدیان و حرفهایها.
ASP.NET Core فریمورک متنباز و کراسپلتفرم مایکروسافت است که برای ساخت برنامههای وب مدرن، APIها، و برنامههای بلادرنگ استفاده میشود. این فریمورک بر پایه .NET ساخته شده و از زبان C# پشتیبانی میکند.
نکته: ASP.NET Core جایگزین ASP.NET Framework شده و روی ویندوز، لینوکس، و مک اجرا میشود.
Web Forms مدل قدیمی مبتنی بر رویداد بود که پیچیدگیهایی در توسعه و نگهداری داشت. ASP.NET Core MVC از معماری مدرن با جداسازی لایهها (Model، View، Controller) استفاده میکند که توسعه را سادهتر و تستپذیر میکند.
دانش پایه C#، HTML، CSS، JavaScript، و آشنایی با SQL Server برای کار با پایگاه داده.
برای شروع توسعه، ابزارهای زیر ضروری هستند:
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).
برای ساخت پروژه:
یا از CLI:
dotnet new webapp -n MyWebApp
cd MyWebApp
پروژه شامل پوشهها و فایلهای زیر است:
Program.cs: نقطه ورود برنامه، تنظیم سرویسها و Middleware.appsettings.json: تنظیمات مثل Connection String.wwwroot: فایلهای استاتیک (CSS، JS، تصاویر).Controllers: منطق برنامه.Views: فایلهای Razor برای رابط کاربری.با دکمه F5 در Visual Studio یا دستور زیر:
dotnet run
مرورگر باز شده و آدرس https://localhost:5001 را نمایش میدهد.
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 ارسال میکند.
Views/Home/Index.cshtml)@{
ViewData["Title"] = "صفحه اصلی";
}
<h1>@ViewData["Message"]</h1>
این View پیام خوشآمدگویی را نمایش میدهد.
Razor امکان ترکیب کد C# با HTML را فراهم میکند. از @ برای درج کد استفاده میشود.
@{
var message = "سلام ASP.NET Core";
var now = DateTime.Now;
}
<h2>@message - @now.ToString("yyyy-MM-dd")</h2>
این کد یک پیام و تاریخ جاری را نمایش میدهد.
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 است.
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.
در appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=MyAppDb;Trusted_Connection=True;TrustServerCertificate=True;"
}
}
dotnet ef migrations add InitialCreate
dotnet ef database update
این دستورات پایگاه داده را بر اساس مدل ایجاد میکنند.
کنترلر زیر عملیات ایجاد، خواندن، ویرایش، و حذف را پیادهسازی میکند:
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");
}
}
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 برای مدیریت محصولات ارائه میدهند.
اعتبارسنجی با استفاده از ویژگیهای [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>
این کد خطاهای اعتبارسنجی را به کاربر نمایش میدهد.
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();
}
}
برای تست API، Swagger را اضافه کنید:
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
app.UseSwagger();
app.UseSwaggerUI();
در مرورگر به /swagger بروید.
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();
}
}
برای احراز هویت 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 کدهایی هستند که در Pipeline درخواست اجرا میشوند، مثل Authentication یا Logging.
app.Use(async (context, next) =>
{
Console.WriteLine($"Request: {context.Request.Path} at {DateTime.Now}");
await next();
Console.WriteLine($"Response: {context.Response.StatusCode}");
});
این Middleware اطلاعات درخواست و پاسخ را لاگ میکند.
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());
}
}
برای ذخیره دادههای موقت کاربر:
builder.Services.AddSession();
app.UseSession();
HttpContext.Session.SetString("User", "Ali");
var user = HttpContext.Session.GetString("User");
برای انتقال داده بین درخواستها:
TempData["Message"] = "عملیات موفق";
@TempData["Message"]
TempData پس از خواندن حذف میشود.
SignalR برای برنامههای بلادرنگ مثل چت یا نوتیفیکیشن استفاده میشود.
dotnet add package Microsoft.AspNetCore.SignalR
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>
این کد یک سیستم چت ساده ایجاد میکند.
برای بهبود عملکرد با ذخیره دادهها در حافظه:
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();
}
}
داده تا ۵ دقیقه در حافظه ذخیره میشود.
برای ثبت رخدادها و دیباگ:
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();
}
}
لاگها در کنسول یا فایل ذخیره میشوند.
Razor بهصورت پیشفرض ورودیها را Encode میکند. از @Html.Raw با احتیاط استفاده کنید.
<form asp-action="Create">
<input name="__RequestVerificationToken" type="hidden" />
<button type="submit">ارسال</button>
</form>
ASP.NET Core توکن CSRF را خودکار تولید میکند.
استفاده از EF Core یا پارامترهای SQL مانع تزریق کد میشود.
dotnet publish -c Release -o ./publish
1. نصب ASP.NET Core Hosting Bundle.
2. کپی فایلهای publish به سرور.
3. تنظیم Application Pool در IIS.
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 برنامه را در کانتینر اجرا میکند.
برای تست سرویسها:
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);
}
}
جداسازی لایهها (Domain، Application، Infrastructure) برای کد تمیز و قابل نگهداری.
برای سرویسهای با عملکرد بالا:
dotnet add package Grpc.AspNetCore
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
جداسازی دستورات (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");
}
}
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);
}
}
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>
این پروژه یک فروشگاه ساده با سبد خرید را پیادهسازی میکند.
برای تسلط بیشتر:
پیشنهاد: پروژههای واقعی مثل سیستم مدیریت کاربران یا اپلیکیشنهای بلادرنگ بسازید.