‫۶ سال و ۷ ماه قبل، دوشنبه ۳۰ بهمن ۱۳۹۶، ساعت ۱۲:۲۶
یک نکته‌ی تکمیلی: بهبود جزئی جداکننده‌های ارقام در C# 7.2

در C# 7.2، جهت بهبود خوانایی، جداکننده‌ی ارقام را درست پس از پیشوندهای 0b و 0x نیز می‌توان قرار داد:
class Class‍CS72
{
   const int intLiteral = 100_000;
   const int binaryLiteral = 0b_0101_0101;
   const int hexLiteral = 0x_FF_FF;
}
‫۶ سال و ۷ ماه قبل، شنبه ۲۸ بهمن ۱۳۹۶، ساعت ۱۷:۴۸
فیلتر Authorize هم در ASP.NET Core هدرهای مربوط به کش کردن را بازنویسی و تنظیم می‌کند. به عبارتی صفحه‌ای که از این فیلتر رد شود، فقط دارای "CacheControl = "no-cache خواهد بود (تا به اشتباه اینگونه صفحات دارای سطح دسترسی، کش نشوند؛ موردی که در نگارش قبلی ASP.NET MVC به صورت توکار بررسی نمی‌شد).
‫۶ سال و ۷ ماه قبل، جمعه ۲۷ بهمن ۱۳۹۶، ساعت ۲۲:۳۶
- اگر در صفحه anti forgery token داشته باشید (یعنی تنظیم پیش‌فرض تمام فرم‌های ASP.NET Core)، این هدر cache-control را بازنویسی می‌کند؛ در جهت کش نشدن آن صفحه. اطلاعات بیشتر
- یعنی نیازی به استفاده از فیلتر NoBrowserCache فوق در برنامه‌های ASP.NET Core نیست و این مورد، تنظیم پیش‌فرض تمام صفحات دارای فرم آن است.
‫۶ سال و ۷ ماه قبل، جمعه ۲۷ بهمن ۱۳۹۶، ساعت ۱۷:۵۵
- چرا قسمت cache-control را کامل نکردید؟ دقیقا به همان صورتیکه عنوان شده

- برای اینکه مشاهده کنید این فیلتر کار می‌کند یا نه، باید به برگه‌ی network مرورگر مراجعه کنید و status code نمایش مجدد صفحه را مشاهده کنید:

اثر دکمه‌ی back برای صفحه‌ی لاگینی که کش مرورگر آن توسط فیلتر فوق غیرفعال شده (دریافت مجدد از سرور؛ بجای خوانده شدن از کش مرورگر).

اثر دکمه‌ی back برای یک صفحه‌ی معمولی (از کش مرورگر خوانده شده؛ بجای دریافت مجدد از سرور).

- ضمن اینکه تعریف این فیلتر صرفا برای صفحه‌ی login توصیه می‌شود و نه جای دیگری و نه کل سایت. گیرم شخصی با دکمه‌ی back، محتوای کش شده‌ی قبلی را مشاهده کند. مهم نیست. چون بلافاصله با ارسال یک درخواست جدید، فیلتر Authorize، دسترسی او را سد می‌کند. صفحه‌ی کش شده هم بر اساس دسترسی پیشین او در کش مرورگر وجود دارد. مشاهده‌ی آن صفحه‌ی قدیمی اهمیتی ندارد؛ چون اطلاعات بعدی به روز شده را باید با گذشت از فیلتر Authorize دریافت کند.

‫۶ سال و ۷ ماه قبل، جمعه ۲۷ بهمن ۱۳۹۶، ساعت ۰۴:۳۷
معادل این مطلب برای ASP.NET Core

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;

namespace ASPNETCoreIdentitySample.Common.WebToolkit
{
    public class NoBrowserCacheAttribute : ActionFilterAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            filterContext.HttpContext.DisableBrowserCache();
            base.OnResultExecuting(filterContext);
        }
    }

    public static class CacheManager
    {
        public static void DisableBrowserCache(this HttpContext httpContext)
        {
            // Note: https://docs.microsoft.com/en-us/aspnet/core/performance/caching/middleware
            // The Antiforgery system for generating secure tokens to prevent Cross-Site Request Forgery (CSRF)
            // attacks sets the Cache-Control and Pragma headers to no-cache so that responses aren't cached.
            // More info:
            // https://github.com/aspnet/Antiforgery/blob/dev/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgery.cs#L381
            // https://github.com/aspnet/Antiforgery/issues/116
            // So ... the following settings won't work for the pages with normal forms with default settings.
            httpContext.Response.Headers[HeaderNames.CacheControl] =
                          new StringValues(new[] { "no-cache", "max-age=0", "must-revalidate", "no-store" });
            httpContext.Response.Headers[HeaderNames.Expires] = "-1";
            httpContext.Response.Headers[HeaderNames.Pragma] = "no-cache";
        }
    }
}
‫۶ سال و ۷ ماه قبل، چهارشنبه ۲۵ بهمن ۱۳۹۶، ساعت ۱۳:۰۹
یک نکته‌ی تکمیلی: اضافه شدن strictPropertyInitialization به TypeScript 2.7

در نگارش 2.7 اگر یک چنین تعریفی را داشته باشید:
export class MovieComponent {

  @Input() movie: Movie;

}
خطای زیر را دریافت خواهید کرد:
Error! Property movie has no initializer and is not assigned directly in the constructor.
یک روش برطرف کردن این خطا، نال‌پذیر تعریف کردن این خاصیت و سپس مقدار دهی اولیه‌ی به آن است:
@Input() movie: Movie | null = null;
و یا در مثال زیر می‌توان مشخص کرد که baz می‌تواند undefined هم باشد:
class C {
    baz: boolean | undefined;
}
روش دیگر، مقدار دهی اولیه، حین تعریف یک خاصیت است:
class C {
    bar = "hello";
}
و یا می‌توان این بررسی را به صورت زیر خاموش کرد:
class C {
    foo!: number;

    ngOnInit() {
        this.foo = 0;
    }
}
با استفاده از عملگر ! به کامپایلر اعلام می‌کنیم که این خاصیت حتما قرار است توسط روشی کمکی مقدار دهی اولیه شود و نال یا بدون مقدار نیست و استفاده‌ی از آن در این کلاس امن است.
در این مورد برای تکمیل پروژه، جهت دریافت تنظیمات کلاینت از سمت سرور

- ابتدا ApiSettingsController.cs  اضافه شد تا تنظیمات ApiSettings را به سمت کلاینت بازگشت دهد.
- سپس
api-config.service.ts جهت خواندن این تنظیمات تعریف و به ماژول Core اضافه شد تا در ابتدای اجرای برنامه‌ی کلاینت، پیش از هر کد دیگری اجرا شود.
- تغییرات مورد نیاز آن‌را در اینجا می‌توانید مشاهده کنید و یا آخرین نگارش پروژه را دریافت کنید.

برای آزمایش آن، اگر برنامه‌ی سرور (در ابتدا؛
جهت مهیا شدن قسمت دریافت تنظیمات سمت سرور ) و سپس کلاینت را اجرا کنید، تنظیمات دریافتی را در کنسول توسعه دهندگان مرورگر، مشاهده خواهید کرد:

به روز رسانی
جهت کاهش مسئولیت‌های کلاس سرویس Auth، دو سرویس جدید token-store.service.ts  (برای ذخیره و بازیابی توکن‌های دریافتی از سرور) و refresh-token.service.ts (مدیریت به روز رسانی خودکار توکن) اضافه و در اصل از auth.service.ts استخراج شدند.