<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های محمد کمائی - Telegram : @komayi</title>
        <link>https://virgool.io/feed/@komaei</link>
        <description>c# - asp.net core - blazor - angular - react - flutter - wordpress - sql server - Tel : +989371448346</description>
        <language>fa</language>
        <pubDate>2026-04-15 06:54:28</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/328432/avatar/NPoGz8.png?height=120&amp;width=120</url>
            <title>محمد کمائی - Telegram : @komayi</title>
            <link>https://virgool.io/@komaei</link>
        </image>

                    <item>
                <title>ارور circular dependency در net core</title>
                <link>https://virgool.io/@komaei/%DB%8C%DA%A9-%D8%B1%D8%A7%D9%87-%D8%AD%D9%84-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%A7%D8%B1%D9%88%D8%B1-circular-dependency-%D8%AF%D8%B1-net-core-c8tc7hyaqjyo</link>
                <description>وقتی یک سرویس کلاس به متدهای یک سرویس کلاس دیگه نیاز داره کلاس دوم رو در کلاس اول اینجکت میکنیم و از متدهاش استفاده می کنیم. معمولا هم از روش &quot;constructor injection&quot; استفاده میشود که مزیت نوشتن تنها یکبار در کلاس و استفاده در همه متدهای در سطح کلاس را دارد همچنین امکان mock کردن وابستگی و تست نویسی را دارد. وقتی به کانستراکتور سرویس اول سرویس دوم رو اینجکت میکنیم دات نت در زمان runtime وقتی میاد از سرویس 1 آبجکت بسازه قبلش باید از همه وابستگی هایی که در کانستراکتور سرویس اول وجود داره از جمله سرویس 2 آبجکت بسازه.  تا اینجا مشکلی نیست ، ولی در سیستم های نرم افزاری بزرگ احتمال وابستگی سرویس کلاس 2 به سرویس کلاس 1 هم وجود دارد ، البته باید در طراحی سیستم دقت لازم شود تا این اتفاق نیفتد ولی اگر افتاد اینجوری میشه که : وقتی میاد از کلاس 1 آبجکت بسازه میبینه که کلاس 1 وابستگی به کلاس های دیگه داره پس باید از همه وابستگی های کلاس 1 (که کلاس 2 هم جزوش هست) آبجکت بسازه و وقتی میره از کلاس 2 آبجکت بسازه باز در کانستراکتور کلاس 2 میبینه که باید از کلاس 1 آبجکت بسازه پس میفته در یک لوپ تکراری بی نهایت و موقع استارت کردن پروژه این ارور رو میده:System.AggregateException: &#x27;Some services are not able to be constructed (Error while validating the service descriptor &#x27;ServiceType: BlazorHosted.Server.Services.IService1 Lifetime: Scoped ImplementationType: BlazorHosted.Server.Services.Service1&#x27;: A circular dependency was detected for the service of type &#x27;BlazorHosted.Server.Services.IService1&#x27;.در فایل program.cs هم که به سرویس کالکشن دات نت کور دو سرویس مون رو اضافه کردیم تا در هر کلاسی نیاز به اینجکت باشه کار instantiate یا همون new کردن آبجکت رو انجام بده. چه با &quot;کلاس&quot; چه با &quot;اینترفیس&quot; هم اینجکت کنیم این ارور رو میگیریم (اینجا با اینترفیس بوده) :حتی به صورت غیر مستقیم هم این اتفاق میفته ، در تصویر زیر A و C براشون این اتفاق افتاده.اگر در کانستراکتورها به صورت &lt;&gt;Lazy اینجکت کنیم هم این ارور رو میگیریم :The lazily-initialized type does not have a public, parameterless constructorعلت اصلی به وجود آمدن این وابستگی ها طراحی اشتباه سیستم یا دیتابیس و یا وجود آنتی پترن در معماری نرم افزار است مثلا وجود لایه اضافی و اشتباه و آنتی پترن ریپازیتوری روی ef core که هم باعث پیچیدگی هم کاهش پرفرمنس وب اپ asp.net core میشه ، راه حل اصلی و اصولی اینه که با اصلاح طراحی و معماری این وابستگی ها اصلاح و حذف بشن (اینجکت DbContext در کلاس های سرویس و حذف کلاسهای ریپازیتوری) ولی اگر موارد استثنا موند و نمی شد کاریش کرد میشه از این راه ها استفاده کرد :- یک راه موقت میتونه این باشه که یک کلاس جدید مثلا با نام ShareClass بسازیم و هر دو وابستگی رو در کلاسهای 1 و 2 حذف کنیم و متدهایی که در کلاس 2 بودن و کلاس 1 بهشون نیاز داره رو به ShareClass منتقل کنیم همینطور متدهایی که در کلاس 1 بودن و کلاس 2 بهشون نیاز داره رو به ShareClass منتقل کنیم و ShareClass رو به هر دو کلاس های 1 و 2 اینجکت کنیم ، ولی اتفاقی که میفته اینه که بعد یه مدت کلی متد که باید در جای درست خودشون باشن به کلاسهای Share منتقل میشن و دیگه توسعه و نگهداری و برنامه نویسی رو برامون سخت میکنه.- یک راه حل میتونه استفاده از پترن mediator و پکیج mediatr باشه که اینطوری همه سرویس کلاسها نهایتا فقط یک وابستگی اونم به مدیت آر داشته باشن و مشکلی بابت وابستگی های رفت و برگشتی ندارن.- یک راه حل دیگه میتونه این باشه که به صورت &quot;پیشفرض&quot; با همون روش &quot;constructor injection&quot; پیش رفت و &quot;هر وقت نیاز به اینجکت های بازگشتی&quot; مثل تصاویر کلاس های 1 و 2 در بالا شد از IServiceProvider خود دات نت استفاده کرد یعنی این اینترفیس رو در کلاسهای 1 و 2 اینجکت کرد و هر جا نیاز به استفاده از متدهای کلاس دیگر شد از متد GetRequiredService اش که به صورت Generic هست استفاده کرده و از سرویس پرووایدر دات نت یک نمونه از کلاس مورد نیاز رو گرفت و با زدن دات از متدهاش استفاده کرد به صورت زیر:در این تصویر از روش جدید primary constructor در دات نت 8 برای اینجکت استفاده شده است.نکته : به جای اینجکت دونه دونه سرویس کلاس ها در program.cs میشه یه کار راحت تری انجام داد اونم اینکه اسم همه این کلاسها رو به Service ختم کنیم و با یه حلقه به سرویس پرووایدر دات نت اضافه کنیم به این صورت :var appServices = typeof(Program).Assembly.GetTypes().Where(s =&gt; s.Name.EndsWith(&quot;Service&quot;) &amp;&amp; s.IsInterface == false).ToList();foreach (var appService in appServices)  builder.Services.Add(new ServiceDescriptor(appService, appService,   ServiceLifetime.Scoped));- راه قبل برای تعداد وابستگی کم خوبه و مشکلی هم پیش نمیاد ولی اگه پروژه خیلی بزرگ هست با وابستگی های پیچیده و circular dependency های زیاد و اگر بخوایم تست بنویسیم ساخت یک نمونه از IServiceProvider برای mock سخت میشه چون باید تمام سرویس کلاسها رو موقع نمونه سازی بهش بدین ضمن اینکه از خطوط اول سرویس کلاس ها قابل تشخیص نیست که اون کلاس چه وابستگی هایی دارد ، در این مواقع این راه میتونه بهتر باشه : یک اکستنشن متد روی IServiceCollection بسازید به همراه کلاس LazilyResolved و  تمام کلاس هایی که براشون مشکل circular dependency پیش میاد رو به صورت &lt;&gt;Lazy اینجکت کنید.فایل IServiceCollectionExtension.cs :سپس در Program.cs این خط را بعد از اینجکت کلاسها یا بعد اون foreach که بالاتر کدش رو نوشتم بزارید: builder.Services.AddLazyResolution();کلاسهای 3 و 4 که به هم وابستگی دارند را به صورت لیزی به هم اینجکت کنید:و در هر کلاس دیگر که خواستین این کلاسها که مشکل circular dependency دارند را به صورت &lt;&gt;Lazy اینجکت کنید. موقع کال کردن متد مورد نظر هم Value. نیاز است.دو روش آخر به صورت لیزی کار میکنن یعنی تا نیاز به آبجکت کلاس اینجکت شده در متدی نباشه اینجکت نمیشه و مشکل circular dependency رو حل میکنن.</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Mon, 11 Mar 2024 15:37:07 +0330</pubDate>
            </item>
                    <item>
                <title>تریم کردن اتوماتیک فیلدهای متنی قبل از نوشتن در دیتابیس با انتیتی فریم ورک کور - ef core trim all char fields (C# strings) before write to database for all tables and all add or updates</title>
                <link>https://virgool.io/@komaei/%D8%AA%D8%B1%DB%8C%D9%85-%DA%A9%D8%B1%D8%AF%D9%86-%D8%A7%D8%AA%D9%88%D9%85%D8%A7%D8%AA%DB%8C%DA%A9-%D9%81%DB%8C%D9%84%D8%AF%D9%87%D8%A7%DB%8C-%D9%85%D8%AA%D9%86%DB%8C-%D9%82%D8%A8%D9%84-%D8%A7%D8%B2-%D9%86%D9%88%D8%B4%D8%AA%D9%86-%D8%AF%D8%B1-%D8%AF%DB%8C%D8%AA%D8%A7%D8%A8%DB%8C%D8%B3-%D8%A8%D8%A7-%D8%A7%D9%86%D8%AA%DB%8C%D8%AA%DB%8C-%D9%81%D8%B1%DB%8C%D9%85-%D9%88%D8%B1%DA%A9-%DA%A9%D9%88%D8%B1-ef-core-trim-all-char-fields-c-strings-before-write-to-database-for-all-tables-and-all-add-or-updates-k6swjk3h193u</link>
                <description>برای اینکه موقع پر کردن فیلدهای متنی دیتابیس مون ، در سی شارپ هر بار متد Trim رو بعد از فیلدهای متنی ننویسیم میتونیم این کار رو یکجا برای orm محبوبمون یعنی ef core تعریف کنیم تا زحمتشو برامون بکشه.شما می تونید با override کردن متد SaveChangesAsync کلاس DbContext به این امر دست یابید. در متد اورراید شده می‌توانید روی موجودیت‌های در ChangeTracker حرکت کنید و قبل از ذخیره تغییرات در دیتابیس ، تمام پراپرتی های رشته ای را تریم کنید.public override async Task&lt;int&gt; SaveChangesAsync(CancellationToken cancellationToken = default){    TrimStringProperties();    return await base.SaveChangesAsync(cancellationToken);}private void TrimStringProperties(){    var entries = ChangeTracker.Entries()        .Where(e =&gt; e.State == EntityState.Added || e.State == EntityState.Modified);    foreach (var entry in entries)    {        foreach (var property in entry.Properties)        {            if (property.CurrentValue is string stringValue)            {                property.CurrentValue = stringValue.Trim();            }        }    }}اگر code first کار میکنید که همین کافیه.اگر db first کار میکنید و از روی دیتابیس scaffold انجام میدین و کلاس AppDbContext و کلاسهای انتیتی رو میسازید ، برای اینکه بعد از اسکفولد این کد یعنی متد اورراید SaveChangesAsync رو هر بار دستی به AppDbContext که دیلیت میشه و دوباره ساخته میشه اضافه نکنید میتونید یه کلاس partial اضافه کنید و در اون فایل این متد رو بزارید و دیگه این فایل در عملیات اسکفولد دیلیت نمیشه.برای اینکار یه کلاس به نام AppDbContextPartial کنار AppDbContext در فولدر Data که خروجی اسکفولد در اون قرار میگیره اضافه کنید. ابتدا مثل هر کلاس دیگه نام فایل و کلاس جدید مثل هم هستند (AppDbContextPartial). به اسم فایل دست نزنید چون نمیتونید در یک فولدر 2 فایل هم نام داشته باشید. بعد از ایجاد وارد فایل شده و اسم کلاس که AppDbContextPartial هست رو به کلاس اصلی دی بی کانتکس تون تغییر بدین که در این مثال AppDbContext هست. حالا هر دو کلاس AppDbContext که در دو فایل AppDbContextPartial و AppDbContext هستن رو پارشیال کنید (با اضافه کردن کلمه کلیدی partial قبل از کلمه کلیدی class)حالا این دو فایل موقع بیلد پروژه به یک کلاس تبدیل میشن ولی شما دیگه نگران حذف و ساخت مجدد فایل AppDbContext بعد از اسکفولد نیستین.من فایلهای تولیدی کامند اسکفولد ef core رو در فولدر Data میریزیم ، کلاسهای انتیتی در فولدر Models و کلاس AppDbContext رو در فولدر Data که میشه این کامند : dotnet ef dbcontext scaffold &quot;Server=.\SQLExpress2022;Database=MyDb;Trusted_Connection=True;TrustServerCertificate=True&quot; Microsoft.EntityFrameworkCore.SqlServer --no-onconfiguring -o Data/Models --context-dir Data -c AppDbContext -fآپشن o- یعنی output که میشه مسیر خروجی کلاسهای انتیتیآپشن context-dir-- یعنی مسیر خروجی کلاس دی بی کانتکسآپشن c- یعنی اسم class دی بی کانتکس چی باشهآپشن f- یعنی به صورت force فایل های جدید رو بساز و اگر از قبل فایلی با این نام موجود بود حذف کن و دوباره فایل جدید رو بسازآپشن no-onconfiguring-- هم باعث میشه کانکشن استرینگ رو در فایل AppDbContext ننویسه و موقع اینجکت DbContext در فایل program.cs کانکشن استرینگ رو براش ارسال میکنیم.اگه کدها اینجا خوب قابل خوندن نیست کدها رو در استک اور فلو هم گذاشتم :https://stackoverflow.com/questions/76628151</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Thu, 06 Jul 2023 15:28:11 +0330</pubDate>
            </item>
                    <item>
                <title>مدیریت یکپارچه اکسپشن های بیزینسی در دات نت کور و بلیزر - How to global StatusCode handling in asp.net core web api &amp; blazor and show MudBlazor Snackbar</title>
                <link>https://virgool.io/@komaei/%D9%85%D8%AF%DB%8C%D8%B1%DB%8C%D8%AA-%DB%8C%DA%A9%D9%BE%D8%A7%D8%B1%DA%86%D9%87-%D8%A7%DA%A9%D8%B3%D9%BE%D8%B4%D9%86-%D9%87%D8%A7%DB%8C-%D8%A8%DB%8C%D8%B2%DB%8C%D9%86%D8%B3%DB%8C-%D8%AF%D8%B1-%D8%A8%D9%84%DB%8C%D8%B2%D8%B1-how-to-global-statuscode-handling-in-blazor-and-show-mudblazor-snackbar-h2ituo8dwv1y</link>
                <description>اگر مثل من از نوشتن کدهای تکراری فراری هستی اینو بخون. در دات نت کور میشه کاری کرد که وقتی به دلیل یه شرط بیزینسی قراره یه کدی اجرا نشه و پیامی رو برگردونه به کلاینت هی try , catch  و if , else ننوشت و به اصطلاح Global Exception Handling انجام داد.مثلا وقتی یه api داریم به نام ConfirmEmail که کارش اینه که یه UserId بگیره و فیلد IsConfirm جدول User دیتابیس رو به مقدار 1 آپدیت کنه. دو تا چک قبل آپدیت انجام میدیم : 1. آیا رکوردی برای این ایمیل موجود هست؟ 2. آیا قبلا این ایمیل تایید شده یا نه؟ اگر هر بار هندلینگ این چک ها رو بخوایم بنویسیم که اینجوری میشه : در لایه سرویس که appDbContext_ رو داره باید اون شرط ها رو چک کنیم ، بعد یه return انجام بدیم به کنترلر ، بعد در کنترلر روی نتیجه دریافتی از سرویس هم یه if دیگه بنویسیم که اگر فلان چیز رو از سرویس گرفتی یه استتوس کد http رو ریترن کن مثلا Conflict که میشه کد 409. این if و else ها برای بقیه شرط های بیزینسی هم تکرار میشه و اون دستور عملیاتی (Statement) اصلی متد سرویس گم میشه لای اون همه ایف و الس و نوشتن و نگهداری کدها رو خیلی سخت میکنه و تعداد خط های برنامه رو بی جهت زیاد میکنه ، میتونید با یه حساب سرانگشتی تعداد خطوط ایف و الس ها رو در تعداد متدهای سرویس و اکشن متدهای کنترلر ضرب کنید و ببینید چند خط کد میشه.با توجه به هندل کردن استتوس کد 500 توسط میدل ویر ExceptionHandler خود asp.net core نیاز به if  نیست و چک های بیزینسی باید throw new AppException(&quot;MyMsg&quot;) انجام بدن و هندل شدنشون باید یکجا صورت بگیره.راه حل اصولی اینه که در کلاس سرویس throw new Exception کنیم و با این کار جلوی اجرای باقی خطوط رو بگیریم و در کلاس گلوبال هندلری که مینویسیم (ExceptionHandler) یه مدل json با ویژگی های StatusCode و Message رو برگردونیم و از شر نوشتن if و else ها یا try catch ها راحت بشیم.یا اینکه ساده تر کار کنیم و از استتوس کدهای http استفاده کنیم به همراه یه استرینگ ساده که در Response بنویسیم و من این روش رو ترجیح میدم.به جای throw new Exception میشه یه کلاس AppException رو throw کرده که از Exception دات نت ارث بری کرده و به خاطر این ارث بری چند ریختی شده و علاوه بر اکسپشن ، AppException هم هست و میشه با کلمه کلیدی is تشخیص داد که این اکسپشن ، اپ اکسپشن هست و از اکسپشن های تولید شده خود دات نت نیست پس در کلاس گلوبال اکسپشن هندلر  رفتاری که ما میخوایم رو داشته باش یعنی 409 با Message اکسپشن رو به کلاینت برگردون.public class AppException : Exception{    public AppException(string message) : base(message) { }}کلاس ExceptionHandler :public static class ExceptionHandler{    public static void AddExceptionHandler(this IApplicationBuilder app)    {        app.UseExceptionHandler(appError =&gt;        {            appError.Run(async context =&gt;            {                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;                context.Response.ContentType = &quot;application/json&quot;;                var contextFeature = context.Features.Get&lt;IExceptionHandlerFeature&gt;();                if (contextFeature?.Error is AppException)                {                    context.Response.StatusCode = StatusCodes.Status409Conflict;                    await context.Response.WriteAsync(CheckException(contextFeature.Error));                }            });        });    }    private static string CheckException(Exception ex)    {        if (ex.InnerException is not null)            return ex.Message + &quot; - InnerException : &quot; + ex.InnerException.Message;        return ex.Message;    }}حالا این میدل ویر رو در فایل program.cs پروژه web api قبل از app.UseHttpsRedirection اضافه کنید:app.AddExceptionHandler();حالا دیگه نیاز نیست ایف و الس های اضافی بنویسید و فقط کافیه در متد سرویس throw new AppException کنید و تمام.    public async Task&lt;int&gt; ConfirmEmail(Guid userId)    {        var user = await _appDbContext.Users.FirstOrDefaultAsync(u =&gt; u.Id == userId);        if (user is null)            throw new AppException(&quot;This activate code is not valid&quot;);        if (user.IsConfirm == true)            throw new AppException(&quot;This account is activated before&quot;);        user.IsConfirm = true;        return await _appDbContext.SaveChangesAsync();    }حالا همین داستان رو در فرانت اند هم داریم ،  وقتی یه Api رو کال میکنیم و استتوس کد 409=Conflict  رو میگیریم باید بعد از کال کردن api شرط های مختلف بزاریم که مثلا اگه 409 بود یه توستر یا اسنک بار رو در ui نمایش بده. همه این ایف و الس های فرانتی هم قابل حذف شدنه.در انگولار برای مدیریت یکجای همه استتوس کدها به یه http interceptor نیازه. در Blazor این کار به راحتی امکان پذیره توسط ایجاد یک کلاس و ارث بری از کلاس DelegatingHandler که در نیم اسپیس System.Net.Http قرار داره. در واقع این کلاس یک middleware هست که امکان اجرای کدهایی رو قبل از ارسال ریکوئست http و بعد از ارسال ریکوئست http به ما میده. در کدهای بعد از ارسال ریکوئست http چند if میزاریم و هر کدوم از StatusCode های دریافتی از بک اند رو در همین یکجا هندل میکنیم و تمام ، و دیگر در کامپوننت های ui و صفحات سایتمون مدام ایف و الس نمی نویسیم. برای استتوس کد 409 که خودمون throw میکردیم یه اسنک بار از نوع Warning نمایش میدیم با نمایش جمله ای که از بک اند اومده. برای استتوس کد 500 یه اسنک بار از نوع Error نمایش میدیم با نمایش یک جمله ثابت مثلا : سیستم به مشکل برخورد لطفا با پشتیبانی تماس بگیرید. بهتره متن انگلیسی اکسپشنی که دات نت کور در بک اند تولید کرده رو نمایش ندیم چون توی اون متن میتونه اسم دیتابیس یا جداول دیتابیس باشه و از نظر امنیتی نمایش اون کار درستی نیست.public class HttpStatusCodeService : DelegatingHandler{    private readonly ISnackbar _snackbar;    private readonly NavigationManager _navigationManager;    public HttpStatusCodeService(ISnackbar snackbar, NavigationManager navigationManager)    {        _snackbar = snackbar;        _navigationManager = navigationManager;    }    protected override async Task&lt;HttpResponseMessage&gt; SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)    {        // before sending the request        var response = await base.SendAsync(request, cancellationToken);        // after sending the request        if (!response.IsSuccessStatusCode)        {            if (response.StatusCode == HttpStatusCode.Conflict) // here                _snackbar.Add(await response.Content.ReadAsStringAsync(), Severity.Warning);            if (response.StatusCode == HttpStatusCode.InternalServerError)                _snackbar.Add(&quot;Server error , tell us please&quot;, Severity.Error);            if (response.StatusCode == HttpStatusCode.Unauthorized)                _navigationManager.NavigateTo(&quot;/&quot;);        }        return response;    }}اگه کدها قابل خوندن و مشاهده به صورت مناسب نیست در اینجا ، کدها رو توی stackoverflow هم گذاشتم: c# - How to global StatusCode handling in blazor and show MudBlazor Snackbar - Stack Overflow</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Mon, 26 Jun 2023 17:19:11 +0330</pubDate>
            </item>
                    <item>
                <title>Password hash .net core</title>
                <link>https://virgool.io/@komaei/password-hash-net-core-zqohggt8lxjz</link>
                <description>هش کردن پسورد کاربران سیستم هم الزامی هم اجباری هم واجب است و اگر جدول User سیستم لو بره هیچ کس حتی مالک سایت هم نباید پسورد کاربران رو بدونه.هش یک طرفه است و قابل برگشت نیست انکریپت قابل برگشتههکرها لیستی دارن از پسوردهای پراستفاده که با الگوریتمهای معروف هش اونارو هش کردن پس لیست هش پسوردهای پر استفاده رو دارن ، برای جلوگیری از پیدا کردن اونها از لیستشون باید یه متن یا عدد رندوم هم علاوه بر هش ذخیره بشه که بهش میگن سالت پسورد یا نمک (salt password) که دیگه چون پیدا کردن اون سالت رندوم سخته کلا کارشون رو سخت تر و احتمال حدس زدن رو حتی برای پسوردهای پر استفاده نزدیک به صفر میکنهسالت باید ذخیره بشه تا برای ساخت مجدد هش استفاده بشه البته در جایی غیر از کنار هش تا هکر اونو نبینه  ، یه راه ساده برای ذخیره نکردنش اینه که سالت رو با هش ترکیب کرد و موقع لاگین دوباره سالت رو کشید بیرون و هش رو تولید کرد ضمنا وجود سالت باعث میشه دو نفر که پسورد یکسان دارن هش پسوردشون یکسان نشهخوشبختانه روش جایگذاری سالت داخل خود هش رو دات نت کور با سخت ترین الگوریتم انجام داده و من سورس کد آخرین ورژنش یعنی ورژن ۳ اش رو از سورس کد دات نت کور استخراج کردم و اکستنشن متدش کردم و در پروژه هام استفاده میکنماینم کدها :https://stackoverflow.com/a/72429730/9875486لینک گیت هابم که استفاده کردم هم داخل همین لینک هستالبته اگر از asp.net identity استفاده میکنید که متدش در کلاسهای manager اش موجوده و میتونید استفاده کنیداین رو هم مد نظر داشته باشین که موقع لاگین پسورد رسیده به اکشن هش میشه و با هش ذخیره شده داخل دیتابیس مقایسه میشه که اگر هشها یکسان بود یعنی پسورد درسته و کاربر باید لاگین بشه به سیستم.</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Tue, 14 Jun 2022 18:11:38 +0430</pubDate>
            </item>
                    <item>
                <title>نکات پرفرمنسی Visual Studio</title>
                <link>https://virgool.io/@komaei/%D9%86%DA%A9%D8%A7%D8%AA-%D9%BE%D8%B1%D9%81%D8%B1%D9%85%D9%86%D8%B3%DB%8C-visual-studio-u5sutkjuuw01</link>
                <description>در مواقعی که کمبود رم در سیستم دارید می‌توانید برخی از ویژگی‌های ویژوال استودیو را که ممکن است از آنها استفاده نکنید غیر فعال کنید.* Disable automatic file restoreویژوال استودیو به طور خودکار تب هایی را که در دفعه قبل باز مانده بودند، دوباره باز می کند. این می تواند زمان بازکردن یک سلوشن را تا 30٪ یا بیشتر، بسته به نوع پروژه و اسناد باز شده، طولانی کند و باعث دیر باز شدن پروژه هایی مثل Windows Forms و XAML و برخی از فایل های جاوا اسکریپت و تایپ اسکریپت بشه. وقتی این ویژگی باز شدن رو خیلی کند کنه ، ویژوال استودیو در یک نوار زرد به شما اطلاع می دهد. با انجام مراحل زیر می توانید بازگشایی خودکار فایل را غیرفعال کنید:Tools &gt; Options &gt; Projects and Solution &gt; Generalتیک Reopen documents on solution load را بردارید.اگر بازیابی خودکار فایل را غیرفعال کنید، یک راه سریع برای رفتن به فایل‌هایی که می‌خواهید باز شوند، استفاده از یکی از دستورات Go To است:Edit &gt; Go To &gt; Go To All (ctrl+t)Edit &gt; Go To &gt; Go To Last Edit Location : رفتن به آخرین مکان ویرایش (Ctrl+Shift+Backspace)Edit &gt; Go To &gt; Go To Recent File : مشاهده لیستی از فایل های اخیراً بازدید شده* .pdbاگر معمولاً حافظه اصلی یا رم شما در اجرا و دیباگ کم است، می توانید با ایجاد یک یا چند تغییر تنظیم عملکرد را بهتر کنید. برای اشکال زدایی در موقع توسعه ، لود فایلهای سیمبل (pdb.) از نظر منابع حافظه پر هزینه است. می توانید تنظیمات فایلهای pdb را برای حفظ حافظه پیکربندی کنید و پروژه را طوری پیکربندی کنید که فقط ماژول ها را از پروژه لود کند : Tools &gt; Options &gt; Debugging &gt; Symbolsریدیو باتن Load only specified modules را انتخاب کنید.* Disable Diagnostic Toolsتوصیه می شود پس از استفاده ، پروفایل CPU را غیرفعال کنید. این ویژگی می تواند منابع زیادی را مصرف کند. هنگامی که پروفایل CPU فعال می شود ، این حالت در دیباگ بعدی فعال باقی می ماند ، بنابراین ارزش آن را دارد که پس از اتمام به صراحت آن را خاموش کنید.Tools &gt; Options &gt; Debugging &gt; Generalتیک Enable Diagnostic Tools while debugging را بردارید.* Disable XAML Designerدیزاینر XAML به طور پیش‌فرض فعال است ، اما تنها در صورتی منابع را مصرف می‌کند که فایل xaml باز کنید. اگر با فایل‌های XAML کار می‌کنید اما نمی‌خواهید از عملکرد طراح استفاده کنید، این ویژگی را غیرفعال کنید تا مقداری حافظه آزاد شود.برای غیرفعال کردن XAML Designer ، به Tools &gt; Options &gt; XAML Designer بروید و گزینه Enable XAML Designer را غیر فعال کنید.* SSD &amp; Latest Versionحتما از هارد ssd استفاده کنید و windows و vs تون رو روی هارد ssd نصب کنید ، وقتی vs رم کم بیاره از virtual memory استفاده میکنه که روی هارد هست و هر چه هارد سریعتر باشه تجربه توسعه و برنامه نویسی بهتر میشه. همیشه هم از آخرین نسخه ویژوال استودیو استفاده کنید و وقتی در پنجره Notifications یا زنگوله پایین راست برنامه یه عدد میندازه یعنی آپدیت جدید اومده و آپدیت رو انجام بدین. البته از منوی Help &gt; Check for updates هم میتونید به روز بودنتون رو چک کنید.* Disable unused extensionsمنوی  Extensions &gt; Manage Extensions را باز کنید از سمت چپ Installed را انتخاب کنید و افزونه هایی که نمیشناسید یا ازشون استفاده نمیکنید را Disable کنید و برنامه را یک بار ببندید و مجدد باز کنید تا اعمال بشه.</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Sun, 29 May 2022 10:09:14 +0430</pubDate>
            </item>
                    <item>
                <title>نوشتن یک متد سرویس با خروجی از نوع لیستی از آبجکتها بدون نوشتن کلاس Dto</title>
                <link>https://virgool.io/@komaei/%D9%86%D9%88%D8%B4%D8%AA%D9%86-%DB%8C%DA%A9-%D9%85%D8%AA%D8%AF-%D8%B3%D8%B1%D9%88%DB%8C%D8%B3-%D8%A8%D8%A7-%D8%AE%D8%B1%D9%88%D8%AC%DB%8C-%D8%A7%D8%B2-%D9%86%D9%88%D8%B9-%D9%84%DB%8C%D8%B3%D8%AA%DB%8C-%D8%A7%D8%B2-%D8%A2%D8%A8%D8%AC%DA%A9%D8%AA%D9%87%D8%A7-%D8%A8%D8%AF%D9%88%D9%86-%D9%86%D9%88%D8%B4%D8%AA%D9%86-%DA%A9%D9%84%D8%A7%D8%B3-dto-ly1uzpaki0kv</link>
                <description>- وقتی در یک متد سرویس یک کوئری می نویسیم اگر فقط یک مقدار ساده برگردانیم مثل int یا string که مشکلی نیست و خروجی متدمون از همین نوع هاست.- اگر بخوایم از دیتابیس یک کوئری بزنیم و نوع خروجی کوئری هم از نوع poco یا همون entity هامون هست نوع خروجی مون میشه مثلاList&lt;Member&gt; یاIEnumerable&lt;Member&gt;- ولی اگر بخوایم از دیتابیس یک کوئری بزنیم و نوع خروجی کوئری از نوع poco یا همون entity هامون نباشه (مثلا چند تنها دو فیلد از 10 فیلد یک جدول رو برگردونیم یا اینکه چند فیلد از یک جدول و چند فیلد از جدول دیگه دیتابیس که با هم جوین خوردن رو برگردونیم) دو راه داریم : ساختن یک کلاس Dto و قراردادن پراپرتی هایی از جنس خروجی کوئری مون در اون و استفاده اون در کوئری:public IEnumerable&lt;MemberDto&gt; GetMembers()
{
    var members = db.Members
    .Select(m =&gt; new MemberDto { Id = m.MemberId, FullName = m.FullName })
    .ToList();
    return members;
}2. اما اگر بعد از کلمه کلیدی new اسم یک کلاس Dto مون رو نیاریم کامپایلر سی شارپ یک آبجکت بی نام (anonymous object) برامون میسازه و از آنجایی که همه آبجکت ها در سی شارپ از object ارث بری میکنن میشه خروجی متد رو IEnumerable ای از object گذاشت:public IEnumerable&lt;object&gt; GetMembers() 
{     
    var members = db.Members     
    .Select(m =&gt; new { Id = m.MemberId, FullName = m.FullName })     
    .ToList();     
    return members; 
}بدین ترتیب میتونید کلاس Dto رو نساخت و جلوی new هم اسم کلاسی رو نیاورد.نکته : آبجکتهای anonymous object فقط خواندنی هستند (read only) و اگر نیاز بشه که روی لیست members یه foreach بزنید و یکی از فیلدها رو تغییر بدین ارور میگیرین و در این مواقع مجبورید کلاس Dto رو بسازید ، ولی در اکثر مواقع که کوئری از دیتابیس زده میشه و جوابش بدون تغییر به کلاس کنترلر return میشه با این روش نیازی به نوشتن کلاس Dto نیست.</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Sun, 22 May 2022 15:29:04 +0430</pubDate>
            </item>
                    <item>
                <title>there was an error running the selected code generator no database provider - ارور اسکفولد ویژوال استودیو</title>
                <link>https://virgool.io/@komaei/there-was-an-error-running-the-selected-code-generator-no-database-provider-%D8%A7%D8%B1%D9%88%D8%B1-%D8%A7%D8%B3%DA%A9%D9%81%D9%88%D9%84%D8%AF-%D9%88%DB%8C%DA%98%D9%88%D8%A7%D9%84-%D8%A7%D8%B3%D8%AA%D9%88%D8%AF%DB%8C%D9%88-yzfhgmedgmqg</link>
                <description>اگر اسکفولد میزنید در Visual Studio برای ساخت صفحات Razor Page یا کنترلر و ویوی MVC و به ارور میخورید این مراحل رو انجام بدین :Install 4 packages:1.Microsoft.EntityFrameworkCore.SqlServer2.Microsoft.EntityFrameworkCore.Tools3.Microsoft.EntityFrameworkCore.Design4.Microsoft.VisualStudio.Web.CodeGeneration.DesignScaffold the data base and create the DbContext and Entities by scaffold command or ef core power tools vs extension.Inject your data base settings in program.cs :builder.Services.AddRazorPages(); 
builder.Services.AddDbContext(options =&gt; { options.UseSqlServer(builder.Configuration.GetConnectionString(&amp;quotCS&amp;quot)); });Add your connection string to appsettings.json :&quot;AllowedHosts&quot;: &quot;*&quot;, &amp;quotConnectionStrings&amp;quot: { 
&amp;quotCS&amp;quot: &amp;quotData Source=.\SQLEXPRESS;Initial Catalog=MyDb1;Integrated Security=True;MultipleActiveResultSets=True&amp;quot
 }اگر به دردتون خورد یه لایک درstackoverflow بزنید : https://stackoverflow.com/a/72063011/9875486</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Sat, 30 Apr 2022 00:26:13 +0430</pubDate>
            </item>
                    <item>
                <title>فیلتر کردن جدول مستر طوری که در جدول دیتیل رکورد نداشته باشه</title>
                <link>https://virgool.io/@komaei/%D9%81%DB%8C%D9%84%D8%AA%D8%B1-%DA%A9%D8%B1%D8%AF%D9%86-%D8%AC%D8%AF%D9%88%D9%84-%D9%85%D8%B3%D8%AA%D8%B1-%D8%A7%D9%88%D9%84-%D8%B7%D9%88%D8%B1%DB%8C-%DA%A9%D9%87-%D8%AF%D8%B1-%D8%AC%D8%AF%D9%88%D9%84-%D8%AF%DB%8C%D8%AA%DB%8C%D9%84-%D8%B1%DA%A9%D9%88%D8%B1%D8%AF-%D9%86%D8%AF%D8%A7%D8%B4%D8%AA%D9%87-%D8%A8%D8%A7%D8%B4%D9%87-xe2ecrukxm8e</link>
                <description>فرض کنید یک جدول داریم به نام CriticalAlarms که لیستی از لاگهای سیستمی را ذخیره میکند و کاربران ادمین این لیست رو مشاهده میکنن ، اگر هر یوزری یکی از این رکوردهای لاگ یا آلارم رو مشاهده کرد باید در جدول دیگری به نام CriticalAlarmViews که جدول دیتیل تیبل اولی است یک رکورد بزنیم که بگیم این یوزر این آلارم رو مشاهده کرده و بعدا دوباره بهش اون آلارم رو نشون ندیم. در واقع میخوایم معادل t-sql دستور not exists رو بنویسم. تفاوت exists و in در sql server این است که وقتی از in استفاده کنید تمامی اعضای داخل پرانتز in پیمایش میشن ولی اگر از exists استفاده کنید به محض اینکه شرط یا شرطهای داخل پرانتر exists برقرار شد مقدار true برگشت داده میشه و تا انتهای اعضا پیمایش نمیشه. معادل in در ef میشه Contains و معادل exists در ef میشه Any.حالا میخوایم با EF Core لیستی از آلارم ها یعنی جدول مستر رو از دیتابیس واکشی کنیم که در جدول دیتیل رکورد نداشته باشن: (آلارمهای مشاهده نشده)await appDbContext.CriticalAlarms
.Where(a =&gt; !a.CriticalAlarmViews.Any(v =&gt; v.CriticalAlarmId == a.Id))
.ToListAsync();https://stackoverflow.com/a/71108419/9875486</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Mon, 14 Feb 2022 10:42:16 +0330</pubDate>
            </item>
                    <item>
                <title>فیلتر کردن یک لیست سی شارپ بر اساس Id و موجود بودن در لیستی دیگر - List contains in another list by C Sharp</title>
                <link>https://virgool.io/@komaei/%D9%81%DB%8C%D9%84%D8%AA%D8%B1-%DA%A9%D8%B1%D8%AF%D9%86-%DB%8C%DA%A9-%D9%84%DB%8C%D8%B3%D8%AA-%D8%B3%DB%8C-%D8%B4%D8%A7%D8%B1%D9%BE-%D8%A8%D8%B1-%D8%A7%D8%B3%D8%A7%D8%B3-%D9%85%D9%88%D8%AC%D9%88%D8%AF-%D8%A8%D9%88%D8%AF%D9%86-%D8%AF%D8%B1-%D9%84%DB%8C%D8%B3%D8%AA%DB%8C-%D8%AF%DB%8C%DA%AF%D8%B1-list-contains-in-another-list-by-c-vhhpfbzutdj4</link>
                <description>اگر دو لیست در #C دارید و میخواین لیست دوم رو طوری فیلتر یا کم کنید که Id هاش داخل لیست اول باشه به این نحو میشه به راحتی انجام داد:var list1 = await _service1.GetAll();
var list2 = await _service2.GetAll();

// Create a list of Ids from list1
var list1_Ids = list1.Select(l =&gt; l.Id).ToList();

// filter list2 according to list1 Ids
var list2 = list2.Where(l =&gt; list1_Ids.Contains(l.Id)).ToList();اگر به دردتون خورد یه رای به این پستstackoverflowبدین :https://stackoverflow.com/a/71091885/9875486</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Sat, 12 Feb 2022 16:07:32 +0330</pubDate>
            </item>
                    <item>
                <title>افزودن ستون Id از جنس int و identity به UserRole</title>
                <link>https://virgool.io/@komaei/%D8%AA%D8%BA%DB%8C%DB%8C%D8%B1-primary-key-%D8%AC%D8%AF%D9%88%D9%84-userrole-%D8%A8%D9%87-%D8%B5%D9%88%D8%B1%D8%AA-%D8%AA%DA%A9-%D8%B3%D8%AA%D9%88%D9%86-id-%D8%A7%D8%B2-%D8%AC%D9%86%D8%B3-int-%D9%88-identity-uvyhnucejgp6</link>
                <description>معمولا برای هر جدول یک فیلد Id از نوع int یا Guid در نظر میگیریم. ولی asp.net identity برای جدول UserRole این فیلد رو نمیزاره و primary key رو دو ستونه قرار میده (UserId,RoleId)از لحاظ پرفورمنسی بهتره یک ستونه باشه ولی اینجا مجبوریم PK رو دو ستونه نگهش داریم چون اینجوری طراحی شده و اگر تک ستونه بشه متدهای کلاسهای Manger خود asp.net identity از کار میفته مثل userManager.AddToRoleAsync . علاوه بر این ما در کل سیستم به یک نحو جداول رو میسازیم و به یک صورت عملیات crud رو انجام میدیم. حالا اگر بخوایم یک فرم برای ویرایش این جدول در ui بسازیم مثل باقی فرم ها بهتره Id سطر مورد نظر ارسال بشه برای update یا delete.پس میایم ستون Id رو به کلاس UserRole (ارث بری از IdentityUserRole هم داره) اضافه میکنیم auto increment اش میکنیم (identtity:Yes)  و primary key دو ستونه رو هم با fluent api براش ست میکنیم سپس Migration میزنیم. اگر ارور گرفتین دیتابیس رو حذف و دوباره Update-Database رو اجرا کنید. اگر تایپ Id رو هم از Guid به int تبدیل کنیم پرفرمنس بهتری داره.برای مشاهده کدهای مورد نیاز فایلهای DbContext و UserRole و UserRoleConfig به این پست stackoverflow مراجعه کنید:https://stackoverflow.com/a/71014800/9875486یک پروژه تمپلیت هم برای UserManagement درست کردم البته از نوع blazor wasm که کدها اونجا هم هست ، این لینکشه :https://github.com/mammadkoma/attendanceبرای نصب و راه اندازی پروژه توضیحات زیر README.md رو ببینید.</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Mon, 07 Feb 2022 11:21:13 +0330</pubDate>
            </item>
                    <item>
                <title>درج رکوردهای اولیه رل در کد فرست - ef core role seed in code first</title>
                <link>https://virgool.io/@komaei/%D8%AF%D8%B1%D8%AC-%D8%B1%DA%A9%D9%88%D8%B1%D8%AF%D9%87%D8%A7%DB%8C-%D8%A7%D9%88%D9%84%DB%8C%D9%87-%D8%B1%D9%84-%D8%AF%D8%B1-%DA%A9%D8%AF-%D9%81%D8%B1%D8%B3%D8%AA-ef-core-role-seed-in-code-first-drgwctepg6mt</link>
                <description>وقتی میخواین کد فرست کار کنید و بعد از migration رکوردهای اولیه ای در جدولتون داشته باشید باید عملیات seed انجام بدین. در code first پیشنهاد میکنم فایلهای تنظیمات انتیتی تون رو جدا کنید مثلا در فایل UserConfig و فایل DbContext متد OnModelCreating رو طولانی نکنید.برای اضافه کردن این کلاسهای Config هم لازم نیست تک تک به OnModelCreating اضافه کنید ، کافی است اسمبلی یکی از اونها رو با 1 خط فقط اضافه کنید (با متد ApplyConfigurationsFromAssembly) ، ef core همه اون کلاسهای تنظیم رو اعمال میکنه.اما عملیات seed طبق مستندات ماکروسافت محدودیت هایی هم دارد ، یکی از اون محدودیت ها این است :Data that needs key values to be generated by the database, including entities that use alternate keys as the identity.یعنی فیلدهایی که توسط دیتابیس پر میشن مثل فیلدهای پرایمری کی از نوع indentityاگر بخواین برای Role رکوردهای پیش فرض seed کنید و Id رو پر نکنید این ارور رو میگیرید:The seed entity for entity type &#x27;Role&#x27; cannot be added because a non-zero value is required for property &#x27;Id&#x27;. Consider providing a negative value to avoid collisions with non-seed data.پس باید Id رو مقداردهی کنید.برای دیدن کدهای مورد نیاز به این پست بنده در stackoverflow مراجعه کنید:https://stackoverflow.com/a/71007605/9875486</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Sun, 06 Feb 2022 17:07:14 +0330</pubDate>
            </item>
                    <item>
                <title>سورت آرایه ای از آبجکت ها در TypeScript ، Angular</title>
                <link>https://virgool.io/@komaei/%D8%B3%D9%88%D8%B1%D8%AA-%DB%8C%DA%A9-%D8%A2%D8%A8%D8%AC%DA%A9%D8%AA-typescript-%D8%AF%D8%B1-angular-pnnqrob3kxfi</link>
                <description>یک آرایه ای از Dto داریم ، میخوایم در بروزر اون لیست رو بر اساس نام خانوادگی سورت کنیم.فکر میکنید راحته؟ولی وقتی شبیه سایر فانکشنها مثل find و filter مینویسید کار نمیکنه! کد مورد نیاز :this.MyDtoArray.sort((a, b) =&gt; (a.lastName &lt; b.lastName ? -1 : 1));</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Sat, 05 Feb 2022 15:37:15 +0330</pubDate>
            </item>
                    <item>
                <title>تغییر کانکشن استرینگ در زمان اجرا - Dynamically change connection string in Asp.Net Core</title>
                <link>https://virgool.io/@komaei/%D8%AA%D8%BA%DB%8C%DB%8C%D8%B1-%DA%A9%D8%A7%D9%86%DA%A9%D8%B4%D9%86-%D8%A7%D8%B3%D8%AA%D8%B1%DB%8C%D9%86%DA%AF-%D8%AF%D8%B1-%D8%B2%D9%85%D8%A7%D9%86-%D8%A7%D8%AC%D8%B1%D8%A7-dynamically-change-connection-string-in-aspnet-core-rl3gszm5xhns</link>
                <description>اگر چند دیتابیس داشتین با یک ساختار و خواستین با یک DbContext به همه دیتابیس ها وصل بشین لازمه در زمان RunTime کانکشن استرینگ رو تغییر بدین ، کدهای لازم رو در این پست stackoverflow بنده مشاهده کنید:https://stackoverflow.com/a/70951198/9875486Console.WriteLine(&amp;quotHello, World!&amp;quot);
for (int i = 1; i &lt;= 10; i++)
{
    if (i % 2 == 0)
    {
        var _context = new AppDbContext(&amp;quotData Source=.\\SQLEXPRESS;Initial Catalog=test2;Integrated Security=True&amp;quot); // test2
        _context.Tbls.Add(new Tbl { Title = i.ToString() });
        _context.SaveChanges();
    }
    else
    {
        var _context = new AppDbContext(&amp;quotData Source=.\\SQLEXPRESS;Initial Catalog=test1;Integrated Security=True&amp;quot); // test1
        _context.Tbls.Add(new Tbl { Title = i.ToString() });
        _context.SaveChanges();
    }
}public partial class AppDbContext : DbContext
    {
        public AppDbContext(string connectionString) : base(GetOptions(connectionString))
        {
        }

        public virtual DbSet&lt;Tbl&gt; Tbls { get; set; }

        private static DbContextOptions GetOptions(string connectionString)
        {
            return SqlServerDbContextOptionsExtensions.UseSqlServer(new DbContextOptionsBuilder(), connectionString).Options;
        }
    }</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Wed, 02 Feb 2022 09:49:42 +0330</pubDate>
            </item>
                    <item>
                <title>ولیدیشن ایمیل در دات نت - Email validation in .net</title>
                <link>https://virgool.io/@komaei/%D9%88%D9%84%DB%8C%D8%AF%DB%8C%D8%B4%D9%86-%D8%A7%DB%8C%D9%85%DB%8C%D9%84-%D8%AF%D8%B1-%D8%AF%D8%A7%D8%AA-%D9%86%D8%AA-email-validation-in-net-vwtsgpzgaiqa</link>
                <description>در دات نت سیستم ولیدیشن فرم ها به این صورت هست که شما ابتدا یک کلاس برای فرم میسازید و با DataAnnotations ها فیلد ها رو مزین میکنید و فریم ورک دات نت ولیدیشن ها رو براتون تولید میکنه. برای ایمیل این دو گزینه رو داریم که هر دو درست کار نمیکنن: [DataType(DataType.EmailAddress)] :که کاراکتر @ رو تشخیص نمیده! (مگه ایمیل آدرس بدون @ داریم؟)2. [EmailAddress] :که دات (.) رو تشخیص نمیده! (مگه ایمیل آدرس بدون com. داریم؟)این ها در هیچ نوع پروژه وب asp.net ای کار نمیکنه ، چه در web form ، چه در mvc و چه در asp.net core mvc یا blazor.اگر نمیخواین پکیجی برای DataAnnotations ها نصب کنید بهترین راه حل RegularExpression هست:[Regular@&amp;quot^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-‌ ]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$&amp;quot, ErrorMessage = &amp;quotایمیل معتبر نیست.&amp;quot)]البته پیشنهاد میکنم برای متن خطا (ErrorMessage) از یک کلاس Constants استفاده کنید که قابلیت مدیریت در یکجا رو داشته باشید. (در پروژه blazor wasm در لایه Shared این کلاس رو بزارید) :namespace Attendance.Shared;
