Saturday, August 20, 2011

MVC Donut hole caching for Razor View

    I was interested with Donut caching for a while and today I have a need for the Donut hole caching or partial view caching. As many of us, I tried to find whether some smart guys had solved this problem. And it seems like Mr.Haacked had mentioned this in his post. However, that solution is for ASP.NET view engine. I have no choice and have to solve it myself. Hopefully MVC team will support this feature in next versions of MVC framework. Hmmm indeed, it could be supported in version 4: See road map.


    My idea is if a view engine renders the view's content to a stream or text writer, we can intercept that process, cache the output string to somewhere together with the view's id or what ever that can identify the view. Then next time the view is rendered, we can determine whether or not to get the content from cache or let the view engine continue it's job. So i dig into the MVC source code and find this:

public class RazorView : BuildManagerCompiledView
{
    protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance)
    {
        //.............
    }
}
    That's exactly what i need, isn't it? We probably can create a derived class from RazorView and override above method, get the content that the text writer receive and write it directly to the writer if the view is cached. So, i need a custom text writer that could return to me what it receive :D
public class TrackableTextWriter : TextWriter
{
    private readonly TextWriter _writer;
    private StringBuilder _mem;
    public TrackableTextWriter(TextWriter writer)
    {
        _writer = writer;
        _mem = new StringBuilder();
    }
    public override Encoding Encoding
    {
        get { return _writer.Encoding; }
    }
    public override void Write(string value)
    {
        _writer.Write(value);
        _mem.Append(value);
    }
    public string GetWrittenString()
    {
        return _mem.ToString();
    }
    protected override void Dispose(bool disposing)
    {
        if (!disposing)
        {
            _writer.Dispose();           
        }
        base.Dispose(disposing);
        _mem = null;
    }
}
    Alright, now it's time to create a derived of RazorView:
public class CachableRazorView : RazorView
{
	private const string ViewCachePrefix = "ViewCache__";
    protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance)
	{
		var appCache = viewContext.HttpContext.Cache;
		var cacheKey = ViewCachePrefix + ViewPath;
		// Check if there was a Cache config that had been fully added to the cache
		var cacheConfiguration = appCache[cacheKey] as CacheConfiguration;
		if (cacheConfiguration != null && cacheConfiguration.Data != null)
		{
			writer.Write(cacheConfiguration.Data);
			return;
		}
		var trackableTextWriter = new TrackableTextWriter(writer);
		base.RenderView(viewContext, trackableTextWriter, instance);
		
		// Cache config has just been added when the view is rendered the first time thanks to the HtmlHelper
		cacheConfiguration = appCache[cacheKey] as CacheConfiguration;
		if (cacheConfiguration != null)
		{
			var writtenString = trackableTextWriter.GetWrittenString();
			cacheConfiguration.Data = writtenString;
			appCache.Remove(cacheConfiguration.Id);
			appCache.Add(cacheConfiguration.Id,
						cacheConfiguration,
						null,
						Cache.NoAbsoluteExpiration,
						TimeSpan.FromSeconds(cacheConfiguration.Duration),
						CacheItemPriority.Default,
						null);
		}
	}
}
    Then there's of course a place we can return this custom view instead of RazorView. That's definitely the RazorViewEngine. So next step is creating our custom razor view engine:
public class CachableRazorViewEngine : RazorViewEngine
{
	protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
	{
		return new CachableRazorView(controllerContext, partialPath, null, false, FileExtensions, ViewPageActivator);
	}

	protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
	{
		return new CachableRazorView(controllerContext, viewPath, masterPath, true, FileExtensions, ViewPageActivator);
	}
}
    As usual, we need to make the web application use this view engine by modifying the globals.asax
protected void Application_Start()
{
	AreaRegistration.RegisterAllAreas();

	RegisterGlobalFilters(GlobalFilters.Filters);

	ViewEngines.Engines.Clear();
	ViewEngines.Engines.Add(new CachableRazorViewEngine());

	RegisterRoutes(RouteTable.Routes);
}
    Using this approach, the traditional OutputCache will not have value. So the idea pops in my head is making a HtmlHelper extension and calling it in the view, something like this:
