ارتقاء به ASP.NET Core 1.0 - قسمت 15 - بررسی تغییرات Caching
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: نه دقیقه

در نگارش‌های پیشین ASP.NET MVC با استفاده از Output Cache، امکان کش کردن خروجی یک اکشن متد، وجود دارد. مکانیزم Output Cache از ASP.NET Core حذف شده‌است؛ اما جایگزین‌های قابل توجهی برای آن تدارک دیده شده‌اند.


معرفی Response Cache

جایگزین ویژگی حذف شده‌ی OutputCache در ASP.NET Core، ویژگی جدیدی است به نام ResponseCache و هدف آن تنظیم هدرهای مرتبط با caching مخصوص HTTP Response ارائه شده‌است. به همین جهت با مکانیزم OutputCache قدیمی ASP.NET MVC که اطلاعات را در حافظه‌ی سرور کش می‌کرد، کاملا متفاوت است.
البته قرار است میان افزار OutputCache را در نگارش‌های آتی ASP.NET Core نیز ارائه کنند.
[ResponseCache(Duration = 60)]
public IActionResult Contact()
{
   ViewData["Message"] = "Your contact page.";
   return View();
}
در اینجا مثالی را از نحوه‌ی تعریف این ویژگی جدید، ملاحظه می‌کنید که در آن مقدار خاصیت مدت زمان کش شدن، برحسب ثانیه است. استفاده‌ی از آن سبب خواهد شد تا هدر HTTP ذیل به خروجی از سرور اضافه شود:
 Cache-Control: public,max-age=60

یک نکته:
این ویژگی را هم می‌توان به کل کنترلر اعمال کرد و هم به یک اکشن متد خاص. اگر این ویژگی هم به کنترلر و هم به اکشن متدی در آن کنترلر اعمال شده باشد، تنظیمات در سطح متدها، تنظیمات در سطح کلاس را بازنویسی می‌کنند.


تعیین مکان کش شدن خروجی یک اکشن متد

در هدر فوق، عبارت public را مشاهده می‌کنید. این public بودن به این معنا است که امکان کش شدن این خروجی، توسط کش سرورهای اشتراکی بین راه هم وجود دارد.
اگر می‌خواهید این امکان را غیرفعال کنید، نیاز است این public به private تنظیم شود:
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Client)]
تنظیم Location فوق به Client به معنای private شدن هدر تنظیم شده و صرفا کش شدن خروجی، توسط کش مرورگر کاربر می‌باشد.


غیرفعال کردن کش شدن خروجی یک اکشن متد

اگر خواستید از کش شدن خروجی یک اکشن متد تحت هر حالتی جلوگیری کنید، مکان آن‌را به None و NoStore آن‌را به true تنظیم کنید:
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
   return View();
}
این تنظیم سبب افزوده شدن یک چنین هدر HTTP ایی به خروجی از سرور می‌شود:
Cache-Control: no-store,no-cache
Pragma: no-cache


امکان تعریف پروفایل‌های کش

بجای اینکه تنظیمات کش کردن تکراری را به انواع و اقسام اکشن متدها اعمال کنیم، می‌توان برای آن‌ها پروفایل ایجاد کرده و از نام این پروفایل، جهت به اشتراک گذاری تنظیمات استفاده کنیم. برای این منظور به کلاس آغازین برنامه مراجعه کرده و جایی که سرویس ASP.NET MVC را فعال سازی کرده‌اید، پروفایل کش جدیدی را تعریف کنید:
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.CacheProfiles.Add("PrivateCache",
            new CacheProfile
            {
                Duration = 60,
                Location = ResponseCacheLocation.Client
            }); 
    });
پس از آن برای استفاده‌ی از این تنظیمات اشتراکی، فقط کافی است تا نام پروفایل مرتبطی را ذکر کنیم:
[ResponseCache(CacheProfileName = "PrivateCache")]


معرفی سرویس کش درون حافظه‌ای

