سلوك الإخراج في ASP.NET MVC 3
-
27-09-2019 - |
سؤال
كنت مجرد اختبار التخزين المؤقت للإخراج في بناء RC من ASP.NET MVC 3.
بطريقة ما ، لا يكرم خاصية VaryByparam (أو بالأحرى ، لست متأكدًا من أنني أفهم ما يجري):
public ActionResult View(UserViewCommand command) {
هنا ، لدى UserviewCommand خاصية تسمى Slug والتي تستخدم للبحث عن مستخدم من قاعدة البيانات.
هذا هو إعلان OutputCache:
[HttpGet, OutputCache(Duration = 2000, VaryByParam = "None")]
ومع ذلك ، عندما أحاول الوصول إلى طريقة الإجراء باستخدام قيم "Slug" المختلفة (عن طريق manupulating عنوان URL) ، بدلاً من تقديم بيانات خاطئة (التي أحاول فرضها عن طريق التصميم) ، فإنها بدلاً من ذلك تستدعي طريقة الإجراء.
على سبيل المثال (حسب ترتيب الاحتجاج)
/مستخدم/عرض/ABC -> يستدعي طريقة الإجراء باستخدام slug = abc/user/view/abc -> طريقة الإجراء لم يتم استدعاؤها/المستخدم/view/xyz -> استدعاء طريقة الإجراء مرة أخرى مع slug = xyz! ألم يكن من المفترض أن يخرج من ذاكرة التخزين المؤقت لأن varybyparam = لا شيء؟
أيضا ، ما هي الطريقة الموصى بها لاتخاذ الإخراج في مثل هذا الموقف؟ (مثال أعلاه)
المحلول
أردت فقط إضافة هذه المعلومات حتى يتم مساعدة الأشخاص الذين يبحثون:
تم تغيير سلوك OutputCache إلى "كما هو متوقع" في الإصدار الأخير (ASP.NET MVC 3 RC 2):
http://weblogs.asp.net/scottgu/archive/2010/12/10/announcing-asp-net-mvc-3-release-candidate-2.aspx
طريقة للذهاب ASP.NET MVC Team (و Master GU)! أنتم جميعا رائعون!
نصائح أخرى
يعمل VaryByparam فقط عندما تبدو قيم عنوان URL /user/view?slug=abc
. يجب أن تكون المعلمة معلمة QueryString وليس جزءًا من عنوان URL مثل الأمثلة المذكورة أعلاه. والسبب في ذلك هو على الأرجح لأن التخزين المؤقت يحدث قبل أي رسم خرائط عناوين URL وهذا التعيين غير مدرج في ذاكرة التخزين المؤقت.
تحديث
سوف يحصلك الرمز التالي على المكان الذي تريد الذهاب إليه. لا يأخذ في الاعتبار أشياء مثل Authorized
المرشحات أو أي شيء ولكنها سوف تخزين ذاكرة التخزين المؤقت بناءً على وحدة التحكم/الإجراء/المعرفات ولكن إذا قمت بتجاهل = "Slug" ، فسيتجاهل تلك السمة المحددة
public class ActionOutputCacheAttribute : ActionFilterAttribute {
public ActionOutputCacheAttribute(int cacheDuration, string ignore) {
this.cacheDuration = cacheDuration;
this.ignore = ignore;
}
private int cacheDuration;
private string cacheKey;
private string ignore;
public override void OnActionExecuting(ActionExecutingContext filterContext) {
string url = filterContext.HttpContext.Request.Url.PathAndQuery;
this.cacheKey = ComputeCacheKey(filterContext);
if (filterContext.HttpContext.Cache[this.cacheKey] != null) {
//Setting the result prevents the action itself to be executed
filterContext.Result =
(ActionResult)filterContext.HttpContext.Cache[this.cacheKey];
}
base.OnActionExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext) {
//Add the ActionResult to cache
filterContext.HttpContext.Cache.Add(this.cacheKey, filterContext.Result,null, DateTime.Now.AddSeconds(cacheDuration),
System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
//Add a value in order to know the last time it was cached.
filterContext.Controller.ViewData["CachedStamp"] = DateTime.Now;
base.OnActionExecuted(filterContext);
}
private string ComputeCacheKey(ActionExecutingContext filterContext) {
var keyBuilder = new StringBuilder();
keyBuilder.Append(filterContext.ActionDescriptor.ControllerDescriptor.ControllerName);
keyBuilder.Append(filterContext.ActionDescriptor.ActionName);
foreach (var pair in filterContext.RouteData.Values) {
if (pair.Key != ignore)
keyBuilder.AppendFormat("rd{0}_{1}_", pair.Key.GetHashCode(), pair.Value.GetHashCode());
}
return keyBuilder.ToString();
}
}