@{
	Html.OutputCache(new CacheConfiguration { Duration = 10 });
}
    So here is the implementation:
public static class CacheHtmlHelperExtensions
{
	public const string ViewCachePrefix = "ViewCache__";
	public static void OutputCache(this HtmlHelper helper, CacheConfiguration cacheConfiguration)
	{
		var view = helper.ViewContext.View as BuildManagerCompiledView;
		if (view != null)
		{
			cacheConfiguration.Id = ViewCachePrefix + view.ViewPath;
			helper.ViewContext.HttpContext.Cache.Add(cacheConfiguration.Id,
													cacheConfiguration,
                                                    null,
                                                    Cache.NoAbsoluteExpiration,
                                                    TimeSpan.FromSeconds(cacheConfiguration.Duration),
                                                    CacheItemPriority.Default,
                                                    null);
		}
	}
}
    Okey, it's time to test this implementation. I put the Html.OutputCache method in the Index page of default MVC application like above. So the view will be cached in 10 seconds. If the view is not accessed in next 10 seconds, the cache engine will remove the content from the cache. However, within 10 seconds, if the view is accessed again, the cache will remain for next 10 seconds and so on. Pretty cool, huh? I need to run the performance test on this page to see the actual result. There is a very cool tool in Linux named "curl-loader" but I didn't know any for Windows. After a while searching, I found apache benchmark very similar and usefull :D. I use "ab" tool to test the web app when enable and disable the cache. The result is very interesting. Eventhough the Index page is quite simple with only text, no database access but when I enable the cache, the web server can serve 1107 requests per second when I run 10000 requests to server at concurency level at 100 compare to only 531 requests per second when I disable the cache, 2 times faster:

benchmark result

    Summary, there is a outstanding issue using this approach, the builtin output cache of ASP.NET can not be utilised. It also ignores the value of ViewModel, that's mean this implementation has not supported caching by different view model. But I think we can do it if we really need that feature. Just find a way to distinguish the different between view model values, it could be a hash code or something :D.

Source code: Razor.DonutHoleCaching.zip

Cheers

44 comments:

Tugberk said...

Hmm, looks like a nice post. To be honest, I haven't read all of it but as I see, you have gone wild a little bit. Why not create a child action and output it inside the view with Html.Action HtmlHelper? This will make it easier.

Unknown said...

Haha, you are right. ASP.NET MVC is so easy to extend that sometime we pick the wrong technical decision :D.

Anyway, there are still cases to use this approach if someone like me don't like to let the view to be aware of the controller :D. It's an anti pattern, isn't it?

Sagar said...

Nice post.
In my search results, found another very nice article on Donut Hole Caching in MVC.
The article also include tutorial for it.
Do try it http://swsharinginfo.blogspot.in/2012/03/donut-hole-caching-partial-view-caching.html

Ramya Krishnan said...

i have go through your article, it is very nice and more informative, clearly understands me. Thanks.
ASP.NET Training in chennai

prabha said...

A very nice guide. I will definitely follow these tips. Thank you for sharing such detailed article. I am learning a lot from you.
angularjs Training in marathahalli

angularjs interview questions and answers

angularjs Training in bangalore

angularjs Training in bangalore

angularjs online Training

angularjs Training in marathahalli

simbu said...

A very nice guide. I will definitely follow these tips. Thank you for sharing such detailed article. I am learning a lot from you.
Java training in Chennai | Java training in Velachery

Java training in Chennai | Java training in Omr

Oracle training in Chennai

Java training in Chennai | Java training in Annanagar

gowsalya said...

Just stumbled across your blog and was instantly amazed with all the useful information that is on it. Great post, just what i was looking for and i am looking forward to reading your other posts soon!
python training in rajajinagar
Python training in bangalore
Python training in usa

kevin antony said...

This is most informative and also this post most user friendly and super navigation to all posts... Thank you so much for giving this information to me.

rpa training in chennai
rpa training in bangalore
rpa course in bangalore
best rpa training in bangalore
rpa online training

nilashri said...