در نگارش‌های پیشین ASP.NET، متدهایی برای کش کردن موقتی اطلاعات در حافظه و سپس بازیابی آن‌ها وجود داشتند. در ASP.NET Core، این متدها توسط سرویس ارائه کننده‌ی IMemoryCache در اختیار برنامه قرار می‌گیرند. برای فعال سازی این سرویس جدید باید مراحل ذیل طی شوند:
الف) ابتدا بسته‌ی Microsoft.Extensions.Caching.Memory را به لیست وابستگی‌های پروژه در فایل project.json اضافه کنید:
{
    "dependencies": {
      //same as before
      "Microsoft.Extensions.Caching.Memory": "1.0.0"
 },
ب) سپس به کلاس آغازین برنامه مراجعه کرده و سرویس آ‌ن‌را معرفی و ثبت کنید:
public void ConfigureServices(IServiceCollection services)
{
  services.AddMemoryCache();
ج) پس از آن سرویس پیاده سازی کننده‌ی IMemoryCache،  در تمام اجزای برنامه در دسترس خواهد بود. برای مثال:
[Route("DNT/[controller]")]
public class AboutController : Controller
{
    private readonly IMemoryCache _memoryCache;
 
    public AboutController(IMemoryCache memoryCache)
    {
        _memoryCache = memoryCache;
    }
 
    [Route("")]
    public ActionResult Hello()
    {
 
        string cacheKey = "my-cache-key";
        string greeting;
 
        if (!_memoryCache.TryGetValue(cacheKey, out greeting))
        {
             greeting = "Hello";
            // store in the cache
            _memoryCache.Set(cacheKey, greeting,
                new MemoryCacheEntryOptions()
                .SetAbsoluteExpiration(TimeSpan.FromMinutes(1)));
        }
 
        return Content($"{greeting} from DNT!");
    }
در مثال فوق، ابتدا وابستگی سرویس کش درون حافظه‌ای، به سازنده‌ی کنترلر تزریق شده‌است. تامین آن هم توسط سرویسی که در کلاس آغازین برنامه ثبت کردیم، انجام می‌شود. پس از آن در اکشن متد Hello، سعی کرده‌ایم بر اساس کلید کشی که مشخص کرده‌ایم، مقداری را بازیابی کنیم. اگر این مقدار وجود نداشته باشد، آن‌را توسط متد Set تنظیم خواهیم کرد تا برای دفعات آتی فراخوانی این متد، مورد استفاده قرار گیرد.
تنظیمات منقضی شدن کش نیز به حالت absolute تنظیم شده‌است. یعنی پس از یک دقیقه حتما منقضی می‌شود. اگر فراخوانی‌های این متد زیاد است، می‌توان حالت منقضی شدن sliding را تنظیم کرد:
 new MemoryCacheEntryOptions()
  .SetSlidingExpiration(TimeSpan.FromMinutes(5))
در این حالت اگر پیش از اتمام 5 دقیقه‌ی تنظیم شده، درخواستی به سرور رسید، این کش برای 5 دقیقه‌ی بعد نیز مجددا تمدید می‌شود.
اگر خواستیم تا این کش سر ساعت منقضی شود، اما در طی این یک ساعت به صورت sliding عمل کند، می‌توان از ترکیب دو حالت مطلق و لغزشی استفاده کرد:
 new MemoryCacheEntryOptions()
  .SetSlidingExpiration(TimeSpan.FromMinutes(5))
  .SetAbsoluteExpiration(TimeSpan.FromHours(1))

یک نکته: اگر فشار حافظه‌ی سرور زیاد شود، مدیر حافظه‌ی این کش، شروع به منقضی کردن آیتم‌هایی با حق تقدم پایین می‌کند. بالاترین حق تقدم را حالت NeverRemove ذیل دارد:
 new MemoryCacheEntryOptions()
  .SetPriority(CacheItemPriority.NeverRemove))


معرفی Tag Helpers مخصوص کش کردن قسمتی از صفحه

در ادامه‌ی مبحث معرفی Tag Helpers، تعدادی از آن‌ها جهت کش کردن محتوای قسمتی از صفحه، طراحی شده‌اند:
<cache expires-after="@TimeSpan.FromMinutes(10)">
    @Html.Partial("_WhatsNew")
    *last updated  @DateTime.Now.ToLongTimeString()
</cache>
تگ جدید cache محتوای دربرگیرنده‌ی آن‌را «در حافظه‌ی سرور» کش می‌کند (و در پشت صحنه از همان کش درون حافظه‌ای که پیشتر بحث شد، استفاده می‌کند). تگ cache در خروجی HTML نهایی مشاهده نمی‌شود و صرفا مفهومی سمت سرور است.
برای نمونه در مثال فوق، محتوای پارشال ویوو رندر شده و همچنین تاریخی که پس از آن نمایش داده شده‌است، به مدت 10 دقیقه در حافظه‌ی سرور کش می‌شوند. اگر این زمان تنظیم نشود، تا زمانیکه برنامه در سرور مشغول به کار است، این قسمت منقضی نخواهد شد.
در اینجا اگر expires-after ذکر شده بود، یعنی پس از این مدت زمان، کش منقضی می‌شود.
<cache expires-after="@TimeSpan.FromSeconds(5)">
    <!--View Component or something that gets data from the database-->
    *last updated  @DateTime.Now.ToLongTimeString()
