1

I have a script that renders a partial view after its data is loaded, but I want at least one other partial view to load using the same data. It's a long-running query (30sec - 1min), so I don't want to load it for each partial view. Or am I going down the wrong path? It should be noted I'm still pretty new to ASP.Net and very new to Javascript/Jquery, so I'm not totally aware of best practices, so if you spot something that's "against convention", please let me know that, too.

EDIT: It dawned on me I should note what I'm trying to eventually get to. In my current non-ASP app (C#/XAML), it loads the data (with an equivalent of LoadMonitorData method, below) when the app loads, then refreshes every 15 minutes. Or the refresh can be triggered by a Refresh button.

Here's what I've got so far...any help or guidance would be greatly appreciated.

Index.cshtml

@{
    ViewBag.Title = "MMCView";
}

@section scripts {
    <script type="text/javascript">
        $(document).on('click', '[name^=project]', function () {
            if ($(this).hasClass('selected')) {
                $('.mig-project').removeClass('selected').removeClass('low-opacity').addClass('full-opacity');
                $('#data-area').removeClass('show-data-view');
            }
            else {
                $(this).addClass("selected").addClass('full-opacity').removeClass('low-opacity');
                $('.mig-project').not(this).removeClass("full-opacity").removeClass('selected').addClass("low-opacity");
                $('#data-area').load($(this).data("url"));
                $('#data-area').addClass('show-data-view');
            }
        })
    </script>

    <script type="text/javascript">
        $(document).ready(function(e) {
            $("#list-container").each(function(index, item) {
                var url = $(item).data("url");
                if (url && url.length > 0) {
                    $(item).load(url);
                }
            })
        })
    </script>
}

<div class="project-list slow-load" id="list-container" data-url="/mmc/projectpanes">
    <img src="loading.gif" />
</div>

<div class="hide-data-view slow-load" id="data-area" data-url="/mmc/projectdata"></div>

MMCController.cs

using MMC_ASP.Models;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.Web.Script.Serialization;

namespace MMC_ASP.Controllers
{
    public class MMCController : AsyncController
    {
        MonitorData downloadedInfo = new MonitorData();

        //GET: MMC
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult ProjectPanes()
        {
            downloadedInfo = LoadMonitorData();
            return PartialView("_ProjectPanes", downloadedInfo.MainPanel.OrderBy(o => o.Client).ToList());
        }

        public ActionResult ProjectData(string server)
        {
            return PartialView("_ProjectData", downloadedInfo.Information.Where(x => x.ServerName == server).ToList());
        }

        public ActionResult MainWindowMonitor()
        {
            return PartialView("_MainWindowMonitor", downloadedInfo.MonitorText);
        }

        public MonitorData LoadMonitorData()
        {
            MonitorData deserializedData = null;
            using (WebClient wc = new WebClient())
            {
                wc.Encoding = Encoding.Unicode;
                string location = "http://MYWEBAPI-RETURNS-JSON";
                string data = wc.DownloadString(new System.Uri(location));
                var deserializer = new JavaScriptSerializer();
                deserializedData = deserializer.Deserialize<MonitorData>(data);
            }
            return deserializedData;
        }
    }
}
4
  • Since the data result is the same and each action simply filters it, why not load all partials and simply hide or collapse them? If not, you could add an api layer in front of MYWEBAPI-RETURNS-JSON that caches the data for a period of time. Then call that api instead and let it manage freshness. Commented Mar 17, 2017 at 18:36
  • When you say, "load all partials and simply hide or collapse them", I suppose I'm not following you. It's the loading part that's getting me...the hiding/collapsing I pretty much have down through CSS/JS. It's getting the data into the downloadedInfo variable that I'm having trouble with. And the caching idea is a very good one...I may look at implementing that at some point. I'll add a point of clarification to my post. Commented Mar 17, 2017 at 19:19
  • Perhaps I'm confused as well. Are you able to get the data from the api or is that the issue? Commented Mar 17, 2017 at 19:25
  • Heh...API data loads fine. I'm trying to figure out the best way to load the data, then access parts of it from different partial views. Commented Mar 17, 2017 at 22:19

2 Answers 2

1

In this situation, the Cache object might be useful to you. You can store your data in the Cache, set it to expire after a reasonable amount of time, write a helper function to re-pull the data on the fly if the cached data has expired, and have your partial views pull their data from the helper function. This way, the new data will only be pulled as needed, regardless how many views are using it, and as a bonus you have easy control over how often to re-execute that expensive query.

Note that this works well in your situation because your data is global in nature. If you were passing user-specific parameters into your query, then Cache wouldn't be a good fit.

using System.Web.Caching;

private MonitorData getCachedData()
{
  var cache = this.HttpContext.Cache;

  if (cache["MonitorData"] == null)
    cache.Add("MonitorData", LoadMonitorData(), null, DateTime.Now.AddMinutes(15), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); // 15 minute cache expiration, as example
  return (MonitorData)cache["MonitorData"];
}

public ActionResult ProjectPanes()
{
    downloadedInfo = getCachedData();
    return PartialView("_ProjectPanes", downloadedInfo.MainPanel.OrderBy(o => o.Client).ToList());
}

public ActionResult ProjectData(string server)
{
    downloadedInfo = getCachedData();
    return PartialView("_ProjectData", downloadedInfo.Information.Where(x => x.ServerName == server).ToList());
}

public ActionResult MainWindowMonitor()
{
    downloadedInfo = getCachedData();
    return PartialView("_MainWindowMonitor", downloadedInfo.MonitorText);
}
Sign up to request clarification or add additional context in comments.

7 Comments

That's a cool idea, and definitely something I'm interested in. However, your example code doesn't work. Were you just tossing off a quick example? If so, could you refer me to some reference for how to implement this? Thanks for the help!
Also, where and how would I implement getCachedData?
This was just a quick example of how you could modify your existing action methods, not a fully-tested-and-compiling example. In my example getCachedData would just be another method in your controller.
Sorry, I thought that the Controller base class contained a Cache property you could use to get a reference to the current request's Cache instance, but I was wrong. Instead, you can get the reference to the existing Cache object using this.HttpContext.Cache - I edited my example above to show this. You shouldn't need to ever actually instantiate a new Cache() object yourself, it should be there for you automatically.
I also fixed my "cache.Add" line where I had left out a couple of required parameters
|
0

The solution that Joe_Irby proposed works great! However, while communicating with him I found another approach that works as well. I figured I'd include it here so anyone else looking for a solution can decide which one will be best for their situation.

https://code.msdn.microsoft.com/Caching-In-Web-API-cb40be30

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.