public static class Constants
{
    public const string RequireMsg = &amp;quotلطفا {0} را وارد کنید.&amp;quot
    public const string RangeMsg = &amp;quot{0} باید در بازه {1} و {2} باشد.&amp;quot
    public const string MinLengthMsg = &amp;quot{0} نباید کمتر از {1} کاراکتر باشد.&amp;quot
    public const string MaxLengthMsg = &amp;quot{0} نباید بیشتر از {1} کاراکتر باشد.&amp;quot
    public const string RegularExpressionMsg = &amp;quot{0} معتبر نیست.&amp;quot
    public const string StringLengthMsg = &amp;quot{0} باید بین {2} کاراکتر و {1} کاراکتر باشد.&amp;quot
    public const string RemoteMsg = &amp;quotاین {0} قبلا در سیستم ثبت شده است.&amp;quot
    public const string CompareMsg = &amp;quot{1} با تکرار آن تطابق ندارد.&amp;quot
}حالا برای متن خطا از این کلاس استفاده کنید :[Regular@&amp;quot^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-‌ ]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$&amp;quot, ErrorMessage = Constants.RegularExpressionMsg)]</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Wed, 29 Dec 2021 11:06:20 +0330</pubDate>
            </item>
                    <item>
                <title>حذف یک فیلد Dto (ViewModel) از خروجی web api های دات نت کور - Remove a property (field) of dto (ViewModel) from asp.net core web api</title>
                <link>https://virgool.io/@komaei/%D8%AD%D8%B0%D9%81-%DB%8C%DA%A9-%D9%81%DB%8C%D9%84%D8%AF-dto-viewmodel-%D8%A7%D8%B2-%D8%AE%D8%B1%D9%88%D8%AC%DB%8C-web-api-%D9%87%D8%A7%DB%8C-%D8%AF%D8%A7%D8%AA-%D9%86%D8%AA-%DA%A9%D9%88%D8%B1-remove-a-property-field-of-dto-viewmodel-from-aspnet-core-web-api-te3nyrathnii</link>
                <description>اگر فیلدی در دیتابیس هست که نباید به صورت json به سمت کاربر ارسال شود ، یا پراپرتی ای در همه کلاسهای Dto (ViewModel) دارید که میخواهید از Response همه api ها حذف شود از این راهها میتونید استفاده کنید :برای حذف کلی هم از ورودی به asp.net core  و هم حذف از خروجی web api های asp.net core میتونید در کلاس Dto روی سر property مورد نظر این attribute رو بزارید :[System.Text.Json.Serialization.JsonIgnore]2. برای حذف field مورد نظر فقط از خروجی web api میتوان از MiddleWare استفاده کرد و از Response حذفش کرد. برای این کار در پروژه asp.net core web api خود یک فولدر به نام Configuration یا Config اضافه کنید و این کلاس رو در اون قرار بدین :using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System.IO;