</cache>
 اگر expires-on آن ذکر شود، می‌توان تاریخ و زمان مشخصی را در اینجا ذکر کرد (برای مثال فردا ساعت 10، با فراخوانی DateTime.Today.AddDays).
<cache expires-on="@DateTime.Today.AddDays(1).AddTicks(-1)">
  <!--View Component or something that gets data from the database-->
 *last updated  @DateTime.Now.ToLongTimeString()
</cache>
همچنین می‌توان از expires-sliding نیز استفاده کرد. به این معنا که اگر در طی مدتی خاص این صفحه درخواست نشد، آنگاه این کشی منقضی می‌شود.
<cache expires-sliding="@TimeSpan.FromMinutes(5)">
    <!--View Component or something that gets data from the database-->
    *last updated  @DateTime.Now.ToLongTimeString()
</cache>
همچنین در اینجا می‌توان کش کردن را به ازای کاربران مختلف، کوئری استرینگ‌های مختلف و امثال آن انجام داد (با ارائه‌ی محتوای متفاوتی به ازای پارامترهای مختلف):
<cache vary-by-user="true">
    <!--View Component or something that gets data from the database-->
    *last updated @DateTime.Now.ToLongTimeString()
</cache>
در این حالت دیگر نیازی نیست تا نگران این باشیم که آیا محتوای قسمت کش شده‌ی از صفحه برای تمام کاربران در دسترس است یا خیر؟ در اینجا هر کاربر لاگین شده‌ی به سیستم، نگارش کش شده‌ی خاص خودش را دریافت می‌کند.

<cache vary-by-route="id">
    <!--View Component or something that gets data from the database-->
    *last updated  @DateTime.Now.ToLongTimeString()
</cache>
در اینجا به ازای پارامتر آی‌دی مسیریابی، نگارش‌های مختلف کش شده‌ای از صفحه تامین می‌شوند. در اینجا می‌توان لیستی از پارامترهای جدا شده‌ی با کاما را مشخص کرد.

<cache vary-by-query="search">
    <!--View Component or something that gets data from the database-->
    *last updated  @DateTime.Now.ToLongTimeString()
</cache>
امکان کش کردن محتوای صفحه به ازای کوئری استرینگ‌های مختلف تنظیم شده نیز وجود دارد.

<cache vary-by-cookie="MyAppCookie">
    <!--View Component or something that gets data from the database-->
    *last updated  @DateTime.Now.ToLongTimeString()
</cache>
در اینجا به ازای محتواهای مختلف کوکی خاصی به نام MyAppCookie، نگارش‌های مختلف کش شده‌ای از صفحه ذخیره می‌شوند.

 <cache vary-by-header="User-Agent">
    <!--View Component or something that gets data from the database-->
    *last updated  @DateTime.Now.ToLongTimeString()
</cache>
در اینجا می‌توان به ازای هدرهای مختلف پروتکل HTTP نگارش‌های کش شده‌ی متفاوتی را ارائه داد.

<cache vary-by="@ViewBag.ProductId">
    <!--View Component or something that gets data from the database-->
    *last updated  @DateTime.Now.ToLongTimeString()
</cache>
اگر خواستید کلید کش را خودتان تعیین کنید از vary-by استفاده کنید.

 <cache vary-by-user="true" vary-by-route="id">
    <!--View Component or something that gets data from the database-->
    *last updated  @DateTime.Now.ToLongTimeString()
</cache>
امکان ترکیب این موارد با هم نیز وجود دارد.

به علاوه چون زیر ساخت این Tag Helper همان Microsoft.Extensions.Caching.Memory است، امکان تنظیم حق تقدم حذف شدن آیتم‌های کش شده نیز وجود دارد:
<cache expires-sliding="@TimeSpan.FromMinutes(10)"
priority="@Microsoft.Extensions.Caching.Memory.CacheItemPriority.NeverRemove">
    <!--View Component or something that gets data from the database-->
    *last updated  @DateTime.Now.ToLongTimeString()
