Kur*_*ula 9 c# asp.net asp.net-mvc asp.net-mvc-4
我在asp.net mvc基本控制器中使用输出缓存属性,但每次都在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;
}
Run Code Online (Sandbox Code Playgroud)
是否还有其他最佳实践来加载所有页面的所有默认值并缓存它们?
如果您只想缓存数据,那么这OutputCache不是正确的机制。OutputCache可用于缓存由操作方法生成的 HTML,因此不必重新生成。如果您想缓存数据,可以使用 轻松实现HttpContextBase.Cache。
另外,我建议不要使用基本控制器类。这肯定意味着您将在同一个基本控制器中混合功能 a和功能 b以及功能 c的逻辑 - 您正在创建一个上帝对象。MVC有更好的方法——过滤器可以注册为所有操作运行,并且如果您将它们与过滤器结合使用,则可以在特定操作上使用它们。
虽然,对缓存使用全局过滤器可能根本没有任何意义,因为通常数据是在请求时缓存的,我已经创建了一个演示如何完成它。请注意,缓存是一个非常广泛的主题,可以通过多种方式完成,但由于您没有提供有关正在缓存的内容、数据源是什么或如何使用它的信息,因此我仅将其显示为一个可能的方式。
这里我们有一个执行缓存的动作过滤器。由于操作过滤器保证在视图之前运行,因此这是可以完成的一种方法。
MyCacheFilter做了三件事:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
为了使用我们的缓存过滤器并确保在显示任何视图之前填充缓存,我们将其注册为全局过滤器。全局过滤器非常适合在不同的类中保留单独的功能,这样它们就可以轻松维护(与基本控制器不同)。
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());
}
}
Run Code Online (Sandbox Code Playgroud)
为了使缓存的数据对于应用程序的其余部分来说是类型安全的,这里有一些方便的扩展方法。
/// <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;
}
}
Run Code Online (Sandbox Code Playgroud)
最后,我们开始使用视图中的数据。由于我们在对象上有扩展方法HttpContextBase,因此我们需要做的就是通过视图访问它并调用我们的扩展方法。
<p>
value1: @this.Context.GetMyDefault("value1")<br />
value2: @this.Context.GetMyDefault("value2")<br />
value3: @this.Context.GetMyDefault("value3")<br />
</p>
Run Code Online (Sandbox Code Playgroud)
我已经在此 GitHub 存储库中创建了该解决方案的工作演示。
再说一次,这不是唯一的方法。您可能希望针对您的应用程序对此进行一些更改。例如,您可以使用ViewData将数据返回到视图而不是HttpContextBase.Items. 或者您可能希望摆脱全局过滤器并将缓存模式移至从缓存加载/返回数据的单个扩展方法中。确切的解决方案取决于您在问题中未提供的内容 - 要求。
| 归档时间: |
|
| 查看次数: |
1363 次 |
| 最近记录: |