using System.Threading.Tasks;
namespace YOURPROJECT.Api.Configurations
{
    public class ResponseMiddleware
    {
        private readonly RequestDelegate _next;

        public ResponseMiddleware(RequestDelegate next)
        {
            _next = next;
        }
        public async Task Invoke(HttpContext httpContext)
        {
            var originBody = httpContext.Response.Body;
            try
            {
                var memStream = new MemoryStream();
                httpContext.Response.Body = memStream;
                await _next(httpContext).ConfigureAwait(false);
                memStream.Position = 0;
                var responseBody = new StreamReader(memStream).ReadToEnd();

                // Custom logic to modify response
                if (responseBody.ToCharArray()[0].ToString() != &amp;quot&lt;&amp;quot)
                {
                    var json = (Newtonsoft.Json.Linq.JObject)JsonConvert.DeserializeObject(responseBody);
                    if (json != null)
                        json.Property(&amp;quotpassword&amp;quot)?.Remove();
                    responseBody = json.ToString();
                }
                
                var memoryStreamModified = new MemoryStream();
                var sw = new StreamWriter(memoryStreamModified);
                sw.Write(responseBody);
                sw.Flush();
                memoryStreamModified.Position = 0;

                await memoryStreamModified.CopyToAsync(originBody).ConfigureAwait(false);
            }
            finally
            {
                httpContext.Response.Body = originBody;
            }
        }
    }
}سپس این میدل ویر را در فایل startup.cs در متد Configure و قبل از app.UseEndpoints ثبت کنید :app.UseMiddleware&lt;ResponseMiddleware&gt;();دقت داشته باشید که با روش میدل ویر روی خروجی تمام api ها تاثیر میگذاریم و فیلد password را به صورت اتوماتیک از تمام web api های پروژه حذف میکنیم.</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Sun, 03 Oct 2021 15:28:44 +0330</pubDate>
            </item>
                    <item>
                <title>Remove Server: Microsoft-IIS/10.0 and X-Powered-By: ASP.NET</title>
                <link>https://virgool.io/@komaei/remove-server-microsoft-iis100-and-x-powered-by-aspnet-qzlg9vfphvtd</link>
                <description>If you want to remove Request Headers (asp.net and iis) from browser inspect , network tab , Header&gt;Request Header in asp.net core apps for security reasons do these: X-Powered-By: ASP.NET : go to iis , select your site , double click on Http Response Headers , click onX-Powered-By: ASP.NETand click Remove.Server: Microsoft-IIS/10.0 : Remote to windows server and open command prompt by administrator and execute this line in command prompt : %systemroot%\system32\inetsrv\appcmd.exe set config -section:system.webServer/security/requestFiltering /removeServerHeader:&quot;True&quot;  /commit:apphostاگر مسئول امنیت ازتون خواست که در inspect بروزر ، در تب network ، قسمت Header&gt;Request Header مشخصات فریم ورک یعنی asp.net و وب سرور یعنی IIS نمایش داده نشود موارد 1 و 2 رو که در بالا ذکر شده انجام بدین.</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Sat, 02 Oct 2021 14:59:34 +0330</pubDate>
            </item>
                    <item>
                <title>حذف رکوردهای تکراری در اس کیو ال - Delete Duplicate rows in SQL Server</title>
                <link>https://virgool.io/@komaei/%D8%AD%D8%B0%D9%81-%D8%B1%DA%A9%D9%88%D8%B1%D8%AF%D9%87%D8%A7%DB%8C-%D8%AA%DA%A9%D8%B1%D8%A7%D8%B1%DB%8C-%D8%AF%D8%B1-%D8%A7%D8%B3-%DA%A9%DB%8C%D9%88-%D8%A7%D9%84-delete-duplicate-rows-in-sql-server-ze3pb22lkj1h</link>
                <description>فرض کنید در جدولی رکوردهایی شبیه به هم ایجاد شده و باعث کندی در سیستم شده مخصوصا جداول پایه سیستم که تعداد کوئری روی اون زیاده و در حجم توکن و کوکی هم تاثیر میزاره.مثلا جدول AspNetRoleClaims که میگه هر role به چه اکشنهایی دسترسی داره. ستونهای جدول AspNetRoleClaims : Id, ClaimType, ClaimValue, RoleIdکه ClaimType اسم controller و ClaimValue اسم action هست و هر رکورد میگه که این رل به این controller و این action دسترسی داره.اگه رکوردهایی تکراری داشته باشیم یعنی با Id های متفاوت ولی ClaimType, ClaimValue, RoleId های یکسان. چه جوری رکوردهای تکراری رو حذف کنیم؟اولا برای اینکه بدونیم رکورد تکراری داریم یا نه میشه جواب این دو select رو با هم مقایسه کرد:select ClaimType,ClaimValue,RoleId from AspNetRoleClaims
