Reputation: 4266
I am using cache on SelectListItems in my asp.net MVC app to store SelectListItems I'm using on lots of pages. The issue is that when I'm using it trough DropDownListFor, if I provide a selected value to this DropDownListFor, the SelectListItems looks to be changed... And I want to keep th SelectListItems in cache without "selected" property!
Here is the cache:
public IEnumerable<SelectListItem> GetAllPersonnelCached()
{
CacheHelper.SaveToCache("mykey", valueToCache, 240); //HttpContext.Current.Cache.Add
CacheHelper.GetFromCache<IEnumerable<SelectListItem>>("mykey"); //HttpContext.Current.Cache["mykey"]
}
This is the properties of the model I'm using
public int? personnelSelected{ get; set; }
public IEnumerable<SelectListItem> personnelList{ get; set; }
And How I fill it:
responsibleSelected = 100;
personnelList = GetAllPersonnelCached();
And here is how I am using the data on HTML part
@Html.DropDownListFor(x => x.personnelSelected, Model.personnelList, "PlaceHolder", new { data_placeholder = " " })
When I am running this code for a webpage, it works well. BUT then, when I call the GetAllPersonnelCached, it gives me all item as expected but the ListItem that has id 100 is "selecteditem". WHY? The fact that I'm using DropDownListFor makes changes on the List (referenced by the cache property in memory)? If yes, how to prevent this? Make the select list item readonly?
Thanks to all
Upvotes: 0
Views: 521
Reputation: 23274
The source code of the DropDownListFor
shows that this extension method internally sets the Selected
property.
Because a SelectListItem
is a reference type, this change occurs on the corresponding item in the cache.
One way to prevent this is to return new SelectListItem
objects from the GetAllPersonnelCached
method, instead of the original cached ones.
public IEnumerable<SelectListItem> GetAllPersonnelCached()
{
CacheHelper.SaveToCache("mykey", valueToCache, 240);
var cachedItems = CacheHelper.GetFromCache<IEnumerable<SelectListItem>>("mykey");
return cachedItems.Select(o => new SelectListItem(o.Text, o.Value);
}
You might consider not to cache the SelectListItem
instances, but the personnel-data objects instead which you transform to SelectListItem
instances on retrieval.
// Assume your PersonnelData looks like below.
class PersonnelData
{
int Id { get; set; }
string Name { get; set; }
}
public IEnumerable<SelectListItem> GetAllPersonnelCached()
{
// valueToCache is a list of PersonnelData objects.
CacheHelper.SaveToCache("mykey", valueToCache, 240);
var cachedPersonnelData = CacheHelper.GetFromCache<IEnumerable<PersonnelData>>("mykey");
return cachedPersonnelData.Select(o => new SelectListItem(o.Name, o.Id.ToString());
}
Upvotes: 2