تفاوت AddSingleton – AddTransient – AddScoped – جلسه ۵۱

AddSignleton-AddScoped-AddTransient-Dropdown-List-Validation-Session51-min

در این جلسه از آموزش ASP.NET Core MVC به بررسی تفاوت AddScoped، AddTransient و AddSingleton ld می‌پردازیم و اعتبارسنجی DropDownList را پیاده‌سازی میکنیم. ما در جلسه 16ام به صورت تئوری به تفاوت میان این سه سرویس اشاره نمودیم. در این جلسه قصد داریم برای تفهیم بهتر این موضوع، به صورت عملی به بررسی تفاوت میان آنها بپردازیم. همچنین در ادامه این جلسه روشهای پیاده‌سازی اعتبارسنجی بروی DropDown Listها را بررسی میکنیم.

تفاوت میان AddScoped, AddTransient و AddSingleton

همانگونه که قبلا اشاره نمودیم، تفاوت اصلی میان AddSingleton, Addtransient و AddScoped در طول عمر سرویس معرفی شده میباشد. متد AddSingleton یک بار در زمان صدا زدن سرویس ایجاد میگردد و در کل طول زمان وب‌اپلیکشن و تمامی درخواست‌ها ثابت میباشد. همچنین متد AddScoped برای هر درخواست، یک نمونه از سرویس ایجاد میکند و در کل طول درخواست نمونه ایجاد شده معتبر میباشد. در پایان، متد AddTransient برای هر درخواست، یک نمونه از سرویس ایجاد میکند که نمونه ایجاد شده در هر درخواست متفاوت میباشد.

برای مشاهده عملی این تفاوتها، میبایست ریپازیتوری های پروژه این دوره آموزشی را بروی ریپازیتوری‌های ایستا قرار دهیم. پس ابتدا برای موجودیت Category یک ریپازیتوری ایستا ایجاد میکنیم.

    public class StaticCategoryRepository : ICategoryRepository
    {
        List<Category> _categories = new()
        {
            new Category { ID = 1, CategoryName="Bill", Description="Category for recording cost of bills", Active=CategoryActiveOptions.Yes},
            new Category { ID = 2, CategoryName = "Rent", Description = "Category for recording montly rental cost", Active = CategoryActiveOptions.Yes },
            new Category { ID = 3, CategoryName = "Petrol", Description = "Category for recording cost of petrol (Gas)", Active = CategoryActiveOptions.Yes }
        };
        public IEnumerable<Category> GetAllCategories()
        {
            return _categories;
        }
    }

سپس در کلاس Startup و متد ConfigureServices به تغییر رپازیتوری فعال با متدهای AddSingleton, AddTransient و AddScoped خواهیم پرداخت و در ویدئو این جلسه به تشریح تفاوت آنها خواهیم پرداخت.

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContextPool<WebAppDBContext>
                (options=> options.UseSqlServer(Configuration.GetConnectionString("CostDBConnectionSQLServer")));
            services.AddControllersWithViews();
            services.AddSingleton<ICostRepository, StaticCostRepository>();
            services.AddSingleton<ICategoryRepository, StaticCategoryRepository>();
        }

برای اضافه نمودن رپازیتوری ایستا، بهترین متد AddSingleton میباشد.

برای اضافه نمودن ریپازیتوری پایگاه داده، بهترین متد AddScoped میباشد.

پیاده‌سازی اعتبارسنجی DropDownList

پیش‌تر، در جلسه 38ام به مبحث اعتبارسنجی فرم پرداخته ایم و در مورد Data Annotation در جلسات 39ام و 40ام مطالب تکمیلی را ارائه نمودیم. در این جلسه قصد داریم تا به اعتبارسنجی DropDownList بپردازیم. برای این موضوع ابتدا باید به لیست بازشونده (DropDownList) خود انتخاب خنثی یا یک انتخاب غیر معتبر صرفا جهت دادن اطلاعات به کاربر اضافه نماییم. سپس بر اساس داده غیر معتبر گزینه اضافه شده، درون Model و یا ViewModel از Data Annotation و پیغام مناسب برای مبحث اعتبارسنجی استفاده می‌نماییم.

تغییرات مورد نیاز کنترلر برای اعتبارسنجی DropDownList

در این جلسه به پیاده سازی این مبحث بروی پروژه مربوط به این دوره آموزشی میپردازیم. پس ابتدا درون کنترلر CostController یک Non Action Method برای بارگزاری اطلاعات لیست‌های بازشونده ایجاد میکنیم. این متد جهت رعایت اصل Don’t Repeat Yourself – DRY ویا همان خودت را تکرا نکن به پروژه اضافه میگردد. زیرا ما در این کنترلر و در Action Method های مختلف نیاز به تکرار این قطعه کد جهت اماده سازی لیست SelectListItem داریم.

        private void LoadDropDownList()
        {
            var Categories = categoryRepository.GetAllCategories();
            List<SelectListItem> CategoryList = new();
            CategoryList.Add(new SelectListItem("Select a Category", "-1"));
            foreach (var category in Categories)
            {
                CategoryList.Add(new SelectListItem(category.CategoryName, category.ID.ToString()));
            }
            List<SelectListItem> PaymentMethodsList = new();
            PaymentMethodsList.Add(new SelectListItem("Select a Payment Method", ""));
            var PaymentMethods = Enum.GetValues(typeof(PaymentMethods)).Cast<PaymentMethods>().ToList();
            for (var i = 0; i < PaymentMethods.Count; i++)
            {
                PaymentMethodsList.Add(new SelectListItem(PaymentMethods[i].ToString(), i.ToString()));
            }
            ViewBag.Categories = CategoryList;
            ViewBag.PaymentMethods = PaymentMethodsList;
        }

