مدیریت خطا در ASP.NET Core
دوره ساخت Minimal APIs در NET 7.
Learn Minimal APIs in .NET 7
Learn how to build Minimal APIs in .NET 7 with hands-on course. By the end of the course, you will be able to build well-constructed Minimal API Endpoints using C#, .NET7, and Swagger.
⭐️ Contents ⭐️
⌨️ (0:00:00) Introduction
⌨️ (0:01:30) Topics Covered
⌨️ (0:02:47) Why Minimal API?
⌨️ (0:06:07) Create Project
⌨️ (0:07:57) Comparing Files Minimal vs Standard
⌨️ (0:11:05) Program file changes
⌨️ (0:13:50) Clean Program class file
⌨️ (0:16:02) API Basics
⌨️ (0:16:44) What is API?
⌨️ (0:21:11) Request and response
⌨️ (0:25:59) Request Object
⌨️ (0:30:12) Response Object
⌨️ (0:35:36) httpverb
⌨️ (0:40:38) Create First Endpoint
⌨️ (0:43:43) Return Types
⌨️ (0:46:15) Route Parameters
⌨️ (0:48:29) Create Coupon Model and Coupon Store
⌨️ (0:51:38) Get All Endpoint
⌨️ (0:53:09) Get Individual Coupon
⌨️ (0:55:19) Create Coupon
⌨️ (0:59:53) Name Endpoints
⌨️ (1:03:17) Products and Accepts in Minimal API
⌨️ (1:06:58) Dependency Injection in Minimal API
⌨️ (1:10:25) Add DTOs
⌨️ (1:13:56) AutoMapper and Dependency Injection
⌨️ (1:18:32) Fluent Validators
⌨️ (1:24:07) Async Endpoints
⌨️ (1:26:11) API Response
⌨️ (1:32:57) Assignment - Put and Delete
⌨️ (1:33:49) Assignment Solution - Put and Delete Endpoints
//برای یک خاصیت مشخص در یک کلاس مشخص modelBuilder.Entity<Department>().Ignore(t => t.Budget); // برای یک کلاس مشخص modelBuilder.Ignore<OnlineCourse>(); // برای نام خاصیتی مشخص در تمام کلاسهای نگاشت شده modelBuilder.Types().Configure(c => c.Ignore("IsDeleted")); // صرفنظر کردن از تمام ایینامها در تمام کلاسهای نگاشت شده modelBuilder.Types().Configure(typeConfiguration => { foreach (var property in typeConfiguration.ClrType .GetProperties().Where(p => p.PropertyType.IsEnum)) { typeConfiguration.Ignore(property); } }); // صرفنظر کردن از خواصی که با یک نام مشخص شروع میشوند در تمام کلاسها modelBuilder.Types().Configure(typeConfiguration => { foreach (var property in typeConfiguration.ClrType .GetProperties().Where(p => p.Name.StartsWith("someName"))) { typeConfiguration.Ignore(property); } });
Any experienced .NET developer knows that even though .NET applications have a garbage collector, memory leaks occur all the time. It’s not that the garbage collector has bugs, it’s just that there are ways we can (easily) cause memory leaks in a managed language.
Memory leaks are sneakily bad creatures. It’s easy to ignore them for a very long time, while they slowly destroy the application. With memory leaks, your memory consumption grows, creating GC pressure and performance problems. Finally, the program will just crash on an out-of-memory exception.
In this article, we will go over the most common reasons for memory leaks in .NET programs. All examples are in C#, but they are relevant to other languages.
In .NET 6 (preview 4), two long-awaited types have been introduced as part of the core library. DateOnly and TimeOnly allow developers to represent either the date or time portion of a DateTime. These two new types are structs (value types) and may be used when your code deals with date or time concepts independently. Both types can be found in the System namespace. Using these new types may align well with how databases allow similar data to be represented. Specifically, these types align well with the SQL Server date and time data types.
_identityVerifier.Initialize(); var isValidIdentity = _identityVerifier.Validate( application.Applicant.Name, application.Applicant.Age, application.Applicant.Address);
_creditScorer.CalculateScore(application.Applicant.Name, application.Applicant.Address); if (_creditScorer.Score < MinimumCreditScore) { return application.IsAccepted; }
تنظیم مقدار خاصیت Score شیء Mock شده
اینترفیس ICreditScorer به صورت زیر تعریف شدهاست و دارای خاصیت Score میباشد که مقدار عددی آن با مقدار حداقل اعتبار تنظیم شدهی در کلاس LoanApplicationProcessor مقایسه خواهد شد (MinimumCreditScore = 100_000):
namespace Loans.Services.Contracts { public interface ICreditScorer { int Score { get; } void CalculateScore(string applicantName, string applicantAddress); } }
var mockCreditScorer = new Mock<ICreditScorer>(); mockCreditScorer.Setup(x => x.Score).Returns(110_000);
اکنون اگر متد آزمایش واحد Accept را بررسی کنیم، چون شخص درخواست دهنده، دارای اعتبار بیشتری از حداقل اعتبار مورد نیاز است، این آزمایش با موفقیت به پایان خواهد رسید. اگر این تنظیم صورت نمیگرفت، شیء mockCreditScorer، مقدار پیشفرض int یا همان صفر را به عنوان مقدار Score بازگشت میداد.
تنظیم مقادیر خواص تو در تو و سلسله مراتبی اشیاء Mock شده
برای کار با خواص تو در تو، ابتدا دو مدل زیر را ایجاد میکنیم:
namespace Loans.Models { public class ScoreResult { public ScoreValue ScoreValue { get; } } public class ScoreValue { public int Score { get; } } }
using Loans.Models; namespace Loans.Services.Contracts { public interface ICreditScorer { int Score { get; } void CalculateScore(string applicantName, string applicantAddress); ScoreResult ScoreResult { get; } } }
//if (_creditScorer.Score < MinimumCreditScore) if (_creditScorer.ScoreResult.ScoreValue.Score < MinimumCreditScore)
برای رفع این مشکل در متد آزمون واحد Accept، باید به صورت زیر عمل کرد:
var mockCreditScorer = new Mock<ICreditScorer>(); mockCreditScorer.Setup(x => x.Score).Returns(110_000); var mockScoreValue = new Mock<ScoreValue>(); mockScoreValue.Setup(x => x.Score).Returns(110_000); var mockScoreResult = new Mock<ScoreResult>(); mockScoreResult.Setup(x => x.ScoreValue).Returns(mockScoreValue.Object); mockCreditScorer.Setup(x => x.ScoreResult).Returns(mockScoreResult.Object);
سپس یک سطح بالاتر را یعنی ScoreResult را تنظیم خواهیم کرد. در اینجا نیاز است خاصیت ScoreValue آن به mock object قبلی تنظیم شود. به همین جهت Returns آن به خاصیت Object شیء mockScoreValue، تنظیم شدهاست.
در آخر برای تنظیم خاصیت ScoreResult شیء mockCreditScorer اصلی، از شیء mockScoreResult استفاده خواهیم کرد.
در این حالت اگر متد آزمون واحد Accept را اجرا کنیم، اینبار به خطای زیر برخواهیم خورد:
Test method Loans.Tests.LoanApplicationProcessorShould.Accept threw exception: System.NotSupportedException: Unsupported expression: x => x.Score Non-overridable members (here: ScoreValue.get_Score) may not be used in setup / verification expressions.
namespace Loans.Models { public class ScoreResult { public virtual ScoreValue ScoreValue { get; } } public class ScoreValue { public virtual int Score { get; } } }
ساده سازی روش تنظیم مقادیر خواص تو در تو و سلسله مراتبی اشیاء Mock شده
روش دیگری نیز برای تنظیم مقادیر خواص تو در تو در کتابخانهی Moq وجود دارد:
mockCreditScorer.Setup(x => x.ScoreResult.ScoreValue.Score).Returns(110_000);
بدیهی است در این حالت نیز باید شرط virtual بودن این خواص، برقرار باشد؛ در غیراینصورت همان استثنای NotSupportedException را دریافت خواهیم کرد.
یک نکته: اگر در زمان تشکیل یک Mock object، مقدار خاصیت DefaultValue آنرا به صورت زیر تنظیم کنیم:
var mockCreditScorer = new Mock<ICreditScorer> { DefaultValue = DefaultValue.Mock };
بررسی تغییرات مقادیر خواص اشیاء Mock شده
کتابخانهی Moq، امکان ردیابی تغییرات مقادیر خواص اشیاء Mock شده را نیز داراست. برای نمایش آن، فرض کنید خاصیت جدید Count را به اینترفیس ICreditScorer اضافه کردهایم:
using Loans.Models; namespace Loans.Services.Contracts { public interface ICreditScorer { int Score { get; } void CalculateScore(string applicantName, string applicantAddress); ScoreResult ScoreResult { get; } int Count { get; set; } } }
_creditScorer.CalculateScore(application.Applicant.Name, application.Applicant.Address); _creditScorer.Count++;
Assert.AreEqual(1, mockCreditScorer.Object.Count);
برای فعال سازی ردیابی تغییرات مقادیر خاصیت Count، تنها کافی است آنرا توسط متد SetupProperty، معرفی کنیم:
mockCreditScorer.SetupProperty(x => x.Count);
در اینجا میتوان یک مقدار اولیه را هم درنظر گرفت:
mockCreditScorer.SetupProperty(x => x.Count, 10);
فعالسازی بررسی تغییرات تمام مقادیر خواص اشیاء Mock شده
اگر تعداد خواصی که قرار است مورد ردیابی قرارگیرند زیاد است، بجای فراخوانی متد SetupProperty بر روی تک تک آنها، میتوان تمام آنها را به صورت زیر تحت کنترل قرار داد:
mockCreditScorer.SetupAllProperties();
نکتهی مهم: محل قرارگیری SetupAllProperties مهم است. برای مثال اگر این سطر را پس از سطر تنظیم مقدار پیشفرض x.ScoreResult.ScoreValue.Score قرار دهید، آزمایش با شکست مواجه میشود؛ چون تنظیمات بازگشت مقادیر پیشفرض خواص را به طور کامل بازنویسی میکند. بنابراین این سطر باید پیش از سطر تنظیم مقادیر پیشفرض خواص Mock شده، فراخوانی شود تا بر روی این مقادیر تنظیمی، تاثیری نداشته باشد.
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: MoqSeries-03.zip
Mini Course #1 Clean Architecture + CQRS - YouTube
00:00:00 - Intro
00:01:10 - Why do we record this course?
00:04:39 - Layered architecture: Why I don't like it anymore?
00:27:27 - Clean architecture
00:38:16 - Course prerequisites (still can't pronounce it correctly)
00:42:30 - What do we build?
00:45:18 - *Domain Layer*
00:49:57 - Entity
01:00:20 - Primitive obsession code smell
01:03:20 - Value Object
01:10:54 - Custom exceptions
01:33:25 - Domain model validation
01:38:55 - Aggregate
01:50:50 - Domain event
02:14:30 - Factory
02:28:50 - Policy
02:43:50 - Repository
02:48:55 - Domain Layer: Summary
02:56:45 - CQS: Command Query Separation
03:07:46 - CQRS: Command Query Responsibility Segregation
03:29:48 - *Application Layer*
03:30:25 - Command/Command Handler/Command Dispatcher definitions
03:40:45 - Automatic command handlers registration
03:44:12 - Application & Domain registration
03:50:52 - Command
03:55:31 - Command Handler
04:01:11 - Where to put methods related to reading?
04:07:00 - Read Service
04:14:14 - Weather Service
04:28:25 - Overview of the other commands & command handlers
04:34:35 - Query/Query Handler/Query Dispatcher definitions
04:44:37 - Automatic query handlers registration (BONUS: example of copy/paste pattern)
04:52:50 - How to tackle reading on Query side?
05:06:30 - *Infrastructure Layer*
05:07:56 - Configuration of Entity Framework Core
05:15:15 - Read Models
05:19:05 - ReadDbContext & WriteDbContext
05:24:13 - EF Entity Configuration
05:42:37 - DbContexts registration
05:55:51 - Query Handlers
06:12:18 - Repository implementation on top of EF Core
06:16:45 - Read Service implementation on top of EF Core
06:19:00 - Dummy Weather Service implementation
06:23:20 - EF Migration
06:29:50 - Applying EF migrations automatically
06:39:38 - *Presentation Layer*
06:41:35 - Controller
06:50:43 - How to return ID of resource in CQRS approach?
07:00:02 - Testing API
07:09:29 - *Cross Cutting Concerns*
07:09:30 - Error Handling
07:20:49 - Logging
07:34:57 - *Unit Testing*
07:42:34 - Unit Test on Domain Layer
08:09:45 - Unit Test on Application Layer
08:34:00 - Summary