Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP .Net MVC 5 JsonResult caching

can someone explain me how to implement caching of JsonResult actions in MVC 5 application? I want to use caching of some ajax-called actions using [OutputCache()] attribute. Some of these actions return ActionResult with html-content, some JsonResult with serialized lists of {Id, Title} pairs which I'm going to use to construct dropdown lists.

My goal is to reduce amount of DB-queries (while building ViewModels) and server requests (when using ajax-calls for it).

So, my code looks like snippets below:

[OutputCache(Duration=60*60*24)]
public async Task<ActionResult> SearchCaseOrgDialog(){
    //extract data return html page
    return View();
}

[OutputCache(Duration=60*60*24)]
public async Task<JsonResult> AjaxOrgDepartments(){
    //query database, serialize data, return json
    var result = await ctx.OrgDepartments
                          .Select(d => new { 
                                        Id = d.Id, 
                                        Title =  d.Title }
                                 )
                          .ToListAsync();

    return Json(result, JsonRequestBehavior.AllowGet);
}

When I look at FireFox tools-panel I see next picture for Html-content: FF caching html content

Here Firefox uses client-side cached version of ajax-requested page.

But situation differs with json-content: FF doesn't cache json content

It doesn't cache content, and seems to transfer data from server (server-side cache).

In both cases response headers look the same:

Cache-Control:"public, max-age=86400, s-maxage=0"

Content is requested using similar ajax-calls like

$.get(url, null, function(data){
    //do something with data
});

So, how do I cache json-content? what is the right way to do it, and why default approach does not work?

like image 620
teran Avatar asked Oct 28 '15 21:10

teran


1 Answers

If you want to avoid DB queries, you should consider caching the data at server side. You can use MemoryCache class to do that.

Quick sample

public class MyLookupDataCache
{
    const string categoryCacheKey = "CATEGORYLIST";
    public List<string> GetCategories()
    {
        var cache = MemoryCache.Default;
        var items = cache.Get(categoryCacheKey);
        if (items != null)
        {
            CacheItemPolicy policy = new CacheItemPolicy();
            policy.AbsoluteExpiration = DateTime.Now.AddDays(7); //7 days 
            //Now query from db
            List<string> newItems = repository.GetCategories();
            cache.Set(categoryCacheKey, newItems, policy);
            return newItems;
        }
        else
        {
            return (List<string>) items;
        }
    }
}

You can change the method signature to return the type you want. For simplicity, i am using List<String>

like image 78
Shyju Avatar answered Oct 16 '22 17:10

Shyju