I have an MVC 5 website that uses Entity Framework for the database interactions.
I would like to use an IEnumerable as a private variable in a controller so that other custom ActionResults in the same controller can use the same information without having to re-query each time. I don't mean the other CRUD ActionResults, but rather other custom methods that do things with the data seen on the Index page, which is usually a subset of the full database table. It would be helpful to query once, then re-use the same data.
In this example, I have private IEnumerable<CourseList> _data;
as a class-level variable and IEnumerable<CourseList> data
as an Index()-level variable. I use Debug.WriteLine
to determine if each variable is empty or not.
As I expect, within the scope of the Index() ActionResult both variables data and _data are not null. Within the scope of ClickedFromIndexPageLink(), _data -- the class-level variable is null.
My theory is that while i have sequentially loaded Index first, the controller doesn't know that. And as far as the controller is concerned, when I request _data contents in the other ActionResult, it hasn't been filled yet. However, in real time, I have clicked Index first and so should expect to see _data filled with the Index query.
To see what I do as a workaround, scroll down to see "Method B (does work, but is repetitive)".
Ts there any simple way to have an IEnumerable used as a private class variable in this manner, or is my workaround the only possible approach?
Method A (doesn't work):
Debug.WriteLine() results:
Begin Index() test *****
Is data Null? Not Null
Is _data Null? Not Null
End Index test *****
Begin ClickedFromIndexPageLink() test*****
Is _data Null? Null
End ClickedFromIndexPageLink test*****
The code:
using IenumerableAsClassVariable.Models;
using System.Collections.Generic;
using System.Data.Entity;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Web.Mvc;
namespace IenumerableAsClassVariable.Controllers
{
// This is the helper class & function used to determine if the IEnumerable is null or empty
public static class CustomHelpers
{
public static string IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
if (enumerable == null)
return "Null";
else
return "Not Null";
}
}
public class CourseListsController : Controller
{
private CreditSlipLogContext db = new CreditSlipLogContext();
private IEnumerable<CourseList> _data;
// If IEnumerable is null or empty return true; else false.
// GET: CourseLists
public ActionResult Index()
{
IEnumerable<CourseList> data = db.CourseLists.AsEnumerable();
Debug.WriteLine("-----");
Debug.WriteLine("Begin Index test *****");
Debug.WriteLine("Is data Null? " + CustomHelpers.IsNullOrEmpty(data));
_data = data;
Debug.WriteLine("Is _data Null? " + CustomHelpers.IsNullOrEmpty(_data));
Debug.WriteLine("End Index test *****");
return View(db.CourseLists.ToList());
}
public ActionResult ClickedFromIndexPageLink()
{
Debug.WriteLine("Begin ClickedFromIndexPageLink test*****");
Debug.WriteLine("Is _data Null? " + CustomHelpers.IsNullOrEmpty(_data));
Debug.WriteLine("End ClickedFromIndexPageLink test*****");
ViewBag.IsDataNull = CustomHelpers.IsNullOrEmpty(_data);
return View();
}
#region OtherCrudActionResultsAreHidden
#endregion
}
}
Method B (does work, but is repetitive):
As I expect, my results aren't null:
Begin ClickedFromIndexPageLink test*****
Is data Null? Not Null
Is _data Null? Not Null
End ClickedFromIndexPageLink test*****
This is because I re-query in the ActionResult, just as I do in the Index() ACtionResult:
public ActionResult ClickedFromIndexPageLink()
{
IEnumerable<CourseList> data = db.CourseLists.AsEnumerable();
Debug.WriteLine("Begin ClickedFromIndexPageLink test*****");
Debug.WriteLine("Is data Null? " + CustomHelpers.IsNullOrEmpty(data));
_data = data;
Debug.WriteLine("Is _data Null? " + CustomHelpers.IsNullOrEmpty(_data));
Debug.WriteLine("End ClickedFromIndexPageLink test*****");
ViewBag.IsDataNull = CustomHelpers.IsNullOrEmpty(_data);
return View();
}