The IDE: ASP.NET MVC with Visual Studio 2008
The environment: Web-App on IIS
The data that is being retrieved varies greatly in terms of their lifespan:
- Some data is very static like States, Countries
- Other data is more fluid, especially during end-user testing, like the load of scripts that have to be fixed occasionally and pushed to production during the day. Especially early on in the test these pushes can happen hourly in some cases and as progress is made during the tests becomes less frequent
- A list of FAQ and Bug fixes that the users can access from the web page has to be refreshed a few times a day
No matter the reason or validity thereof, it is simple enough to specify the OutputCache for each. For example:
Caches the load of script files for 2 hours:
[OutputCache(Duration = 7200, VaryByParam = "none")]
public FileResult GetjQueryScripts()
{
string combinedResults = combineLikeDirectoryFiles("~/Scripts/jquery/Base/", FileType.js);
combinedResults += combineLikeDirectoryFiles("~/Scripts/jquery/Plugins/", FileType.js);
combinedResults += combineLikeDirectoryFiles("~/Scripts/jquery/Plugins/jquery.grid/", FileType.js);
combinedResults += combineLikeDirectoryFiles("~/Scripts/jquery/Plugins/jquery.datepick/", FileType.js);
return streamText(combinedResults, js);
}
Caches States for 2 days:
[OutputCache(Duration = 57600, VaryByParam = "none")]
public string GetAllStates()
{
return GetAllForGenericData(Repository.FindAll());
}
The problem: This works great, but has some issues:
- hard coded so needs re-compilation and code-migration (who knows how long that can take)
- In a development environment, especially if you do not want caching. For example my scripts are cached and when I make a script change do not want the cached version locally during unit testing. Set the duration property of the cache to 0 for this and REMEMBER to change it to (what was it again?!) before you build and deploy, or commit/check-in to version-control.
[CustomOutputCacheAttribute(TypeOfFileToCache = FileType.js, VaryByParam = "none")]
public FileResult GetjQueryScripts()
{
string combinedResults = combineLikeDirectoryFiles("~/Scripts/jquery/Base/", FileType.js);
combinedResults += combineLikeDirectoryFiles("~/Scripts/jquery/Plugins/", FileType.js);
combinedResults += combineLikeDirectoryFiles("~/Scripts/jquery/Plugins/jquery.grid/", FileType.js);
combinedResults += combineLikeDirectoryFiles("~/Scripts/jquery/Plugins/jquery.datepick/", FileType.js);
return streamText(combinedResults, js);
}
Here is the declaration of the custom attribute:
public class CustomOutputCacheAttribute : OutputCacheAttribute
{
private FileType _typeOfFileToCache;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
SetupDuration();
base.OnActionExecuting(filterContext);
}
public FileType TypeOfFileToCache
{
get { return _typeOfFileToCache; }
set { _typeOfFileToCache = value; }
}
public string VaryByParam
{
get { return base.VaryByParam; }
set { base.VaryByParam = value; }
}
public void SetupDuration()
{
int durateMe;
switch (TypeOfFileToCache)
{
case FileType.js:
{
base.Duration = int.TryParse(ConfigurationSettings.AppSettings[ "outputCacheDurationScriptLoad" ],
out durateMe)
? durateMe
: 0;
}
break;
case FileType.css:
{
base.Duration = int.TryParse(ConfigurationSettings.AppSettings[ "outputCacheDurationCssLoad" ],
out durateMe)
? durateMe
: 0;
}
break;
default:
base.Duration = 0;
break;
}
}
}
public enum FileType
{
js = 1,
css = 2
}
Note that it inherits from System.MVC library's OutputCacheAttribute class. The OnActionExecuting method is called by the framework, which is overridden. The OnActionExecuting method essentially only has one addition, the SetupDuration() method that gets its duration from the web.config file based on the file type. In this example the app has a different duration for css and js files. The next important step in the OnActionExecuting() method is to invoke the base's OnActionExecuting() method, and you're done.
No comments:
Post a Comment