‫۵ سال و ۶ ماه قبل، پنجشنبه ۲۳ اسفند ۱۳۹۷، ساعت ۱۲:۵۲
یک نکته‌ی تکمیلی: تعریف بیشتر از یک role سبب بروز خطا می‌شود
اگر در برنامه آرایه‌ای از claims مانند آرایه‌ای از roles تعریف شود، به خطای زیر برخواهید خورد:
An unhandled exception occurred while processing the request.
InvalidCastException: Cannot cast Newtonsoft.Json.Linq.JArray to Newtonsoft.Json.Linq.JToken.
Newtonsoft.Json.Linq.Extensions.Convert<T, U>(T token)

Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler.HandleRequestAsync
مشکل اینجا است که نگاشت زیر:
options.ClaimActions.MapUniqueJsonKey(claimType: "role", jsonKey: "role");
به همراه واژه‌ی Unique است؛ یعنی یک آرایه را نمی‌پذیرد و به همین جهت است که عنوان می‌کند JArray دریافتی، قابل تبدیل به JToken نیست. برای رفع این مشکل می‌توان از متد زیر استفاده کرد:
options.ClaimActions.MapJsonKey(claimType: "role", jsonKey: "role"); // for having 2 or more roles
‫۵ سال و ۶ ماه قبل، چهارشنبه ۲۲ اسفند ۱۳۹۷، ساعت ۱۵:۲۲
یک نکته‌ی تکمیلی: در نگارش‌های 2.1 به بعد، دیگر سشن‌ها کار نمی‌کنند. چرا؟
به علت فعال شدن GDPR در نگارش 2.1 به بعد، تا زمانیکه کاربر رضایت خود را اعلام نکند، کوکی سشن نوشته نخواهد شد. اگر این مساله بر روی برنامه‌ی شما تاثیر داشته‌است، یا می‌توانید کلا GDPR را غیرفعال کنید و یا کوکی سشن را به صورت اجباری و اساسی علامتگذاری کنید تا همواره تولید شود:
public void ConfigureServices(IServiceCollection services) 
{ 
    services.Configure<CookiePolicyOptions>(options => 
    { 
        options.CheckConsentNeeded = context => true; // consent required 
        options.MinimumSameSitePolicy = SameSiteMode.None; 
    }); 
 
    services.AddSession(opts =>  
    { 
        opts.Cookie.IsEssential = true; // make the session cookie Essential 
    }); 
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); 
}
در این مثال GDPR فعال است ( که البته می‌توان CheckConsentNeeded آن‌را false کرد)، اما کوکی سشن به صورت IsEssential علامتگذاری شده‌است تا همواره نوشته شود.
‫۵ سال و ۶ ماه قبل، چهارشنبه ۲۲ اسفند ۱۳۹۷، ساعت ۱۳:۰۱
غیرممکن هست که در یک دیکشنری کلید تکراری ثبت شود؛ چون استثناء تولید می‌کند و هویت آن به این صورت است. مشکلی که در طراحی فوق دارید، استفاده از StringBuilder به عنوان کلید هست:
var sb1 = new StringBuilder("Food");
var sb2 = new StringBuilder("Food");
Console.WriteLine(sb1 == sb2);
خروجی مقایسه‌ی فوق، false است؛ چون این شیء Equals(object) را پیاده سازی نکرده و روش محاسبه‌ی یکی بودن آن‌ها به این صورت است:
true if this instance and sb have equal string, Capacity, and MaxCapacity values; otherwise, false.
آن‌را تبدیل کنید به رشته، مشکل حل می‌شود. ضمنا هدف از دیکشنری یافتن سریع کلیدها است و عموما از یک رشته‌ی بلند به عنوان کلید استفاده نمی‌شود. از هش کوتاه آن استفاده می‌شود.
‫۵ سال و ۶ ماه قبل، سه‌شنبه ۲۱ اسفند ۱۳۹۷، ساعت ۲۳:۱۲
Lazy را به قسمتی از درون Func اعمال کردید. کل Func باید Lazy شود تا درست کار کند.
using System;
using System.Collections.Concurrent;
using System.Threading;

namespace LazyDic
{
    public class LazyConcurrentDictionary<TKey, TValue>
    {
        private readonly ConcurrentDictionary<TKey, Lazy<TValue>> _concurrentDictionary;
        public LazyConcurrentDictionary()
        {
            _concurrentDictionary = new ConcurrentDictionary<TKey, Lazy<TValue>>();
        }

        public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
        {
            var lazyResult = _concurrentDictionary.GetOrAdd(key,
             k => new Lazy<TValue>(() => valueFactory(k), LazyThreadSafetyMode.ExecutionAndPublication));
            return lazyResult.Value;
        }

        public TValue AddOrUpdate(TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
        {
            var lazyResult = _concurrentDictionary.AddOrUpdate(
                key,
                new Lazy<TValue>(() => addValue),
                (k, currentValue) => new Lazy<TValue>(() => updateValueFactory(k, currentValue.Value),
                                                      LazyThreadSafetyMode.ExecutionAndPublication));
            return lazyResult.Value;
        }

        public TValue AddOrUpdate(TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
        {
            var lazyResult = _concurrentDictionary.AddOrUpdate(
                key,
                k => new Lazy<TValue>(() => addValueFactory(k)),
                (k, currentValue) => new Lazy<TValue>(() => updateValueFactory(k, currentValue.Value),
                                                      LazyThreadSafetyMode.ExecutionAndPublication));
            return lazyResult.Value;
        }

        public int Count => _concurrentDictionary.Count;
    }
}
‫۵ سال و ۶ ماه قبل، سه‌شنبه ۲۱ اسفند ۱۳۹۷، ساعت ۱۴:۵۲
در هر دو مورد، برای سفارشی سازی‌های ویژه‌ی سطوح دسترسی، باید از مفهوم user-claims استفاده کنید؛ جدول ویژه‌ای مخصوص اینکار وجود دارد، به همراه امکان استفاده‌ی پویای از آن. در این حالت نیازی به تغییری در جداول پایه‌ی این سیستم نیست و همچنین زیرساخت آن در اصل با همین user-claims کار می‌کند؛ حتی نقش‌های قدیمی آن هم چیزی بیشتر از یک user-claims از نوع ClaimTypes.Role نیستند.
‫۵ سال و ۶ ماه قبل، دوشنبه ۲۰ اسفند ۱۳۹۷، ساعت ۱۴:۵۹
برای پیاده سازی قفل گذاری در سطح برنامه:
- سمت دیتابیس آن استفاده از تراکنش‌ها و isolation level است و یا مواردی مانند sp_getapplock .
- بهتر است برای پیاده سازی AsyncLock از کتابخانه‌ی « AsyncEx » استفاده کنید، چون نکات زیادی را به همراه دارد. 
- همچنین برای کپسوله سازی آن بهتر است از فیلترها استفاده شود (مثلا یک فیلتر [DisableConcurrentExecution] را بر این اساس ایجاد کنید) تا صرفا یک اکشن متد خاص را تحت کنترل قرار دهند و نه مانند میان‌افزارها که تمام سیستم را داخل lock قرار می‌دهند.