Choosing a custom output cache provider for specific controller actions

I am trying to implement MongoDB / Memory, the unified output cache provider, for use with MVC4. Here is my initial implementation:

public class CustomOutputCacheProvider : OutputCacheProvider { public override object Get(string key) { FileLogger.Log(key); return null; } public override object Add(string key, object entry, DateTime utcExpiry) { return entry; } public override void Set(string key, object entry, DateTime utcExpiry) { } public override void Remove(string key) { } } 

And my entry in web configuration:

 <caching> <outputCache defaultProvider="CustomOutputCacheProvider"> <providers> <add name="CustomOutputCacheProvider" type="MyApp.Base.Mvc.CustomOutputCacheProvider" /> </providers> </outputCache> </caching> 

And use in HomeController:

 [OutputCache(Duration = 15)] public ActionResult Index() { return Content("Home Page"); } 

My problem is that when I check the log file for the requested keys, I see not only a request to the home controller, but also all other ways:

 a2/ <-- should only log this entry a2/test a2/images/test/50115c53/1f37e409/4c7ab27d/50115c531f37e4094c7ab27d.jpg a2/scripts/jquery-1.7.2.min.js 

I realized that I should not set CustomOutputCacheProvider as defaultProvider in Web.Config, I could not figure out how to specify the cache provider that I want to use for a specific controller action.

Using Asp.Net web pages, you can execute it using <%@ OutputCache Duration="60" VaryByParam="None" providerName="DiskCache" %> at the top of the page, but for MVC the only solution I could find , is an override of the HttpApplication.GetOutputCacheProviderName Method in Global.asax.

Is there a more elegant way to do this using the [OutputCache] attribute?

+6
source share
3 answers

Is there a more elegant way to set OutputCacheProvider using the [OutputCache] attribute?

I think the answer is no (well, not with the current version of mvc4), since there is no connection between the implementation of the custom OutputCacheProvider and the decoration of the action with the OutputCache attribute.

As you discovered, by implementing a custom provider and registering with the Get method, you see every request made to the web server. If you removed the OutputCache attribute from all of your actions, you will still see every request in the error log. I thought that the answer to this ASP.NET MVC gets into outputcache for every action , it was pretty useful to confirm this.

Since it looks like you want to implement only one output cache provider, I think your only option is to not set the default provider and continue to override the implementation of GetOutputCacheProviderName (as you mentioned). Maybe something like this to exclude all content, images and scripts.

 public override string GetOutputCacheProviderName(HttpContext context) { string absolutePath = context.Request.Url.AbsolutePath; if (absolutePath.StartsWith("/Content/", StringComparison.CurrentCultureIgnoreCase) || absolutePath.StartsWith("/Scripts/", StringComparison.CurrentCultureIgnoreCase) || absolutePath.StartsWith("/Images/", StringComparison.CurrentCultureIgnoreCase)) return base.GetOutputCacheProviderName(context); return "CustomOutputCacheProvider"; } 

If you need to implement more than one output cache provider, I think you will need to implement an assistant to give you the correct provider name. But here is an example when I allowed you routing data; where, as the previous example looked directly at the URL.

 public override string GetOutputCacheProviderName(HttpContext context) { RouteCollection rc = new RouteCollection(); MvcApplication.RegisterRoutes(rc); RouteData rd = rc.GetRouteData(new HttpContextWrapper(HttpContext.Current)); if (rd == null) return base.GetOutputCacheProviderName(context); var controller = rd.Values["controller"].ToString(); var action = rd.Values["action"].ToString(); if (controller.Equals("Content", StringComparison.CurrentCultureIgnoreCase) || controller.Equals("Scripts", StringComparison.CurrentCultureIgnoreCase) || controller.Equals("Images", StringComparison.CurrentCultureIgnoreCase)) return base.GetOutputCacheProviderName(context); if (controller.Equals("Account", StringComparison.CurrentCultureIgnoreCase)) return "AccountOutputCacheProvider"; if (controller.Equals("Something", StringComparison.CurrentCultureIgnoreCase)) return controller + "OutputCacheProvider"; return "CustomOutputCacheProvider"; } 
+5
source

If I where you are, I will try to write MyOutputCachAttribute, inherited from OutputCachAttribute, which will select the provider by its parameter.

+1
source

Check out this article from MSDN Magazine (with source code and examples linking to MongoDB and Azure as distributed cache providers) may well provide some insight http://msdn.microsoft.com/en-us/magazine/gg650661.aspx

EDIT

Can the CacheProfile parameter be used to specify the provider as suggested here?

http://www.dotnetcurry.com/ShowArticle.aspx?ID=665

0
source

Source: https://habr.com/ru/post/922171/


All Articles