سلام دوستان عزیز 🌱
میخواستم یه نکته مهم رو باهاتون در میون بذارم:
من تولیدکننده حرفهای محتوا نیستم، فقط یه علاقهمند به برنامهنویسیام که مثل خیلی از شما، در مسیر یادگیری قدم گذاشته.
با توجه به شرایط کاریام، فقط جمعهها فرصت دارم که تمرین کنم و چیزهایی که یاد میگیرم رو با شما به اشتراک بذارم.
محتواهایی که منتشر میکنم ممکنه پایهای یا برای بعضیها تکراری باشه، اما برای من هر بخش کوچکی از کد یه قدم مهمه برای فهم عمیقتر.
هدفم اینه که با تمرینهای مداوم، حتی اگر تعداد پروژهها زیاد بشه، مفاهیم رو بهخوبی درک کنم و ملکه ذهنم بشه.
اگر محتواها ساده یا ابتدایی هستن، منو ببخشید 🙏
من استاد نیستم، فقط یه یادگیرندهام—مثل شما.
و هر چیزی که یاد میگیرم، با عشق و صداقت منتشر میکنم.
BookSelect (4).zip
حجم:
24.7M
صفحهبندی پیشرفته با Razor و Bootstrap
در این ساختار، فقط چند شماره اطراف صفحه فعلی نمایش داده میشن، با دکمههای «اول»، «قبلی»، «بعدی» و «آخر» برای حرکت سریع. نقطهچینها قبل و بعد از صفحات، به کاربر کمک میکنن مسیر طولانی رو بهتر درک کنه. ظاهر با کلاسهای Bootstrap طراحی شده تا هم زیبا باشه، هم واکنشگرا.
Shop & Orders (3).zip
حجم:
24.9M
ساده کردن کدهای enum helper
سادهسازی نمایش Enum در پروژههای MVC
برای تبدیل مقادیر Enum به متن قابلنمایش (مثل فارسی)، میتونیم از ویژگی
[Display(Name = "...")]استفاده کنیم. بهجای نوشتن کدهای طولانی در کنترلر، با ساخت یک تابع ساده مثل `GetDisplayName()`، هم در کنترلر و هم در View میتونیم متن مناسب رو دریافت کنیم. این کار باعث تمیز شدن کد، کاهش تکرار، و افزایش خوانایی پروژه میشه.
پروژه ASP.Net Core MVC (وب و سی شارپ)
ویرایش پروژه
بیایم این چهار بخش کد رو مرحلهبهمرحله بررسی کنیم تا دقیقاً بدونی چه تفاوتهایی دارن و کد درست برای فرم ویرایش چیه:
---
## ✅ 1. لیست ساده با
Selectو آبجکت ناشناس ViewBag.Authors = _context.Authors .Select(a => new { a.Id, a.FullName }) .ToList(); - فقط یه لیست ساده از
Idو
FullNameمیسازه - خروجی:
List<object>- ❌ برای DropDown قابل استفاده نیست چون ساختارش مناسب
asp-itemsنیست --- ## ✅ 2. لیست آماده با
SelectListViewBag.Authors = new SelectList(_context.Authors.ToList(), "Id", "FullName"); - ساختار مناسب برای DropDown - خروجی:
SelectList- ✅ در View با
asp-items="ViewBag.Authors"قابل استفاده - ❌ اگر مقدار انتخابشده رو مشخص نکنی، DropDown خالی میمونه --- ## ✅ 3. بررسی وجود کتاب تکراری در فرم ویرایش
bool exists = _context.Books .Any(b => b.Title == book.Title && b.AuthorId == book.AuthorId); if (exists) { ModelState.AddModelError("Title", "این نویسنده قبلاً کتابی با این عنوان دارد."); }- بررسی میکنه که آیا همین نویسنده قبلاً کتابی با همین عنوان ثبت کرده یا نه - اگر بله، خطا به
ModelStateاضافه میشه و فرم دوباره نمایش داده میشه - ✅ این بخش کاملاً درسته و برای جلوگیری از دادههای تکراری استفاده میشه ❌ ولی برای افزودن و برای ویرایش مناسب نیست --- ## ✅ 4. ساخت دستی لیست DropDown با
SelectListItemViewBag.Authors = _context.Authors .Select(a => new SelectListItem { Value = a.Id.ToString(), Text = a.FullName }) .ToList(); - خروجی:
List<SelectListItem>- ✅ قابل استفاده در View با
asp-items="ViewBag.Authors"- میتونی برای هر آیتم
Selected = trueبزنی - مناسب برای فرمهایی که مقدار انتخابشده رو از قبل داری --- ## 🔍 نتیجهگیری کلی: | روش | خروجی | مناسب DropDown | کنترل انتخابشده | |------|--------|----------------|-------------------| | Select با آبجکت ناشناس | List<object> | ❌ | ❌ | | SelectList | SelectList | ✅ | با پارامتر چهارم | | SelectListItem دستی | List<SelectListItem> | ✅ | با
Selected = true| --- ## ✨ جمله یادسپاری: > «در فرم ویرایش، یا از SelectList با پارامتر چهارم استفاده کن، یا از SelectListItem با شرط Selected—هر دو روش حرفهای هستن.»
[Required(ErrorMessage = "قیمت محصول الزامی است")]
[Range(1, 1000000, ErrorMessage = "قیمت باید بین ۱ تا ۱,۰۰۰,۰۰۰ باشد.")]
[Column(TypeName = "decimal(18,2)")]
[Display(Name = ":قیمت")]
public decimal Price { get; set; }
بیایم هر کد رو جداگانه بررسی کنیم تا تفاوتشون کاملاً برات روشن بشه:
---
🧮 1. [Column(TypeName = "decimal(18,2)")]
این خط مربوط به تنظیم نوع ستون در دیتابیس هست:
- decimal(18,2) یعنی:
- مجموعاً ۱۸ رقم
- ۲ رقم بعد از اعشار
- یعنی میتونی عددی مثل 1234567890123456.78 ذخیره کنی
📌 این فقط روی ساختار دیتابیس تأثیر داره، نه روی اعتبارسنجی فرم یا محدودیتهای ورود کاربر.
---
✅ 2. [Range(1, 1000000, ErrorMessage = "...")]
این خط مربوط به اعتبارسنجی در فرم و سمت سرور هست:
- یعنی کاربر فقط میتونه عددی بین ۱ تا ۱,۰۰۰,۰۰۰ وارد کنه
- اگر عددی خارج از این بازه وارد بشه، پیام خطا نمایش داده میشه
📌 این فقط روی ورودی کاربر تأثیر داره، نه روی نوع ستون در دیتابیس.
---
🧠 نتیجهگیری
| ویژگی | مربوط به | توضیح |
|-------|-----------|--------|
| decimal(18,2) |
دیتابیس | ظرفیت ذخیره عدد بزرگ با دقت بالا |
| Range(1,1000000) |
اعتبارسنجی | محدودیت ورود عدد توسط کاربر |
🔹 پس حتی اگر دیتابیس اجازه بده عددی مثل 9999999999999999.99 ذخیره بشه، اعتبارسنجی فرم جلوی ورود عدد بالاتر از 1,000,000 رو میگیره.
پروژه ASP.Net Core MVC (وب و سی شارپ)
[Required(ErrorMessage = "قیمت محصول الزامی است")] [Range(1, 1000000, ErrorMessage = "قیمت باید بین
اگر منظورت اینه که در این خط:
csharp [Column(TypeName = "decimal(18,2)")]عدد ۱۸ رو به ۸ تغییر بدیم و بشه:
csharp [Column(TypeName = "decimal(8,2)")]بله، میتونی این کار رو انجام بدی، ولی باید بدونی دقیقاً چه تأثیری داره: --- 🔍 تفاوت decimal(18,2) با decimal(8,2) | نوع | توضیح | |-----|-------| | decimal(18,2) | عددی با حداکثر ۱۸ رقم، که ۲ رقم آن بعد از اعشار است. یعنی تا 9999999999999999.99 قابل ذخیره است. | | decimal(8,2) | عددی با حداکثر ۸ رقم، که ۲ رقم آن بعد از اعشار است. یعنی تا 999999.99 قابل ذخیره است. | 🔹 پس اگر از decimal(8,2) استفاده کنی، بیشترین مقدار قابل ذخیره میشه حدود ۹۹۹ هزار تومان 🔹 اگر محصولاتی با قیمت بالاتر داری، ممکنه خطای overflow یا ذخیره ناقص رخ بده --- ✅ پیشنهاد من چون در اعتبارسنجی Range(1, 1000000) استفاده کردی، decimal(8,2) کفایت میکنه و با اون بازه هماهنگه. پس بله، میتونی با خیال راحت عدد ۱۸ رو به ۸ تغییر بدی تا فضای دیتابیس بهینهتر بشه.
مشکل اینجاست که وقتی عدد خیلی بزرگ وارد میکنی، قبل از اینکه اعتبارسنجی
[Range]فرصت بررسی داشته باشه، مدلسازی (`Model Binding`) در ASP.NET Core با خطای `OverflowException` متوقف میشه**—چون عدد از محدودهی `int` یا `decimal` خارج شده و تبدیل مستقیم شکست میخوره. --- ## ✅ راهحل قطعی: اعتبارسنجی قبل از تبدیل برای اینکه اعتبارسنجی واقعاً کار کنه و خطای سرریز رخ نده، باید: --- ### 1. **نوع فیلد ورودی را از `int` به `string` تغییر بده در مدل ویو (ViewModel) یا مدل فرم، فیلد عددی را به
stringتبدیل کن تا اول اعتبارسنجی انجام بشه، بعد تبدیل:
[Required]
[RegularExpression(@"^\d{1,7}$", ErrorMessage = "عدد باید بین ۱ تا ۹۹۹۹۹۹۹ باشد.")]
public string QuantityInput { get; set; }
🔹 این یعنی فقط عددهای تا ۷ رقم مجاز هستن
🔹 هیچ تبدیل به intانجام نمیشه تا زمانی که خودت کنترل کنی --- ### 2. در کنترلر، تبدیل امن انجام بده
if (!ModelState.IsValid) { return View(model); // ✅ نمایش پیام خطا } if (!int.TryParse(model.QuantityInput, out int quantity)) { ModelState.AddModelError("QuantityInput", "عدد وارد شده معتبر نیست."); return View(model); } if (quantity < 1 || quantity > 1000000) { ModelState.AddModelError("QuantityInput", "عدد باید بین ۱ تا ۱,۰۰۰,۰۰۰ باشد."); return View(model); } // ✅ حالا میتونی با quantity ادامه بدی--- ### 3. در View از `Html.ValidationMessageFor` استفاده کن
<div class="form-group">
<label for="QuantityInput">تعداد</label>
<input asp-for="QuantityInput" class="form-control" />
<span asp-validation-for="QuantityInput" class="text-danger"></span>
</div>
---
## 🎯 نتیجه نهایی
- عدد خیلی بزرگ باعث خطای سرریز نمیشه چون اول بهصورت stringگرفته میشه - اعتبارسنجی کامل انجام میشه - پیام خطا بهصورت زیبا نمایش داده میشه - هیچ خطای
Unhandled Exceptionیا
OverflowExceptionنمیبینی
SmartReports.zip
حجم:
25.3M
پروژه داشبورد گزارشگیری و نمودارها
پروژه ASP.Net Core MVC (وب و سی شارپ)
پروژه داشبورد گزارشگیری و نمودارها
> پروژه : SmartReports - داشبورد گزارشگیری و نمودارها
---
## ✅ لیست کامل پروژه سوم و کارهایی که انجام دادیم
### 1. هدف پروژه
ساخت یک داشبورد گزارشگیری با تمرکز بر:
- سفارشها، مشتریان، محصولات
- نمایش نمودارهای آماری با Chart.js
- طراحی واکنشگرا با Bootstrap
- اجرای آفلاین با فایلهای محلی JS و CSS
---
### 2. ساختار پروژه
| بخش | توضیحات |
|-----|---------|
|
Controllers/ReportsController.cs| کنترلر اصلی گزارشها شامل اکشنهای روزانه، مشتریان، محصولات | |
Models/Report/*.cs| مدلهای گزارش مثل
DailyOrderReport,
TopProductReport,
CustomerActivityReport| |
Views/Reports/*.cshtml| ویوهای گزارشها و نمودارها | |
wwwroot/js/| فایلهای آفلاین: chart.js,
jquery v3.6.0.js,
bootstrap v4.6.2.js| |
wwwroot/css/| فایل آفلاین: bootstrap-v4.6.2.css | | Layout.cshtml | اضافه کردن فایلهای آفلاین و ساخت ظاهر حرفهای | | appsettings.json | اتصال به دیتابیس و تنظیمات پروژه | --- ### 3. اکشنهایی که نوشتیم #### 🔹
DailyOrders()- گروهبندی سفارشها بر اساس تاریخ - محاسبه تعداد سفارش و مجموع قیمت - استفاده از
Include(o => o.Products)- اضافه کردن
AsNoTracking()برای بهینهسازی - ارسال دادهها به View برای نمایش نمودار #### 🔹
TopProducts()- نمایش محصولات پرفروش بر اساس تعداد سفارش - ساخت مدل
TopProductReport- مرتبسازی نزولی بر اساس فروش #### 🔹
CustomerActivity()و
ActiveCustomers()- نمایش همه مشتریان و مشتریان فعال - محاسبه تعداد سفارش و آخرین تاریخ سفارش - ارسال عنوان پویا با ViewBag.Title --- ### 4. نمودارها با Chart.js - ساخت نمودار ستونی برای سفارشها - رنگبندی سفارشی ستونها - نمایش تعداد سفارش بالای هر ستون با
DataLabels- حذف مجموع از Tooltip و نمایش فقط مقدار هر ستون - عنوان پویا مثل:
نمودار تعداد سفارشها — مجموع: ۱۰ عدد--- ### 5. رفع خطاها و بهینهسازیها - اضافه کردن
AsNoTracking()برای جلوگیری از ردیابی اضافی - اصلاح
decimal(8,2)به
decimal(18,2)برای جلوگیری از خطای Overflow - بررسی خطای
OverflowExceptionو تبدیل امن عددهای بزرگ - استفاده از
stringیا
double?برای ورودی عددی با کنترل دستی - طراحی فوتر با Bootstrap که روی دکمهها نیفته - تنظیم فایلهای آفلاین برای اجرای بدون اینترنت --- ### 6. فایلهای آفلاین که استفاده کردی
<!-- CSS --> <link href="~/css/bootstrap-v4.6.2.css" rel="stylesheet" /> <!-- JS --> <script src="~/js/jquery v3.6.0.js"></script> <script src="~/js/bootstrap v4.6.2.js"></script> <script src="~/js/chart.js"></script>--- ## 🎯 نتیجه نهایی پروژه سوم - داشبورد گزارشگیری کامل و قابل توسعه - نمودارهای حرفهای و قابل شخصیسازی - اجرای آفلاین بدون نیاز به CDN - رعایت اصول معماری MVC و بهینهسازی EF Core - پایهای برای آموزش تولید محتوا و پروژههای واقعی
زمان:
حجم:
5.4M
ترجمه مقادیر فنی به متن فارسی در سی شارپ کالبد شکافی الگوی enum در ASP.Net Core MVC
ساخته شده از هوش مصنوعی
پروژه ASP.Net Core MVC (وب و سی شارپ)
ترجمه مقادیر فنی به متن فارسی در سی شارپ کالبد شکافی الگوی enum در ASP.Net Core MVC ساخته شده از هو
بیایم این کد رو کلمه به کلمه و خط به خط بررسی کنیم تا دقیقاً بفهمی چطور enum با DisplayAttribute و EnumHelper ترکیب شده و در کنترلر استفاده شده.
---
✅ بخش اول: تعریف Enum با نامهای نمایشی
csharp
public enum OrderStatus
{
[Display(Name = "در انتظار")]
Pending,
[Display(Name = "تأیید شده")]
Confirmed,
[Display(Name = "ارسال شده")]
Shipped,
[Display(Name = "تحویل داده شده")]
Delivered,
[Display(Name = "لغو شده")]
Canceled
}
🔹 enum OrderStatus
تعریف یک نوع شمارشی برای وضعیت سفارشها
🔹 [Display(Name = "...")]
مشخص کردن نام نمایشی فارسی برای هر مقدار
مثلاً OrderStatus.Pending در View به صورت «در انتظار» نمایش داده میشه
---
✅ بخش دوم: کلاس کمکی برای گرفتن نام نمایشی
csharp
public static class EnumHelper
{
public static string GetDisplayName(Enum value)
{
var field = value.GetType().GetField(value.ToString());
var attr = field?.GetCustomAttribute<DisplayAttribute>();
return attr?.Name ?? value.ToString();
}
}
🔹 GetDisplayName(Enum value)
متدی برای گرفتن نام نمایشی از Enum
🔹 value.GetType().GetField(value.ToString())
دریافت اطلاعات فیلد مربوط به مقدار Enum
🔹 GetCustomAttribute<DisplayAttribute>()
بررسی اینکه آیا ویژگی [Display(Name = "...")] وجود دارد یا نه
🔹 attr?.Name ?? value.ToString()
اگر DisplayAttribute وجود داشت، مقدار Name را برمیگرداند
اگر نبود، نام اصلی Enum را برمیگرداند (مثلاً Pending)
---
✅ بخش سوم: اکشن Index برای صفحه اصلی فروشگاه
csharp
public IActionResult Index()
{
var recentOrders = _context.Orders
.Include(o => o.OrderProducts)
.ThenInclude(op => op.Product)
.OrderByDescending(o => o.OrderDate)
.Take(5)
.ToList()
.Select(o => new
{
o.Id,
o.CustomerName,
o.OrderDate,
StatusText = EnumHelper.GetDisplayName(Enum.Parse<OrderStatus>(o.Status)),
ProductCount = o.OrderProducts.Count,
TotalAmount = o.OrderProducts.Sum(op => op.Product.Price * op.Quantity)
})
.ToList();
var topProducts = _context.Products
.Where(p => p.IsAvailable)
.OrderByDescending(p => p.Price)
.Take(5)
.ToList();
ViewBag.RecentOrders = recentOrders;
ViewBag.TopProducts = topProducts;
return View();
}
🔹 Include و ThenInclude
برای بارگذاری سفارشها و محصولات مرتبط
🔹 OrderByDescending(o => o.OrderDate)
مرتبسازی سفارشها از جدید به قدیم
🔹 Enum.Parse<OrderStatus>(o.Status)
تبدیل رشتهی Status به مقدار enum از نوع OrderStatus
🔹 EnumHelper.GetDisplayName(...)
گرفتن نام فارسی وضعیت سفارش
🔹 ProductCount و TotalAmount
تعداد محصولات و مجموع قیمت سفارش
---
✅ بخش چهارم: اکشن OrderDetails
csharp
public IActionResult OrderDetails(int id)
{
var order = _context.Orders
.Include(o => o.OrderProducts)
.ThenInclude(op => op.Product)
.FirstOrDefault(o => o.Id == id);
if (order == null)
return NotFound();
var status = OrderStatus.Shipped;
var displayName = EnumHelper.GetDisplayName(status);
ViewBag.StatusText = displayName;
return View(order);
}
🔹 Include و ThenInclude
بارگذاری سفارش و محصولات مرتبط
🔹 OrderStatus.Shipped
مقدار Enum بهصورت مستقیم
🔹 EnumHelper.GetDisplayName(status)
گرفتن نام فارسی «ارسال شده»
---
✅ بخش پنجم: اکشن ProductDetails
csharp
public IActionResult ProductDetails(int id)
{
var product = _context.Products.Find(id);
if (product == null)
return NotFound();
return View(product);
}
🔹 Find(id)
یافتن محصول با شناسه
🔹 return View(product)
ارسال محصول به View برای نمایش جزئیات
---
🎯 نتیجهگیری
- Enum با DisplayAttribute برای نمایش فارسی وضعیتها استفاده شده
- کلاس EnumHelper بهصورت عمومی قابل استفاده در همه جا هست
- در کنترلر، مقدار Enum از دیتابیس تبدیل میشه و نام نمایشی گرفته میشه
- این ساختار هم خوانا، هم قابل توسعه، و هم مناسب برای چندزبانهسازیه