</cache>


مبحث تکمیلی

امکان ذخیره سازی آیتم‌های کش شده در بانک اطلاعاتی (بجای حافظه‌ی فرار) نیز پیش بینی شده‌است که تحت عنوان «کش توزیع شده» در دسترس است.
Working with a Distributed Cache
  • #
    ‫۸ سال و ۱ ماه قبل، پنجشنبه ۱۴ مرداد ۱۳۹۵، ساعت ۲۳:۵۰
    نکته‌ای در مورد کش کردن فایل‌های استاتیک در ASP.NET Core
    تمام مطالب فوق در مورد کش کردن خروجی اطلاعات پویا هستند. در مورد فایل‌های ایستا می‌توان از میان افزار static files به نحو ذیل استفاده کرد:
    app.UseStaticFiles(new StaticFileOptions() 
    { 
        OnPrepareResponse = context => 
        { 
            context.Context.Response.Headers["Cache-Control"] =  
                    "private, max-age=43200"; 
     
            context.Context.Response.Headers["Expires"] =  
                    DateTime.UtcNow.AddHours(12).ToString("R"); 
        } 
    });
    در اینجا نحوه‌ی افزودن هدرهای مخصوص caching را به فایل‌های استاتیک ارائه‌ی شده‌ی توسط برنامه به کمک StaticFileResponseContext مشاهده می‌کنید.
    • #
      ‫۸ سال و ۱ ماه قبل، پنجشنبه ۲۱ مرداد ۱۳۹۵، ساعت ۰۹:۳۶
      سلام؛ اگر وب سرور مطمئنا iis باشه از تگ staticContent در وب کنفیگ میشه فایلهای استاتیک رو کش کرد؟ یا اینکه به دلیل عدم وابستگی  به iis  دیگه روش قدیم تاثیری برای کش کردن نداره؟
      • #
        ‫۸ سال و ۱ ماه قبل، پنجشنبه ۲۱ مرداد ۱۳۹۵، ساعت ۱۳:۱۵
        IIS و تمام مداخل آن، در اینجا هم معتبر هستند. کاری که مدخل static content انجام می‌دهد:
        <staticContent>
           <clientCache httpExpires="Sun, 29 Mar 2020 00:00:00 GMT" cacheControlMode="UseExpires" />
        </staticContent>
        با نکته‌ی عنوان شده یکی هست (هر دو یک سری هدر را به Response نهایی اضافه می‌کنند).
  • #
    ‫۷ سال و ۶ ماه قبل، دوشنبه ۷ فروردین ۱۳۹۶، ساعت ۰۰:۳۳
    به روز رسانی
    با حذف فایل project.json در VS 2017، اکنون با کلیک راست بر روی گروه نام پروژه (فایل csproj)، گزینه‌ی Edit آن ظاهر شده و مداخل ذکر شده‌ی در مطلب فوق، چنین تعاریفی را پیدا می‌کنند: 
    <Project Sdk="Microsoft.NET.Sdk.Web">
      <ItemGroup>
        <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="1.0.0" />
      </ItemGroup>
    </Project>
  • #
    ‫۶ سال و ۷ ماه قبل، جمعه ۲۷ بهمن ۱۳۹۶، ساعت ۰۲:۳۰
    آیا این ویژگی شامل دکمه Back مرورگر هم میشود؟
    یعنی کاربر لاگین میکند، در صفحه هوم با استفاده از دکمه لاگ اوت خارج میشود و بعد روی دکمه بک مرورگر کلیک میکند.
    چه اتفاقی می‌افتد؟ کاربر صفحه هوم را میبیند؟ یا چون لاگ اوت کرده باید اول لاگین کنه؟
    بروی متد صفحه هوم ویژگی ResponseCache برابر با ResponseCacheLocation.None و NoStore = true تنظیم شده است.
    اگر این ویژگی برای (دکمه Back مرورگر)  نیست لطفا راهنماییم کنید که چطور میتونم این کار را انجام دهم
    ASP.Net Core 2.0
    و در این لینک هم گفته شده که این ویژگی در نسخه 2.0 فعال نیست و در 2.1 فعال میشود. (ابتدای صفحه)
    https://docs.microsoft.com/en-us/aspnet/core/performance/caching/response  
      • #
        ‫۶ سال و ۷ ماه قبل، جمعه ۲۷ بهمن ۱۳۹۶، ساعت ۱۷:۴۳
        معادل این مطلب برای ASP.NET Core
        دقیقا مثال بالا را پیاده سازی کردم.
        هم بصورت [NoBrowserCache]  و هم بصورت کلی
        services.AddMvc(options =>
        {
            options.Filters.Add(typeof(NoBrowserCacheAttribute));
        });
        در دو حالت هم مقادیر ست میشن

        ولی در عمل کار نمیکنه
        با هر بار خروج از سیستم از هر صفحه ای، با زدن دکمه بک به همون صفحه برمیگرده
        • #
          ‫۶ سال و ۷ ماه قبل، جمعه ۲۷ بهمن ۱۳۹۶، ساعت ۱۷:۵۵
          - چرا قسمت cache-control را کامل نکردید؟ دقیقا به همان صورتیکه عنوان شده

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

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

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

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

          • #
            ‫۶ سال و ۷ ماه قبل، جمعه ۲۷ بهمن ۱۳۹۶، ساعت ۱۸:۳۹

            توی متد DisableBrowserCache به همون صورت هست که گفتید، ولی در خروجی فقط مقدار "no-cache" نمایش داده میشه. مقدار Expires رو هم تغییر دادم ولی باز در خروجی -1 نمایش داده شد. هر بار هم متد DisableBrowserCache اجرا میشه.  مقدار Order فیلتر رو بصورت منفی هم تنظیم کردم ولی فایده ای نداشت. داره از جای دیگه تنظیم میشه. بیس پروژه هم DNTIdentity هست.

            • #
              ‫۶ سال و ۷ ماه قبل، جمعه ۲۷ بهمن ۱۳۹۶، ساعت ۲۲:۳۶
              - اگر در صفحه anti forgery token داشته باشید (یعنی تنظیم پیش‌فرض تمام فرم‌های ASP.NET Core)، این هدر cache-control را بازنویسی می‌کند؛ در جهت کش نشدن آن صفحه. اطلاعات بیشتر
              - یعنی نیازی به استفاده از فیلتر NoBrowserCache فوق در برنامه‌های ASP.NET Core نیست و این مورد، تنظیم پیش‌فرض تمام صفحات دارای فرم آن است.
            • #
              ‫۶ سال و ۷ ماه قبل، شنبه ۲۸ بهمن ۱۳۹۶، ساعت ۱۷:۴۸
              فیلتر Authorize هم در ASP.NET Core هدرهای مربوط به کش کردن را بازنویسی و تنظیم می‌کند. به عبارتی صفحه‌ای که از این فیلتر رد شود، فقط دارای "CacheControl = "no-cache خواهد بود (تا به اشتباه اینگونه صفحات دارای سطح دسترسی، کش نشوند؛ موردی که در نگارش قبلی ASP.NET MVC به صورت توکار بررسی نمی‌شد).
          • #
            ‫۶ سال و ۶ ماه قبل، چهارشنبه ۱۶ اسفند ۱۳۹۶، ساعت ۱۸:۰۶
            عملیات cashing رو در کل سیستم غیر فعال کردم با این تنظیمات 


            ولی در آخر قسمت cache-control ناقص اعمال میشه ؟


            • #
              ‫۶ سال و ۶ ماه قبل، چهارشنبه ۱۶ اسفند ۱۳۹۶، ساعت ۱۸:۳۴
              این همان معنای «بازنویسی» هست که کمی بالاتر توضیح دادم.
  • #
    ‫۶ سال و ۵ ماه قبل، چهارشنبه ۲۹ فروردین ۱۳۹۷، ساعت ۱۸:۳۱
    کپسوله سازی امکانات این مطلب در ICacheService

    ابتدا بسته‌ی نیوگت DNTCommon.Web.Core را نصب کنید:
    PM> Install-Package DNTCommon.Web.Core
    سپس مثالی از ICacheService آن‌را در اینجا می‌توانید مشاهده کنید.   
    • #
      ‫۶ سال و ۲ ماه قبل، سه‌شنبه ۲۶ تیر ۱۳۹۷، ساعت ۱۶:۱۷
      با تشکر؛ 
      آیا الزامی برای این نوع کپسوله سازی وجود دارد؟ در واقع با داشتن انتزاعی برروی کتابخانه Microsoft.Extensions.Caching.Abstraction به این شکل، تنها با یک واسط ICacheService چه چیز اضافی را بدست خواهیم آورد؟ حال اگر تعویض پذیر بودن مد نظر می‌باشد، در صورت نیاز به دو نسخه توزیع شده و درون حافظه ای به صورت یکجا، داشتن یک واسط جوابگو نخواهد بود مگر با استفاده از الگوی Abstract Factory  یا امکانات پیشرفته IoC Container‌های ثالث برای تعیین این مورد که برای یک واسط یکتا، کدام نوع کش را وهله سازی کند. 
      آیا داشتن دو واسط متمایز به عنوان مثال ICacheService و IDistributedCacheService هم کار اضافی نمی‌باشد؟ 
      با توجه به اینکه در توضیحات مخزن گیت این مجموعه اشاره شده است به کپسوله سازی امکانات IMemoryCache، که در این صورت  برای استفاده از کتابخانه Microsoft.Extensions.Logging هم نیاز به انتزاعی جدید خواهد بود و همچنین سایر کتابخانه ها. یا اگر نکته مربوط به متد GetOrAdd و داشتن یکسری متد جدید مدنظر بود؛ می‌توان با یکسری متد الحاقی هم به این اهداف رسید.
  • #
    ‫۶ سال و ۴ ماه قبل، پنجشنبه ۶ اردیبهشت ۱۳۹۷، ساعت ۱۷:۲۰
    یک نکته‌ی تکمیلی: نحوه‌ی تنظیم زمان در متدهای Set

    IMemoryCache به همراه یک سری متد الحاقی Set دار است. در اینجا متدهایی که DateTimeOffset را می‌پذیرند، با مقدار DateTimeOffset.UtcNow مقایسه خواهند شد.
  • #
    ‫۵ سال و ۱ ماه قبل، چهارشنبه ۱۶ مرداد ۱۳۹۸، ساعت ۱۶:۱۷
    سلام؛ من در صفحه جزئیات محصول، یک فایل css دارم که اونو از دیتابیس پر می‌کنم و برای یک محصول بصورت جدا از دیتابیس بصورت زیر پر میشود:
    @section content{
    
        <link href=@Url.RouteUrl(new { controller="Home", action="GetCss" ,styles=Model.CssBody}) rel="stylesheet" type="text/css" />
    }
    زمانیکه از کش استاتیک استفاده کنم و بخواهم زمان رو مثلا 6 ماه کش در نظر بگیرم، آیا این فایل css را که در صفحه جزییات هم پر میشود، در کش در نظر می‌گیرد؟
  • #
    ‫۵ سال و ۱ ماه قبل، جمعه ۱۸ مرداد ۱۳۹۸، ساعت ۰۱:۳۸
    اگر تنظیمات UseStaticFiles را برای کش شدن فایل‌های استاتیک فرضا 5 روز در نظر بگیریم و در این مدت عکسهایی رو به wwwroot اضافه کنیم، آیا این عکسها هم کش می‌شوند، یا باید مدت زمان کش منقضی شود تا عکسهای جدید هم در مرورگر کاربر کش شوند؟
    • #
      ‫۵ سال و ۱ ماه قبل، جمعه ۱۸ مرداد ۱۳۹۸، ساعت ۰۲:۵۲
      این هدرها به هر فایلی که توسط مرورگر درخواست شود و از کش خوانده نشود، اضافه می‌شود.
  • #
    ‫۴ سال و ۱۱ ماه قبل، سه‌شنبه ۲ مهر ۱۳۹۸، ساعت ۲۳:۴۰
    یک نکته‌ی تکمیلی: MemoryCache در ASP.NET Core 3.0

    از نگارش 2.0، به تنظیمات MemoryCache خاصیت SizeLimit اضافه شده‌است تا اگر به این حد رسید، شروع به حذف کردن آیتم‌های موجود کند:
    public class MyMemoryCache 
    {
        public MemoryCache Cache { get; set; }
        public MyMemoryCache()
        {
            Cache = new MemoryCache(new MemoryCacheOptions
            {
                SizeLimit = 1024
            });
        }
    }
    تنظیم این خاصیت در ASP.NET Core 3.0 در هر جائیکه که وجود داشته، انجام شده. در این حالت اگر برنامه‌ی قدیمی خود را اجرا کنید، یک چنین استثنایی را دریافت خواهید کرد:
    Exception: Cache entry must specify a value for Size when SizeLimit is set.
    at Microsoft.Extensions.Caching.Memory.MemoryCache.SetEntry(CacheEntry entry)
    راه حل آن، یافتن تمام MemoryCacheEntryOptions‌ها در کل برنامه و تمام وابستگی‌های آن (یافتن تمام متدهای cache.Set و تنظیم پارامتر سوم آن) و سپس افزودن خاصیت Size =1 به آن است. در این حالت واحد به 1 تنظیم می‌شود. یعنی SizeLimit به تعداد آیتم موجود در کش، تفسیر خواهد شد. روش دیگر تنظیم آن، استفاده از متد الحاقی SetSize است:
     var cacheEntryOptions = new MemoryCacheEntryOptions()
                    .SetSize(1)
                    .SetSlidingExpiration(TimeSpan.FromSeconds(3));
    • #
      ‫۳ سال و ۶ ماه قبل، چهارشنبه ۶ اسفند ۱۳۹۹، ساعت ۲۲:۳۴
      لطفا یکم بیشتر در مورد این Set Size توضیح بدید، یعنی اگه اون رو به یک تنظیم کنیم میشه بی نهایت کش تنظیم بشه و بعد که حافظه کم آورد بر اساس Priority میاد اضافه‌ها رو حذف میکنه ؟
      • #
        ‫۳ سال و ۶ ماه قبل، پنجشنبه ۷ اسفند ۱۳۹۹، ساعت ۰۰:۴۱
        بر اساس SizeLimit که خاصیت MemoryCacheOptions هست، کار می‌کند. اگر این خاصیت تنظیم شده باشد و (SetSize(1 در MemoryCacheEntryOptions استفاده شده باشد، هر آیتمی که به کش اضافه می‌کنید، یک واحد درنظر گرفته می‌شود. زمانیکه به SizeLimit رسید، شروع به حذف قدیمی‌ها می‌کند و البته اینکار را بر اساس priority آیتم‌های اضافه شده انجام می‌دهد. هر چقدر حق تقدم کمتری داشته باشند، زودتر حذف می‌شوند.
        • #
          ‫۳ سال و ۶ ماه قبل، یکشنبه ۱۰ اسفند ۱۳۹۹، ساعت ۲۱:۵۶
          اگر Set size رو بیشتر از یک در نظر بگیریم کاربردش چیه ؟
          • #
            ‫۳ سال و ۶ ماه قبل، یکشنبه ۱۰ اسفند ۱۳۹۹، ساعت ۲۳:۱۶
            واحد اندازه‌گیری هست. SetSize مشخص می‌کند که هر آیتم اضافه شده‌ی به کش، چند واحد را به خود اختصاص می‌دهد و SizeLimit حد نهایی مجموع این واحدها هست.
    • #
      ‫۳ سال و ۱ ماه قبل، سه‌شنبه ۲۹ تیر ۱۴۰۰، ساعت ۱۵:۱۹
      سلام، وقت بخیر؛ وقتی میخام از استیمول ریپرت در پروژه DNTIdentity  شما استفاده کنم با خطای زیر روبرو میشم.

      • #
        ‫۳ سال و ۱ ماه قبل، سه‌شنبه ۲۹ تیر ۱۴۰۰، ساعت ۱۵:۳۰
        این مورد را باید به صورت یک خطا، به تیم استیمول ارجاع بدید تا درستش کنند. تنظیم Size کش، هم توسط EF-Core و هم توسط ASP.NET Core در قسمت‌های خاصی انجام می‌شوند و .... مابقی باید خودشان را با این سیستم جدید وفق دهند. البته این تغییرات آنچنان جدید هم نیستند؛ بنابراین بهتر است قبل از گزارش خطا به آن‌ها، از آخرین نگارش استیمول استفاده کنید.
        • #
          ‫۳ سال و ۱ ماه قبل، سه‌شنبه ۲۹ تیر ۱۴۰۰، ساعت ۱۵:۴۴
          متاسفانه فقط در پروژه DNTIdentity این مشکل وجود دارد و در بقیه پروژه‌ها این خطا بروز نمیکند و ریپرتر درست کار میکند.از آخرین ورژن هم استفاده میکنم.با تشکر از شما.
          • #
            ‫۳ سال و ۱ ماه قبل، سه‌شنبه ۲۹ تیر ۱۴۰۰، ساعت ۱۶:۰۹
            برای تکرار: این SizeLimit توسط وابستگی‌های ثالث و امثال آن تنظیم می‌شود و زمانیکه تنظیم شد، شما باید خودتان را با آن وفق دهید. برای نمونه اگر در برنامه در قسمتی از آن، این موارد استفاده شده باشند، SizeLimit تنظیم شده دارند:
            و  ...
  • #
    ‫۴ سال و ۸ ماه قبل، شنبه ۱۴ دی ۱۳۹۸، ساعت ۱۲:۲۳
    با سلام آیا امکان تعریف چند پروفایل کش وجود دارد؟ 
    • #
      ‫۴ سال و ۸ ماه قبل، شنبه ۱۴ دی ۱۳۹۸، ساعت ۱۲:۳۷
      با توجه به قسمت «امکان تعریف پروفایل‌های کش » مطلب جاری، بله.
  • #
    ‫۴ سال و ۷ ماه قبل، یکشنبه ۲۹ دی ۱۳۹۸، ساعت ۱۵:۰۹
    با سلام؛
    - لطفا اگر تجربه ای از استفاده‌ی از کش در دات نت کور دارید که منجر به بهبود سرعت سایت یا کاهش استفاده از منابع سرور شده رو با ما هم در میان بگزارید که از چه نوع کش با چه تنظیماتی استفاده کردید؟
    - ضمنا اگر پروژه با SPA باشد مثلا با VueJS آیا باز هم کش مورد استفاده است؟
  • #
    ‫۳ سال و ۱ ماه قبل، دوشنبه ۱۱ مرداد ۱۴۰۰، ساعت ۱۹:۱۱
    من یک چنین اکشن متدی دارم:
        [ResponseCache(Duration = 60)]
            public IActionResult GetTime()
            {
                return Content(DateTime.Now.ToString());
            }
    و در پاسخ هم مقدار برابر است با:
    cache-control: public,max-age=60
    ولی با هر بار رفرش نتیجه به روز را میگیرم.برای همه بخش‌ها به همین شکل عمل میکند
    • #
      ‫۳ سال و ۱ ماه قبل، دوشنبه ۱۱ مرداد ۱۴۰۰، ساعت ۱۹:۳۷
      - اگر نیاز به فعالسازی سمت سرور بود، نیاز است یکسری میان‌افزار هم اضافه شوند.
      همچنین ReponseCache در این موارد اثری ندارد:
      • حتما باید status-code خروجی 200 و یا Ok باشد.
      • نوع درخواست باید head و یا get باشد.
      • هدر از نوع  authorization نباید حضور داشته باشد.
      • اگر میان‌افزار فایل‌های ثابت، پیش از میان‌افزار کش فعال شود، عملیات کش رخ نخواهد داد.
      • در اینجا هدر تنظیم کوکی نباید حضور داشته باشد.
      • #
        ‫۳ سال و ۱ ماه قبل، سه‌شنبه ۱۲ مرداد ۱۴۰۰، ساعت ۰۱:۲۰
        ممنون بررسی کردم به نظر میرسد مرورگر‌ها ( کروم و فایرفاکس تست شدند) در حالت reload کردن صفحه مجددا صفحات را درخواست میکنند و در این حالت کش را ندید میگیرند. طبق بررسی‌ها متدهای reload در جاوا اسکریپت نیز به همین شکل کش را ندید میگیرد. جهت تست و بررسی میتوانید لینک مورد نظر را در تب دیگری باز کرده تا نتیجه را مشاهده کنید.
        نکته دیگری که در جست و جو‌ها برخورد کردم این است که ممکن است مرورگر (بیشتر در رابطه با کروم بود) که کش را ممکن است روی حالت ssl نامعتبر نیز عمل نکند و ندید گرفته شود.
  • #
    ‫۲ سال و ۲ ماه قبل، یکشنبه ۵ تیر ۱۴۰۱، ساعت ۱۲:۱۸
    با سلام؛ MemoryCache برای  هر کاربر که لاگین می‌کند می‌تواند متفاوت باشد یا  مثل یک فیلد ایستا عمل می‌کند؟ دنبال اینم که هر کاربری که لاگین کرد محتویات کش آن متفاوت باشد؛ برای هر کاربر.
    • #
      ‫۲ سال و ۲ ماه قبل، یکشنبه ۵ تیر ۱۴۰۱، ساعت ۱۳:۵۴
      سراسری هست؛ هرچند می‌توانید کلید کش را بر اساس user-id تعیین کنید و یا از سشن استفاده کنید.