Thanks for the informative article. This is one of the best resources I have found in quite some time. Nicely written and great info. I really cannot thank you enough for sharing.
Data Science training in Chennai | Data Science Training Institute in Chennai
Data science training in Bangalore | Data Science Training institute in Bangalore
Data science training in pune | Data Science training institute in Pune
Data science online training | online Data Science certification Training-Gangboard
Data Science Interview questions and answers

Unknown said...

I am really happy with your blog because your article is very unique and powerful for new reader.
Click here:
selenium training in chennai | selenium course in chennai
selenium training in bangalore | selenium course in bangalore
selenium training in Pune | selenium course in pune | selenium class in pune
selenium training in Pune | selenium course in pune | selenium class in pune
selenium online training | selenium training online | online training on selenium


sunshineprofe said...

I have to voice my passion for your kindness giving support to those people that should have guidance on this important matter.
iosh course in chennai

afiah b said...

Were a gaggle of volunteers as well as starting off a brand new gumption within a community. Your blog furnished us precious details to be effective on. You've got completed any amazing work!

Java training in Chennai

Java training in Bangalore

Selenium training in Chennai

Selenium training in Bangalore

jefrin said...

Your very own commitment to getting the message throughout came to be rather powerful and have consistently enabled employees just like me to arrive at their desired goals.

Data warehouse training chennai | Data warehousing training chennai

gautham said...

to become a develop in oracle database you can learn through sql certification

gautham said...

looks a great post for azure online training

gautham said...

thanks for marvelous post
cyber security online training hyderabad

dras said...

Thanks for giving this useful post..
inplant training in chennai
inplant training in chennai
inplant training in chennai for it.php
Australia hosting
mexico web hosting
moldova web hosting
albania web hosting
andorra hosting
australia web hosting
denmark web hosting

raju said...

awesome post......!
inplant training in chennai
inplant training in chennai for it.php
panama web hosting
syria hosting
services hosting
afghanistan shared web hosting
andorra web hosting
belarus web hosting
brunei darussalam hosting
inplant training in chennai

shri said...

good post...!
internship in chennai for ece students
internships in chennai for cse students 2019
Inplant training in chennai
internship for eee students
free internship in chennai
eee internship in chennai
internship for ece students in chennai
inplant training in bangalore for cse
inplant training in bangalore
ccna training in chennai


nisha said...

The Blog is very Impressive. Thank you for Put efforts and bring fruitful output for this BLog.

Data Science Training Course In Chennai | Data Science Training Course In Anna Nagar | Data Science Training Course In OMR | Data Science Training Course In Porur | Data Science Training Course In Tambaram | Data Science Training Course In Velachery

anish said...

I feel happy about and learning more about this topic. keep sharing your information regularly for my future reference. This content creates new hope and inspiration within me. Thanks for sharing an article like this. the information which you have provided is better than another blog.
Oracle Training | Online Course | Certification in chennai | Oracle Training | Online Course | Certification in bangalore | Oracle Training | Online Course | Certification in hyderabad | Oracle Training | Online Course | Certification in pune | Oracle Training | Online Course | Certification in coimbatore

aarthi said...

It is an amazing article.thank you. Java training in Chennai | Certification | Online Course Training | Java training in Bangalore | Certification | Online Course Training | Java training in Hyderabad | Certification | Online Course Training | Java training in Coimbatore | Certification | Online Course Training | Java training in Online | Certification | Online Course Training

ramesh said...

Nice. thanks for sharing this blog. every content should be very uniquely represented.

Azure Training in Chennai | Certification | Azure Online Training Course | Azure Training in Bangalore | Certification | Azure Online Training Course | Azure Training in Hyderabad | Certification | Azure Online Training Course | Azure Training in Pune | Certification | Azure Online Training Course | Azure Training | microsoft azure certification | Azure Online Training Course

Damien Grant said...

https://digitalweekday.com/
https://digitalweekday.com/
https://digitalweekday.com/
https://digitalweekday.com/
https://digitalweekday.com/
https://digitalweekday.com/
https://digitalweekday.com/
https://digitalweekday.com/

Damien Grant said...

https://digitalweekday.com/
https://digitalweekday.com/
https://digitalweekday.com/
https://digitalweekday.com/
https://digitalweekday.com/
https://digitalweekday.com/
https://digitalweekday.com/
https://digitalweekday.com/

