gpt4 book ai didi

c# - 基本 Controller 中的 Asp.Net MVC Outputcache 不工作

转载 作者:太空狗 更新时间:2023-10-29 17:49:09 27 4
gpt4 key购买 nike

我在 asp.net mvc 基本 Controller 中使用输出缓存属性,但它每次都被调用,就像在 OnActionExecuting 中一样。是否有任何选项可以只调用一次该方法来加载所有默认值?

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
GetDefaults();
base.OnActionExecuting(filterContext);
}

[OutputCache(Duration = 60000)]
private ActionResult GetDefaults()
{
//code to load all my default values
// Viewdata values used in all pages in my aplication
// Viewdata values used in all pages in my aplication
// Viewdata values used in all pages in my aplication
return null;
}

加载所有页面的所有默认值并缓存它们的任何其他最佳实践?

最佳答案

如果您只想缓存数据,那么OutputCache 不是正确的机制。 OutputCache 可用于缓存由操作方法生成的 HTML,因此不必重新生成。如果要缓存数据,可以使用 HttpContextBase.Cache 轻松实现。

此外,我 recommend against using a base controller class .这肯定意味着您将在同一个基本 Controller 中混合用于功能 a功能 b 以及 功能 c 的逻辑 - 您正在创建一个god object . MVC 有更好的方法 - filters它可以注册为所有操作运行,如果您将它们与过滤器结合使用,则可以用于特定操作。

虽然,对缓存使用全局过滤器可能根本没有任何意义,因为通常数据是在被请求时缓存的,我已经创建了一个演示如何它可以做完了。请注意,缓存是一个非常广泛的主题,可以通过多种方式完成,但是由于您没有提供有关缓存内容、数据源或使用方式的信息,我只是将其作为一种可能的方式展示。

我的缓存过滤器

这里我们有一个执行缓存的 Action 过滤器。由于操作过滤器保证在 View 之前运行,因此这是一种可以完成的方法。

MyCacheFilter 做了 3 件事:

  1. 从缓存中读取数据
  2. 检查数据是否存在,如果不存在,则重新加载缓存
  3. 将对数据对象的引用添加到请求缓存,可以从应用程序中的任何其他位置访问它,包括 View 。

public class MyCacheFilter : IActionFilter
{
/// <summary>
/// The cache key that is used to store/retrieve your default values.
/// </summary>
private static string MY_DEFAULTS_CACHE_KEY = "MY_DEFAULTS";

public void OnActionExecuted(ActionExecutedContext filterContext)
{
// Do nothing
}

public void OnActionExecuting(ActionExecutingContext filterContext)
{
var cache = filterContext.HttpContext.Cache;

// This method is called for each request. We check to ensure the cache
// is initialized, and if not, load the values into it.
IDictionary<string, string> defaults =
cache[MY_DEFAULTS_CACHE_KEY] as IDictionary<string, string>;
if (defaults == null)
{
// The value doesn't exist in the cache, load it
defaults = GetDefaults();

// Store the defaults in the cache
cache.Insert(
MY_DEFAULTS_CACHE_KEY,
defaults,
null,
DateTime.Now.AddHours(1), // Cache for exactly 1 hour from now
System.Web.Caching.Cache.NoSlidingExpiration);
}

// Caching work is done, now return the result to the view. We can
// do that by storing it in the request cache.
filterContext.HttpContext.SetMyDefaults(defaults);
}

private IDictionary<string, string> GetDefaults()
{
// You weren't specific about where your defaults data is coming from
// or even what data type it is, but you can load it from anywhere in this method
// and return any data type. The type returned should either by readonly or thread safe.
var defaults = new Dictionary<string, string>
{
{ "value1", "testing" },
{ "value2", "hello world" },
{ "value3", "this works" }
};


// IMPORTANT: Cached data is shared throughout the application. You should make
// sure the data structure that holds is readonly so it cannot be updated.
// Alternatively, you could make it a thread-safe dictionary (such as ConcurrentDictionary),
// so it can be updated and the updates will be shared between all users.
// I am showing a readonly dictionary because it is the safest and simplest way.
return new System.Collections.ObjectModel.ReadOnlyDictionary<string, string>(defaults);
}
}

MyCacheFilter 用法

要使用我们的缓存过滤器并确保在显示任何 View 之前填充缓存,我们将其注册为全局过滤器。全局过滤器非常适合在不同的类中保留单独的功能片段,它们可以在其中轻松维护(与基本 Controller 不同)。

public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
// Add our MyCacheFilter globally so it runs before every request
filters.Add(new MyCacheFilter());
filters.Add(new HandleErrorAttribute());
}
}

HttpContextBaseExtensions

为了使缓存的数据对于应用程序的其余部分是类型安全的,这里有几个方便的扩展方法。

/// <summary>
/// Extensions for convenience of using the request cache in views and filters.
/// Note this is placed in the global namespace so you don't have to import it in your views.
/// </summary>
public static class HttpContextBaseExtensions
{
/// <summary>
/// The key that is used to store your context values in the current request cache.
/// The request cache is simply used here to transfer the cached data to the view.
/// The difference between the request cache (HttpContext.Items) and HttpContext.Cache is that HttpContext.Items
/// is immediately released at the end of the request. HttpContext.Cache is stored (in RAM) for the length of
/// the timeout (or alternatively, using a sliding expiration that keeps it alive for X time after
/// the most recent request for it).
///
/// Note that by using a reference type
/// this is very efficient. We aren't storing a copy of the data in the request cache, we
/// are simply storing a pointer to the same object that exists in the cache.
/// </summary>
internal static string MY_DEFAULTS_KEY = "MY_DEFAULTS";


/// <summary>
/// This is a convenience method so we don't need to scatter the reference to the request cache key
/// all over the application. It also makes our cache type safe.
/// </summary>
public static string GetMyDefault(this HttpContextBase context, string defaultKey)
{
// Get the defaults from the request cache.
IDictionary<string, string> defaults = context.Items[MY_DEFAULTS_KEY] as IDictionary<string, string>;

// Get the specific value out of the cache that was requested.
// TryGetValue() is used to prevent an exception from being thrown if the key doesn't
// exist. In that case, the result will be null
string result = null;
defaults.TryGetValue(defaultKey, out result);

return result ?? String.Empty;
}

/// <summary>
/// This is a convenience method so we don't need to scatter the reference to the request cache key
/// all over the application. It also makes our cache type safe.
/// </summary>
internal static void SetMyDefaults(this HttpContextBase context, IDictionary<string, string> defaults)
{
context.Items[MY_DEFAULTS_KEY] = defaults;
}
}

用法

最后,我们开始使用 View 中的数据。由于我们在 HttpContextBase 对象上有扩展方法,我们需要做的就是通过 View 访问它并调用我们的扩展方法。

<p>
value1: @this.Context.GetMyDefault("value1")<br />
value2: @this.Context.GetMyDefault("value2")<br />
value3: @this.Context.GetMyDefault("value3")<br />
</p>

我已经创建了这个解决方案的工作演示 in this GitHub repository .

同样,这不是唯一的方法。您可能希望为您的应用程序稍微改变一下。例如,您可以使用 ViewData 代替 HttpContextBase.Items 将数据返回到 View 。或者您可能希望摆脱全局过滤器并将缓存模式移动到单个扩展方法中,该方法从缓存中加载/返回数据。确切的解决方案取决于您在问题中未提供的内容 - 要求。

关于c# - 基本 Controller 中的 Asp.Net MVC Outputcache 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41918276/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com