Tuesday, October 25, 2016

what you can and cannot do with Session and Html.RenderAction

What if this controller...

using System;
using System.Web.Mvc;
namespace Something.Controllers
{
   public class HomeController : Controller
   {
      public ActionResult Index()
      {
         Session["state"] = 0;
         return View();
      }
      
      public ActionResult Yin()
      {
         int state = Convert.ToInt32(Session["state"] as string);
         state = state - 1;
         Session["state"] = state;
         return PartialView("_Yin", state);
      }
      
      public ActionResult Yang()
      {
         int state = Convert.ToInt32(Session["state"] as string);
         state = state + 1;
         Session["state"] = state;
         return PartialView("_Yang", state);
      }
   }
}

 
 

...coughed up this action?

@{
   Layout = null;
}
<html>
   <head>
      <script type="text/javascript" src="~/Scripts/jquery-1.10.2.min.js"></script>
   </head>
   <body>
      <div>
         <button id="yinbutton">yin</button>
         <div id="yin">
            @{
               Html.RenderAction("Yin");
            }
         </div>
         <button id="yangbutton">yang</button>
         <div id="yang">
            @{
               Html.RenderAction("Yang");
            }
         </div>
      </div>
      <script type="text/javascript">
         $('#yinbutton').bind('click', function () {
            var route = '@Url.Action("Yin", "Home", new {})';
            $.ajax({
               url: route,
               type: "GET"
            }).done(function (partialViewResult) {
               $("#yin").html(partialViewResult);
            });
         });
         $('#yangbutton').bind('click', function () {
            var route = '@Url.Action("Yang", "Home", new {})';
            $.ajax({
               url: route,
               type: "GET"
            }).done(function (partialViewResult) {
               $("#yang").html(partialViewResult);
            });
         });
      </script>
   </body>
</html>

 
 

Let's also have these two partial views in the mix.

  1. _Yin.cshtml:
    @model int
    <div>Partial One: @Model.ToString()</div>
     
  2. _Yang.cshtml:
    @model int
    <div>Partial Two: @Model.ToString()</div>

 
 

I had a hunch here that state could not be communicated between partials with Session, but this is only partially true. Observe what happens when we run our code.

 
 

What is above shows what happens both when the view spins up and when either of the buttons is clicked. The buttons should increment the number kept in Session up and down, but they do nothing. However, I should stress that if nothing else, at least the zero set upfront is communicated out to the partials. It just seems the partials lack the "page lifecycle" (forgive the web forms analogy) to set something in Session. What if we use the cache instead?

using System;
using System.Runtime.Caching;
using System.Web.Mvc;
namespace Something.Controllers
{
   public class HomeController : Controller
   {
      private static ObjectCache _objectCache
      {
         get { return MemoryCache.Default; }
      }
      
      public ActionResult Index()
      {
         CacheItemPolicy cacheItemPolicy = new CacheItemPolicy();
         _objectCache.Add(new CacheItem("state", 0), cacheItemPolicy);
         return View();
      }
      
      public ActionResult Yin()
      {
         int state = Convert.ToInt32(_objectCache["state"]);
         _objectCache.Remove("state");
         state = state - 1;
         CacheItemPolicy cacheItemPolicy = new CacheItemPolicy();
         _objectCache.Add(new CacheItem("state", state), cacheItemPolicy);
         return PartialView("_Yin", state);
      }
      
      public ActionResult Yang()
      {
         int state = Convert.ToInt32(_objectCache["state"]);
         _objectCache.Remove("state");
         state = state + 1;
         CacheItemPolicy cacheItemPolicy = new CacheItemPolicy();
         _objectCache.Add(new CacheItem("state", state), cacheItemPolicy);
         return PartialView("_Yang", state);
      }
   }
}

 
 

What is below is given upon the spin up initially before any of the buttons are clicked. We can see that the original zero value may not only be communicated outward, but may also be updated!

 
 

The two buttons work too! They will move the number in the cache up and down and communicate that up to the UI by way of an AJAX refresh of some HTML.

No comments:

Post a Comment