همانگونه که مشاهده نمودید، داده های مورد نظر از پایگاه داده و Enum List واکشی شده و توسط حلقه درون لیست‌های متناظر قرار گرفته است. سپس از این متد در Action Methodهای Create و Edit استفاده مینماییم.

        [HttpGet]
        public IActionResult Create()
        {
            LoadDropDownList();
            return View();
        }
        [HttpPost]
        public IActionResult Create(CreateCostViewModel model)
        {
             if (ModelState.IsValid)
            {
                Cost NewCost = new()
                {
                    Amount = model.Amount,
                    CategoryID = model.CategoryID,
                    Comment = model.Comment,
                    RegisteredDate = model.RegisteredDate,
                    PaymentMethod = model.PaymentMethod
                };
                costRepository.Create(NewCost);
                return RedirectToAction("Index");
            }
            LoadDropDownList();
            return View(model);
        }
        [HttpGet]
        public IActionResult Edit(int id)
        {
            var cost = costRepository.GetCostByID(id);
            LoadDropDownList();
            return View(cost);
        }
        [HttpPost]
        public IActionResult Edit(Cost editedCost)
        {
            if (ModelState.IsValid)
            {
                costRepository.Update(editedCost);
                return RedirectToAction("Index");
            }
            LoadDropDownList();
            return View(editedCost);
        }

تغییرات مورد نیاز View و Model جهت اعتبارسنجی DropDownList

به علاوه، درون نما های خود برای این دو فلید میبایست از asp-validation-for جهت نمایش خطای اعتبار سنجی استفاده نماییم.

    <div>
        <label asp-for="CategoryID" class="form-label"></label>
        <select asp-for=CategoryID asp-items="@ViewBag.Categories" class="form-select"></select>
        <span asp-validation-for="CategoryID" class="text-danger"></span>
    </div>
    <div>
        <label asp-for="PaymentMethod" class="form-label"></label>
        <select asp-for="PaymentMethod" class="form-select" asp-items="@ViewBag.PaymentMethods"></select>
        <span asp-validation-for="PaymentMethod" class="text-danger"></span>
    </div>

همانگونه که در قطعه کد فوق مشاهده میکنید، اطلاعات لیست ها توسط ViewBag به asp-items منتقل میگردد. این ViewBag ها در None Action Method فوق مقدار دهی میگردند. همچنین برای فیلد PaymentMethod از خصوصیت Required و پیغام مناسب استفاده میکنیم. ضمنا به منظور ظاهر نشدن خطای داده نامعتبر از یک علامت سوال در انتهای نوع PaymentMethod استفاده میکنیم. این عملیات به فیلد مورد نظر این امکان را میدهد تا مقدار تهی را به عنوان ورودی قبول کند. با توجه به مقدار -1 در فیلد CategoryID ما از Regular Expression جهت محدود نمودن فیلد به اعداد مثبت استفاده میکنیم. توجه داشته باشید این تغییرات را ما بروی CreateCostViewModel و مدل Cost اعمال میکنیم.

    public class CreateCostViewModel
    {
        [Column(TypeName = "decimal(18, 2)")]
        [Required]
        [DataType(DataType.Currency)]
        public decimal Amount { get; set; }
        [Required]
        [DataType(DataType.Date)]
        [Display(Name ="Registered Data")]
        public DateTime RegisteredDate { get; set; }
        [MaxLength(150)]
        public string Comment { get; set; }
        [RegularExpression("^\\d+$",ErrorMessage ="Please select a category")]
        [Display(Name ="Category")]
        public int CategoryID { get; set; }
        [Display(Name ="Payment Method")]
        [Required(ErrorMessage = "Please select a Payment Method")]
        public PaymentMethods? PaymentMethod { set; get; }
    }

همچنین کد مربوط به مدل Cost به صورت زیر خواهد بود.

    public class Cost
    {
        [Key]
        public int ID { get; set; }
        [Column(TypeName = "decimal(18, 2)")]
        [Required]
        public decimal Amount { get; set; }
        [Required]
        [DataType(DataType.Date)]
        public DateTime RegisteredDate { get; set; }
        [MaxLength(150)]
        public string Comment { get; set; }
        [Required]
        [RegularExpression("^\\d+$", ErrorMessage = "Please select a category")]
        public int CategoryID { get; set; }
        [ForeignKey(nameof(CategoryID))]
        public virtual Category Category { get; set; }
        [Required(ErrorMessage = "Please select a Payment Method")]
        public PaymentMethods? PaymentMethod { set; get; }
        public string InvoiceImagePath { get; set; }
    }

در صورت نیاز به جزئیات بیشتر، میتوانید ویدئو آموزشی این جلسه را تماشا نمایید. همچنین برای آگاهی از جلسات بعدی این دوره آموزشی، ما را در اینستاگرام، تلگرام، یوتیوب و آپارات دنبال کنید. ضمنا لیست کامل جلسات در این قسمت در دسترس شما میباشد و سورس کد این جلسه را میتوانید از GitHub ما دانلود نمایید.

تماشای ویدیو در یوتیوب ما

دانلود اسلایدهای آموزشی این جلسه از اینجا

برچسب ها

0 0 رای ها
امتیازدهی به مقاله
اشتراک در
اطلاع از
guest
0 نظرات
بازخورد (Feedback) های اینلاین
مشاهده همه دیدگاه ها
0
افکار شما را دوست داریم، لطفا نظر دهید.x