devi said...

"It is really a great and useful piece of information. I am glad that you shared this helpful info with us. Please keep us up to date like this. Thank you for sharing.

Data Science Training In Chennai

Data Science Online Training In Chennai

Data Science Training In Bangalore

Data Science Training In Hyderabad

Data Science Training In Coimbatore

Data Science Training

Data Science Online Training

Devi said...

Thanks for sharing such a wonderful blog. oracle training in chennai

datasciencecourse said...

Really nice and interesting post. I was looking for this kind of information and enjoyed reading this one. Keep posting. Thanks for sharing.

Simple Linear Regression

Correlation vs Covariance

Tableau Training in Hyderabad said...


Nice article and thanks for sharing with us. Its very informative

Machine Learning Training in Hyderabad

Gopinath N said...

I'm very much inspired when I've visited your blog. Your blog is really informative. Hope you will continue with new article.
aws training in chennai
aws course in chennai

shreekavi said...

Wonderful post and more informative!keep sharing Like this!
DOT NET Training in Bangalore
Dot Net classes in Pune
.Net Training in Hyderabad
Dot Net Training Institute in Delhi
Dot Net Training in Gurgaon

INFYCLE TECHNOLOGIES said...

Infycle Technologies, the best software training institute in Chennai offers the No.1 Python training in Chennai for Students, tech professionals, and freshers. In addition to the Python Training Course, Infycle also offers other professional courses such as Cyber Security, Data Science, Oracle, Java, Power BI, Digital Marketing, Big Data, etc., which will be trained with 100% practical classes. After the completion of training, the trainees will be sent for placement interviews in the top MNC's. Call 7502633633 to get more info and a free demo.

Lokeswari said...

I think this is one of the best blog for me because this is really helpful for me. Thanks for sharing this valuable information

internship meaning | internship meaning in tamil | internship work from home | internship certificate format | internship for students | internship letter | Internship completion certificate | internship program | internship certificate online | internship graphic design

Ramesh Sampangi said...

Really awesome blog. Informative content and useful to my people. Thanks for sharing this blog with us.
AI Patasala Data Science Course in Hyderabad

360DigiTMG said...

Good to visit your weblog again, it has been months for me. Nicely this article that i've been waiting for so long. I will need this post to total my assignment in the college, and it has the exact same topic together with your write-up. Thanks, good share.
data science course in hyderabad

Unknown said...

You know your projects stand out of the herd. There is something special about them. It seems to me all of them are really brilliant! data science course in surat

data science said...

I was just examining through the web looking for certain information and ran over your blog.It shows how well you understand this subject. Bookmarked this page, will return for extra.

PMP Training in Malaysia said...

360DigiTMG, the top-rated organisation among the most prestigious industries around the world, is an educational destination for those looking to pursue their dreams around the globe. The company is changing careers of many people through constant improvement, 360DigiTMG provides an outstanding learning experience and distinguishes itself from the pack. 360DigiTMG is a prominent global presence by offering world-class training. Its main office is in India and subsidiaries across Malaysia, USA, East Asia, Australia, Uk, Netherlands, and the Middle East.

360DigiTMG said...

I recently came across your article and have been reading along. I want to express my admiration of your writing skill and ability to make readers read from the beginning to the end. I would like to read newer posts and to share my thoughts with you.
data science course fee in hyderabad

Anonymous said...

fon perde modelleri
Numara Onay
mobil ödeme bozdurma
nft nasıl alınır
Ankara Evden Eve Nakliyat
trafik sigortası
dedektör
web sitesi kurma
Ask Romanlari

Data Science Course In Chennai said...

traininginstitute said...

I think this is a really good article. You make this information interesting and engaging. You give readers a lot to think about and I appreciate that kind of writing.
data science training

The Blogger Worlds said...

Hotspot Shield Business Crack is a powerful VPN application that safeguards your PC's information while utilizing a shaky remote association. Hotspot Shield Cracked APK

The Blogger Worlds2 said...

Farming Simulator 22 for PC and FREE right here! Farming Simulator 22 download links are always updated and working! FS22 Crack

Post a Comment