select distinct ClaimType,ClaimValue,RoleId from AspNetRoleClaimsکه فرقشون در distinct هست ، اگر این سه فیلد ClaimType, ClaimValue, RoleId تکرار شده باشن تعداد جواب این دو سلکت متفاوت هست یعنی رکورد تکراری داریم و اگر تعداد جواب این دو سلکت مساوی بود یعنی رکورد تکراری نداریم.حالا اگر رکورد تکراری داشتیم چه کار کنیم؟یه راه حل ساده اینه که با ROW_NUMBER تعداد هر رکورد رو مشخص کنیم و بریزیم در یک temp table :SELECT Id, ClaimType, ClaimValue, RoleId, ROW_NUMBER() OVER (
PARTITION BY ClaimType,ClaimValue,RoleId
ORDER BY ClaimType,ClaimValue,RoleId) row_num
into #temp
FROM AspNetRoleClaimsدقت کنید که در جلوی PARTITION BY ستون Id رو نمیاریم چون Id کلید اصلی جدول هست و unique هست و اگر بیاد نتیجه select میشه : همه رکوردها 1 بار تکرار شدن. پس محتوای temp# میشه همه رکوردها و همه ستونها به علاوه ستون row_num که میگه این رکورد چند بار در این جدول اومده.خب حالا کافیه رکوردهایی از جدول AspNetRoleClaims رو delete کنیم که در temp# ستون row_num شون بیشتر از 1 هست ، ارتباط رکوردهای این دو جدول هم از طریق Id انجام میدیم.پس با این delete رکوردهای تکراری AspNetRoleClaims رو حذف میکنیم:delete AspNetRoleClaims where Id in(select Id from #temp where row_num&gt;1)در نهایت هم temp# رو drop میکنیم :drop table #temp</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Sat, 11 Sep 2021 12:29:02 +0430</pubDate>
            </item>
                    <item>
                <title>هندل کردن عمومی ارور 400 در برنامه وب ای پی آی دات نت کور -  net core web api global BadRequest (400) handling</title>
                <link>https://virgool.io/@komaei/%D9%87%D9%86%D8%AF%D9%84-%DA%A9%D8%B1%D8%AF%D9%86-%D8%B9%D9%85%D9%88%D9%85%DB%8C-%D8%A7%D8%B1%D9%88%D8%B1-400-%D8%AF%D8%B1-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%88%D8%A8-%D8%A7%DB%8C-%D9%BE%DB%8C-%D8%A2%DB%8C-%D8%AF%D8%A7%D8%AA-%D9%86%D8%AA-%DA%A9%D9%88%D8%B1-net-core-web-api-global-badrequest-400-handling-bliu3s57ydgq</link>
                <description>اگر کار ولیدیشن فیلدهای مدل ورودی رو توسط data annotation ها یا fluent validation انجام بدین و کاربر فیلدی رو درست پر نکنه ModelState معتبر یا Valid نیست. اروری که در swagger میگیرید به این شکل هست :Error 400 Response headers  date: Thu19 Aug 2021 13:45:08 GMT   server: Kestrel   www-authenticate: Bearerکه هم خروجی مناسبی برای برنامه SPA مون نیست ، هم اینکه در همه اکشن متدها باید if(ModelState.IsValid) رو بنویسیم. حالا روشی رو بهتون میگم که هر دو مشکل رو حل میکنه. اول اینکه در کلاس startup.cs تون کد نزنید و service یا config ای که مینویسن رو در یک کلاس دیگر بنویسید و در استارت آپ فقط صداش کنید.برای این کار یعنی مدیریت ارورهای بد رکوئست یا همون ارور 400 یه فولدر در پروژه web api تون اضافه کنید به نام ioc یا config و کلاسهای این چنینی رو در اون اضافه کنید و در استارت آپ کالشون کنید.دیگه کدها رو نمیگم D:چرا میگم ولی لینک stackoverflow  اش رو میدم که اگه دوست داشتین یه لایک هم اونجا بهم بدین :https://stackoverflow.com/a/68863235/9875486خیلی سرچ کردم و کسی به این خوبی جواب نداده در اینترنت.خروجی ارور 400 تون شبیه این میشه:{
  &amp;quotstatusCode&amp;quot: 400,
  &amp;quotmessage&amp;quot: &amp;quotشماره موبایل معتبر نیست - کد اعتبارسنجی معتبر نیست&amp;quot
}</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Fri, 20 Aug 2021 18:40:14 +0430</pubDate>
            </item>
                    <item>
                <title>اکستنشن ویژوال استودیو  Ef Core Power Tools  - ارور Data is Null. This method or property cannot be called on Null values</title>
                <link>https://virgool.io/@komaei/%D8%A7%DA%A9%D8%B3%D8%AA%D9%86%D8%B4%D9%86-%D9%88%DB%8C%DA%98%D9%88%D8%A7%D9%84-%D8%A7%D8%B3%D8%AA%D9%88%D8%AF%DB%8C%D9%88-ef-core-power-tools-%D8%A7%D8%B1%D9%88%D8%B1-data-is-null-this-method-or-property-cannot-be-called-on-null-values-ftehayc2htny</link>
                <description>اگر پروژه تون از نوع data first بود و با ef کوئری روی جدولی زدین و این ارور رو گرفتین :Data is Null. This method or property cannot be called on Null values.علت این هست که 1. فیلدی در جدول دیتابیس دارین که allow null هست ولی در کلاس انتیتی سمت سی شارپ Required هست.2. مقدار این ستون دیتابیس هست NULL هست.من در data first برای ایجاد DbContext و کلاسهای poco یا همون Entity ها از اکستنشن ویژوال استودیو ef core power tools استفاده میکنم. برای نصب در Visual Studio منوی Extensions را باز کنید و Manage Extensions رو انتخاب کنید. از سمت چپ روی Online کلیک کنید و از سمت راست ef core power tools رو سرچ کنید و دکمه Download اش رو بزنید. بعد از نصب نیازه که یک بار vs رو ببندید و صبر کنید تا نصب بشه.EF Core Power Toolsبعد از نصب کافیه روی پروژه وب (mvc core  یا web api core یا Razor Pages) راست کلیک کنید و از منوی Ef Core Power Tools گزینه Reverse Engineer رو انتخاب کنید تا DbContext و مدل دوباره ساخته بشه و کد با دیتابیس sync بشه و این ارور بر طرف بشه.بهتره در پروژه یک فولدر به نام Data بسازید برای ساختن فایل AppDbContext.cs در اون و داخل فولدر Data یه فولدر به نام Entities برای ساختن فایل های poco یا همون موجودیت که معادل جداول دیتابیس.این اکستنشن موقع اینکار یعنی کار scaffold از دیتابیس به برنامه تنظیماتی هم داره که سیو هم میشه در پروژه تون و هر بار نمیخواد تنظیماتش رو انجام بدین. مثلا اسم کلاس DbContext رو میتونید بدین بهش ، محل ساخت فایلهای مدل poco و محل ساخت فایل DbContext رو میتونید بدین مثلا : Data یا Data/Entities ، همچنین اینکه اسم مدلها رو مفرد بسازه یا به صورت جمع. البته این نکته رو مد نظر داشته باشین با توجه به این که هر بار عمل اسکفولد انجام میدین فایلها پاک میشن و دوباره ساخته میشه ، کدهایی که میتونید در AppDbContext نزارید رو نزارید که مجبور نشید هر بار اونارو بعد از ایجاد فایل جدید AppDbContext دوباره بنویسید. مثلا کانکشن استرینگ رو در فایل Program.cs که UseSqlServer میکنید پاس بدین.اصلا هم سمت لایه Repository نرید چون خود کلاس DbContext ای اف کور که ما ازش ارث بری کردیم هر DbSet اش یک ریپازیتوری هست و برای 1 جدول هم Unit Of Work هست. تنها کافیه یک فولدر برای لایه Service بسازید (لایه ها رو با فولدر بسازید کارتون خیلی راحت میشه و ارور خیلی کمتری میگیرید) و داخلش interface ها و class های عملیاتی و بیزینسی سیستم تون رو بنویسید و به کانستراکتور کلاس ها مثلا ProductService  تون AppDbContext رو inject کنید و عملیات دیتابیسی تون رو بنویسید. این interface ها و class ها رو در program.cs اینجکت کنید با AddScpoed و در کانستراکتور controller ها یا صفحات razor page اینجکت کنید و از متدهای سرویس ها استفاده کنید.به دنبال ارث بری کلاسهای سرویس هم نباشید چون ارث بری یعنی اینکه یک سری متد مثل GetAll , GetById , Remove , Update رو به همه کلاسهای service بخورونید در حالیکه خیلی از انتیتی های یک سیستم مثلا Remove ندارن. هر متدی نیاز بود بنویسید که به لطف ef core عملیات دیتابیسی خیلی راحت شده.برای توضیحات بیشتر عدم استفاده از لایه ریپازیتوری این لینک رو مطالعه کنید:https://www.dntips.ir/post/841/ef-code-first-11هدف uow این است که تعداد ساخت آبجکت از dbcontext رو در یک ریکوئست 1 دونه نگه داره تا عملیات کراد روی انتیتی های مختلف ترنزکشنال انجام بشه. آبجکت dbcontext خودش uow هم هست و اگر دو تا insert در 1 جدول یا 2 جدول مختلف انجام بدین اگر اینسرت اولی انجام بشه ولی دومی نشه کل عملیات rollback میشه پس اگه خواستین یه همچین کاری کنید که ترنزکشنال اجرا بشه هر دو عملیات رو در 1 متد سرویس و با 1 دی بی کانتکس انجام بدین و SaveChanges کنید.</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Wed, 18 Aug 2021 20:16:13 +0430</pubDate>
            </item>
                    <item>
                <title>گرفتن آی پی آدرس در برنامه های وب دات نت کور - Ip addres in .net core</title>
                <link>https://virgool.io/@komaei/%DA%AF%D8%B1%D9%81%D8%AA%D9%86-%D8%A2%DB%8C-%D9%BE%DB%8C-%D8%A2%D8%AF%D8%B1%D8%B3-%D8%AF%D8%B1-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%87%D8%A7%DB%8C-%D9%88%D8%A8-%D8%AF%D8%A7%D8%AA-%D9%86%D8%AA-%DA%A9%D9%88%D8%B1-ip-addres-in-net-core-hzmbsvvcg2od</link>
                <description>برای بدست آوردن آی پی آدرس در در برنامه های وب دات نت کور کافی است در کنترلر خود از این خط استفاده نمائید :string ipAddress = HttpContext.Connection.RemoteIpAddress?.ToString();البته اگر نیاز باشه در تمامی اکشن متد های خود ip رو بدست بیارید راه حل اینه که یک ActionFilter بنویسید و در آن ip رو بدست بیارین و اکشن فیلتر مورد نظر رو در کل پروژه inject کنید.</description>
                <category>محمد کمائی - Telegram : @komayi</category>
                <author>محمد کمائی - Telegram : @komayi</author>
                <pubDate>Tue, 17 Aug 2021 20:41:15 +0430</pubDate>
            </item>
            </channel>
</rss>