views:

53

answers:

1

I am calling SSRS web services to retrieve a list of reports and each report's parameters. Since SSRS doesn't have a single web service method to get that data, I need to do it in two steps. 1) Get list of reports. 2) Loop through the list of reports and for each one, call a web service method to get its parameters.

With multiple calls to get parameters, I figured I should cache the results. My question is, which is the correct/best practice way of doing it?

Should I use attributes in my controller method? But that caches the entire output of the controller, not just specific data I want to cache. (Pseudo code)

[OutputCache(Duration=3600, VaryByParam="none")]
public ActionResult GetReportList()
{
    var rService = GetReportService();
    var reportList = rService.ListChildren(ReportsRoot, true);

    foreach (var report in reportList)
    {
        rService.GetParameters(report.Name);
    }

    return Json(result);
}

Or should I go through and manually cache only what I need using System.Web.Caching classes/method?

+1  A: 

I would not do the caching directly in the action, but rather create a class that you could call to handle the caching. Then you can decide if you want to make the cache calls in your action or create an ActionFilter to handle it.

Below is how you can handle the cache in an ActionFilter and pass it down to the action for the ones that need it.

ActionFilter.cs

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public sealed class PutStuffInCacheAttribute : ActionFilterAttribute
    {
           // Fires before the action
       public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);
                var context = filterContext.HttpContext;
                SomeData result = (SomeData)context.Cache["reports"];
                if (result == null)
                {
                    var reports = new myReportsListClass();         
                    var result = reports.GetReportsData();
                    context.Cache.Add("reports", result);
                }

                filterContext.RouteData.Values.Add("reports", result);
            }   

            //Fires after the action but before view is complete.
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            base.OnActionExecuted(filterContext);
        }       
        }

Controller.cs

[PutStuffInCache]
public ActionResult GetReportList()
{
    var result = (SomeData)this.RouteData.Values["reports"];
    return Json(result);
}
Thad
Thad, thanks for the response. Would you mind elaborating a little on your answer? Maybe with some pseudo code, specifically on the ActionFilter? I'm new to C#/.NET.
Jason