2012-06-13 3 views
6

मैं इसे प्रस्तुत करने से पहले किसी भी दृश्य के अंतिम संशोधित समय को प्राप्त करना चाहता हूं। यह लेआउट पृष्ठों, आंशिक दृश्य आदिएएसपी.नेट एमवीसी 3 किसी भी दृश्य के अंतिम संशोधित समय प्राप्त करें?

मैं के लिए

Response.Cache.SetLastModified(viewLastWriteUtcTime); 

ठीक से http कैशिंग को संभालने के लिए एक उचित समय निर्धारित करना चाहते हैं शामिल हैं। वर्तमान में मैं इस दृश्य खुद के लिए काम कर रहा है लेकिन अगर वहाँ लेआउट पृष्ठों में कोई परिवर्तन, या बच्चे को आंशिक दृश्य उन लोगों द्वारा

var viewLastWriteUtcTime = System.IO.File.GetLastWriteTime(
    Server.MapPath(
    (ViewEngines.Engines.FindView(ControllerContext, ViewBag.HttpMethod, null) 
      .View as BuildManagerCompiledView) 
     .ViewPath)).ToUniversalTime(); 

उठाया नहीं कर रहे हैं वहाँ किसी भी तरह से मैं समग्र अंतिम संशोधित समय प्राप्त कर सकते हैं है कर रहे हैं?

मैं 304 Not Modified के साथ प्रतिक्रिया के संबंधित भाग को संशोधित करने वाले तैनाती के बाद प्रतिक्रिया नहीं देना चाहता क्योंकि उपयोगकर्ताओं को असंगत व्यवहार मिलेगा।

+0

दिलचस्प समस्या:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public class UpdateLastModifiedFromViewsAttribute : ActionFilterAttribute { public override void OnResultExecuted(ResultExecutedContext filterContext) { var cache = filterContext.HttpContext.Response.Cache; cache.SetLastModified(CacheFriendlyRazorViewEngine.GetLatestTime(filterContext.Controller.ControllerContext, true)); } } 

अंत में, नियंत्रक आप पर या एक वैश्विक फिल्टर के रूप में इसका उपयोग करना चाहते करने के लिए फ़िल्टर लागू करें। सुनिश्चित नहीं है कि मेरा समाधान सबसे आसान तरीका है, लेकिन इसमें मजाक करना मजेदार था। – tvanfosson

उत्तर

5

मैं यह गारंटी नहीं दे रहा हूं कि यह करने का यह सबसे प्रभावी तरीका है, लेकिन मैंने इसका परीक्षण किया है और यह काम करता है। आपको GetRequestKey() तर्क को समायोजित करने की आवश्यकता हो सकती है और आप अपने परिदृश्य के आधार पर वैकल्पिक अस्थायी संग्रहण स्थान चुनना चाहेंगे। मैंने फ़ाइल के समय के लिए किसी भी कैशिंग को लागू नहीं किया क्योंकि ऐसा कुछ ऐसा लग रहा था जिसमें आपको कोई दिलचस्पी नहीं होगी। यह जोड़ना मुश्किल नहीं होगा कि समय कम हो जाए और आप इससे बचना चाहें प्रत्येक अनुरोध पर फ़ाइल का उपयोग ओवरहेड।

सबसे पहले, एक दृश्य इंजन के साथ RazorViewEngine का विस्तार करें जो इस अनुरोध के दौरान प्रदान किए गए सभी विचारों के लिए सबसे बड़ा अंतिम संशोधित समय ट्रैक करता है। हम सत्र आईडी द्वारा की गई सत्र में नवीनतम समय संग्रहीत करके और टाइमस्टैम्प का अनुरोध करके ऐसा करते हैं। आप इसे किसी भी अन्य दृश्य इंजन के साथ आसानी से कर सकते हैं।

