MVC 5 Auto refreshing partial view

Dave Gordon picture Dave Gordon · Jun 1, 2014 · Viewed 18.3k times · Source

I have a partial view which is displayed as the Footer of the site in _Layout. The controller calculates a value every second - the number of victims of computer crime.

Controller Code:

namespace EUWebRole.Controllers
{
public partial class PartialFooterStatisticsController : Controller
    {

    [OutputCache(NoStore = true, Location = OutputCacheLocation.Client, Duration = 1)]
    public ActionResult Index()
        {
        // 14 victims per second.
        // what second is it
        int hrs = DateTime.Now.Hour;
        int min = DateTime.Now.Minute;
        int sec = DateTime.Now.Second;

        int totalSeconds = sec + (min * 60) + (hrs * 3600);
        int totalVictims = totalSeconds * 14;
        ViewData["TotalVictims"] = totalVictims.ToString("N0");

        return PartialView("_PartialFooterStatistics");
        }
    }
}

The Partial view looks like this - no formatting or anything - I just want the value for now :P

@ViewData["TotalVictims"]

Finally, the _Layout section for this is here:

  @Html.Partial("_PartialFooterStatistics")

How can I get the value to display in _Layout and update each second without refreshing the whole page - I am guessing that is what the Partial view will prevent but not sure.

Sorry for such a simple question but we all start somewhere.

Thanks

UPDATE 1

Ok I am a little further forward now. The GetVictimCount is being called only once. Developer tools output

Here is my current Controller code:

 public partial class PartialFooterStatisticsController : Controller
{


    public ActionResult Index()
    {
        return PartialView("_PartialFooterStatistics");

    }

    public JsonResult GetVictimCount()
    {

        int hrs = DateTime.Now.Hour;
        int min = DateTime.Now.Minute;
        int sec = DateTime.Now.Second;

        int totalSeconds = sec + (min * 60) + (hrs * 3600);
        int totalVictims = totalSeconds * 14;

        //logic here for getting your count
        var victimCount = totalVictims;

        return Json(victimCount, JsonRequestBehavior.AllowGet);
    }

}

My Partial View code:

<script src="~/Scripts/jquery-1.10.2.js"></script>
<div id="victimCountId">
    Result
</div>


<script type="text/javascript">

var timeoutId;
$(document).ready(function () {
    timeoutId = window.setTimeout(UpdateCount, 1000);
});

function UpdateCount() {
    $.getJSON("PartialFooterStatistics/GetVictimCount", function (dataResponse) {
        var div = $('#victimCountId').html(dataResponse);

        printResult(div, item);

    });
}

function printResult(div, item) {
    div.append("Result " + item.Line1);
}
</script>

and my _Layout Code

     <footer>
        <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        @Html.Partial("_PartialFooterStatistics")
    </footer>
</div>



@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)


</body>
</html>

<script type="text/javascript">

$(function () {

    setInterval(function () { $('#_PartialFooterStatistics').load('GetVictimStatistics'); }, 1000); // every 3 sec

});

</script>

function printResult(div, item) {
    div.append("Result " + item.Line1);
}
</script>

As said the Partial view is not being called each second, and the output isn't right either... I am expecting "Result " and a number formatted like 100,000 which it is in the controller but instead all I get is 100000.

Answer

Kyle Gobel picture Kyle Gobel · Jun 1, 2014

As Jeremy West said in the comments...you will need to use javascript to make this happen.

Your MVC controller action is on the server, so that will only run when there is a request to that action.

You can make that happen with javascript (You send a request in the background).

So one solution which may work for you, is make an action that returns some JSON. One action might look like this.

public class VictimController : Controller 
{
    public JsonResult GetVictimCount()
    {
        //logic here for getting your count
        var victimCount = ...

        return JsonResult(victimCount, JsonRequestBehavior.AllowGet);
    }
}

So now that you have your logic for getting your count that continues to update, you can just call this at will with javascript. Using jquery a solution would look something like

<script type='text/javascript'>
    function updateCount() {
        $.getJSON("/Victim/GetVictimCount", function (dataResponse) {
            //dataResponse will be whatever we returned from our action
            //so now we can just populate whatever dom element we want with the value
            //for example we'll just replace all the html in the dom element with id 'victimCountId'
            $('#victimCountId').html(dataResponse);
        });
    }
</script>

Then since you want this run every second, you could use window.setTimeout

<script type="text/javascript">
    var timeoutId;
    $(document).ready(function () {
        timeoutId = window.setTimeout(updateCount, 1000);
    });
</script>

So with this solution, you will be sending requests to the server every second. I don't know exactly what you're doing on the server, or if it needs to be, but If you can move this whole solution to just javascript, that would be quicker and probably better as your server wouldn't have to handle so many requests.

Again, this is just one way get the behavior you're after.