كيفية تشغيل الإخراج للتخزين المؤقت للمستخدمين المصادقين في ASP.NET MVC؟
-
22-09-2019 - |
سؤال
لدي تطبيق ASP.NET MVC. أنا بحاجة إلى تخزين بعض الصفحات ولكن فقط للمستخدمين غير المصابين.
لقد حاولت استخدام VaryByCustom="user"
كالآتي GetVaryByCustomString
التنفيذ:
public override string GetVaryByCustomString(HttpContext context, string custom)
{
if (custom == "user")
{
if (context.User.Identity.IsAuthenticated)
{
return context.User.Identity.Name;
}
else
{
return "";
}
}
return base.GetVaryByCustomString(context, custom);
}
ومع ذلك ، هذا ليس بالضبط ما أحتاجه لأن الصفحات لا تزال مخزنة مؤقتًا. الفرق الوحيد هو أنه تم تخزينه مؤقتًا الآن لكل مستخدم بشكل منفصل.
أحد الحلول الممكنة هو العودة Guid.NewGuid()
في كل مرة يتم فيها مصادقة المستخدم ، ولكن يبدو لي مضيعة كبيرة للموارد بالنسبة لي.
هل لديك أي نصائح لي؟
المحلول
إذن هذا ما فعلته:
public class NonAuthenticatedOnlyCacheAttribute : OutputCacheAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
var httpContext = filterContext.HttpContext;
if (httpContext.User.Identity.IsAuthenticated)
{
// it's crucial not to cache Authenticated content
Location = OutputCacheLocation.None;
}
// this smells a little but it works
httpContext.Response.Cache.AddValidationCallback(IgnoreAuthenticated, null);
base.OnResultExecuting(filterContext);
}
// This method is called each time when cached page is going to be
// served and ensures that cache is ignored for authenticated users.
private void IgnoreAuthenticated(HttpContext context, object data, ref HttpValidationStatus validationStatus)
{
if (context.User.Identity.IsAuthenticated)
validationStatus = HttpValidationStatus.IgnoreThisRequest;
else
validationStatus = HttpValidationStatus.Valid;
}
}
شكرا جزيلا ل كريج ستونتز الذي أشارني إلى تصحيح الاتجاه والذي أجابني عن غير قصد.
نصائح أخرى
يتم التخزين المؤقت للسمات بشكل عام ، ثم تحتاج إلى تخزين الموقع الأصلي. إذا قمت بالوصول إلى الصفحة التي تم تسجيلها ، فستضع موقعًا على أي شيء ، ثم عند الوصول إلى مجهول ، لا يزال هناك شيء.
public class AuthenticatedOnServerCacheAttribute : OutputCacheAttribute
{
private OutputCacheLocation? originalLocation;
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
var httpContext = filterContext.HttpContext;
if (httpContext.User.Identity.IsAuthenticated)
{
originalLocation = originalLocation ?? Location;
Location = OutputCacheLocation.None;
}
else
{
Location = originalLocation ?? Location;
}
base.OnResultExecuting(filterContext);
}
}
الإجابة المقبولة صحيحة لكنها لا تعمل على التخزين المؤقت بهذه الطريقة وجهات النظر الجزئية. لقد جمعت كلا الاختلافين:GetVaryByCustomString
وحدد Duration
إلى الحد الأدنى - للآراء الجزئية و AddValidationCallback
طريقة للصفحات. في الواقع ، من الممكن استخدام الطريقة الأولى فقط ولكن الطريقة الثانية لا تبدو باهظة الثمن - إنها لا تتصل OnResultExecuting
في كل مرة ولكن معالج مسجل فقط.
لذلك فئة سمة ذاكرة التخزين المؤقت المخصصة
public class CacheAttribute : OutputCacheAttribute
{
public CacheAttribute()
{
Duration = 300; /*default cache time*/
}
private bool _partialView;
/// <summary>
/// Set true if Partial view is cached
/// </summary>
public bool PartialView
{
get { return _partialView; }
set
{
_partialView = value;
if ( _partialView ) {
VaryByCustom = "Auth";
}
}
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
if ( PartialView ) OnCachePartialEnabled( filterContext );
else OnCacheEnabled(filterContext);
base.OnResultExecuting( filterContext );
}
private OutputCacheLocation? originalLocation;
private int? _prevDuration;
protected void OnCachePartialEnabled(ResultExecutingContext filterContext)
{
var httpContext = filterContext.HttpContext;
if ( !_prevDuration.HasValue) _prevDuration = Duration;
Duration = httpContext.User.Identity.IsAuthenticated ? 1 : _prevDuration.Value;
}
protected void OnCacheEnabled(ResultExecutingContext filterContext)
{
var httpContext = filterContext.HttpContext;
if ( httpContext.User.Identity.IsAuthenticated ) {
// it's crucial not to cache Authenticated content
originalLocation = originalLocation ?? Location;
Location = OutputCacheLocation.None;
}
else {
Location = originalLocation ?? Location;
}
// this smells a little but it works
httpContext.Response.Cache.AddValidationCallback( IgnoreAuthenticated, null );
}
// This method is called each time when cached page is going to be
// served and ensures that cache is ignored for authenticated users.
private void IgnoreAuthenticated(HttpContext context, object data, ref HttpValidationStatus validationStatus)
{
validationStatus = context.User.Identity.IsAuthenticated
? HttpValidationStatus.IgnoreThisRequest
: HttpValidationStatus.Valid;
}
}
تجاوز طريقة getVaryByCustomString في global.asax.cs
public override string GetVaryByCustomString(HttpContext context, string custom)
{
if ( custom == "Auth" ) {
//do not cache when user is authenticated
if ( context.User.Identity.IsAuthenticated ) {
return base.GetVaryByCustomString( context, custom );
}
return "NotAuth";
}
return base.GetVaryByCustomString( context, custom );
}
استخدمه مثل هذا:
[Cache]
public virtual ActionResult Index()
{
return PartialView();
}
[ChildActionOnly, Cache(PartialView=true)]
public virtual ActionResult IndexPartial()
{
return PartialView();
}
محدث: لقد أضفت أيضًا إصلاح Fujiy هنا