public class CacheFriendlyRazorViewEngine : RazorViewEngine 
{ 
    protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) 
    { 
     UpdateLatestTime(controllerContext, GetLastModifiedForPath(controllerContext, viewPath)); 
     var pathToMaster = masterPath; 
     if (string.IsNullOrEmpty(pathToMaster)) 
     { 
      pathToMaster = "~/Views/Shared/_Layout.cshtml"; // TODO: derive from _ViewStart.cshtml 
     } 
     UpdateLatestTime(controllerContext, GetLastModifiedForPath(controllerContext, pathToMaster)); 
     return base.CreateView(controllerContext, viewPath, masterPath); 
    } 

    protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) 
    { 
     UpdateLatestTime(controllerContext, GetLastModifiedForPath(controllerContext, partialPath)); 
     return base.CreatePartialView(controllerContext, partialPath); 
    } 

    private DateTime GetLastModifiedForPath(ControllerContext controllerContext, string path) 
    { 
     return System.IO.File.GetLastWriteTime(controllerContext.HttpContext.Server.MapPath(path)).ToUniversalTime(); 
    } 

    public static void ClearLatestTime(ControllerContext controllerContext) 
    { 
     var key = GetRequestKey(controllerContext.HttpContext); 
     controllerContext.HttpContext.Session.Remove(key); 
    } 

    public static DateTime GetLatestTime(ControllerContext controllerContext, bool clear = false) 
    { 
     var key = GetRequestKey(controllerContext.HttpContext); 
     var timestamp = GetLatestTime(controllerContext, key); 
     if (clear) 
     { 
      ClearLatestTime(controllerContext); 
     } 
     return timestamp; 
    } 

    private static DateTime GetLatestTime(ControllerContext controllerContext, string key) 
    { 
     return controllerContext.HttpContext.Session[key] as DateTime? ?? DateTime.MinValue; 
    } 

    private void UpdateLatestTime(ControllerContext controllerContext, DateTime timestamp) 
    { 
     var key = GetRequestKey(controllerContext.HttpContext); 
     var currentTimeStamp = GetLatestTime(controllerContext, key); 
     if (timestamp > currentTimeStamp) 
     { 
      controllerContext.HttpContext.Session[key] = timestamp; 
     } 
    } 

    private static string GetRequestKey(HttpContextBase context) 
    { 
     return string.Format("{0}-{1}", context.Session.SessionID, context.Timestamp); 
    } 
} 

इसके बाद, कुछ वैश्विक फिल्टर में, global.asax.cs

protected void Application_Start() 
{ 
    System.Web.Mvc.ViewEngines.Engines.Clear(); 
    System.Web.Mvc.ViewEngines.Engines.Add(new ViewEngines.CacheFriendlyRazorViewEngine()); 
    ... 
} 

अंत में अपने नए के साथ मौजूदा इंजन (रों) बदलने के लिए या एक प्रति नियंत्रक आधार पर एक OnResultExecuted जोड़ें। नोट, मुझे विश्वास है कि प्रतिक्रिया के बाद नियंत्रक में सट्टेबाजी की जाती है, इसलिए मुझे लगता है कि आपको फ़िल्टर का उपयोग करना होगा। मेरा परीक्षण यह सच साबित करता है।

साथ ही, ध्यान दें कि सत्र के साथ सत्र को प्रदूषित करने के लिए उपयोग किए जाने के बाद मैं सत्र के मूल्य को साफ़ कर रहा हूं। हो सकता है कि आप इसे कैश में रखना चाहें और उस पर एक संक्षिप्त समाप्ति सेट कर सकें ताकि सत्र में इसे संग्रहीत करने की लेनदेन लागत से बचने के लिए आपको चीजों को स्पष्ट रूप से साफ करने की आवश्यकता नहीं है या यदि आपका सत्र स्मृति में नहीं रखा गया है।

[UpdateLastModifiedFromViews] 
public class HomeController : Controller 
{ 
    ... 
} 
+0

मेरे लिए अच्छा लग रहा है, मैं शायद सत्र के बजाय कैश का उपयोग करता हूं और उन्हें दृश्यनाम या इसी तरह के आधार पर कुंजी करता हूं। यह समझ में आता है कि निर्माण दृश्य/आंशिक रूप में हुकिंग करना ऐसा करने का एक व्यवहार्य तरीका होगा और फिर बैकिंग स्टोर का उपयोग करना होगा जो अद्यतन अधिकतम हो जाता है यदि लेखन समय वर्तमान अधिकतम से अधिक हो। –

संबंधित मुद्दे