MVC dropdown remembers previous selected value fro

2019-08-05 07:28发布

问题:

I have a view which has roughly 10 dropdowns, when I load this page against an ID which has no data saved against it the dropdowns have the selected value of "Please Select" which is create as im creating a new record.

When I navigate back to this view with an ID that has data saved against it, the selected values of each drop down is set by the data I pass in to the view which again is correct.

But if I then reload the page with an ID that has no data saved against it, the selected values of the drop downs are set from the previous record! I have debugged this over and over and for the ID that has no data linked it I can see its passing in NULL for the selected values for each drop downs. I'm assuming this is to do with the ModelState? So I tried the following at the beginning of my controller

ModelState.Clear();

Before the load method is called, but the issue still exists has anyone come across this? I've googled for a solution but the only things that come up are "MVC Dropdown doesn't remember the selected value" which is the opposite to the issue I have.

  • Update *

I think I have found the issue, I'm currently using how to cache objects in MVC so when I load the dropdowns from the db for the page I then store them in the cache as follows:

 if (CacheExtension.IsIncache("ListType"))
        {
            model.ListType = CacheExtension.GetFromCache<List<SelectListItem>>("ListType");
            model.ListTime = CacheExtension.GetFromCache<List<SelectListItem>>("ListDuration");
            model.ListPostageOption = CacheExtension.GetFromCache<List<SelectListItem>>("ListPostage");
            model.ListPricingType = CacheExtension.GetFromCache<List<SelectListItem>>("ListPrice");
        }
        else
        {

const string queryMultiple = @"

                                     SELECT StatusId, StatusDescription from [Status].table1

                                     SELECT StatusId, StatusDescription from [Status].table2

                                     SELECT StatusId, StatusDescription from [Status].table3

                                     SELECT StatusId, StatusDescription from [Status].table4";

        using (var sqlCon = new SqlConnection(Con.ReturnDatabaseConnection()).QueryMultiple(queryMultiple))
        {
            var duration = sqlCon.Read().ToList();
            var type = sqlCon.Read().ToList();
            var options = sqlCon.Read().ToList();
            var pricing = sqlCon.Read().ToList();

            model.ListType = new List<SelectListItem>();
            model.ListTime = new List<SelectListItem>();
            model.ListPostageOption= new List<SelectListItem>();
            model.ListPricingType = new List<SelectListItem>();

            model.ListType .AddRange(
                type.Select(
                    item => new SelectListItem { Text = item.StatusDescription, Value = item.StatusId.ToString() }));

            model.ListTime.AddRange(
                duration.Select(
                    item => new SelectListItem { Text = item.StatusDescription, Value = item.StatusId.ToString() }));

            model.ListPostageOption.AddRange(
                options.Select(
                    item => new SelectListItem { Text = item.StatusDescription, Value = item.StatusId.ToString() }));

            model.ListPricingType.AddRange(
                pricing.Select(
                    item => new SelectListItem { Text = item.StatusDescription, Value = item.StatusId.ToString() }));

            // Cache everything
            CacheExtension.SaveTocache("ListType", model.ListAdvertType, new DateTime(1));
            CacheExtension.SaveTocache("ListDuration", model.ListDuration, new DateTime(1));
            CacheExtension.SaveTocache("ListPostage", model.ListPostageOption, new DateTime(1));
            CacheExtension.SaveTocache("ListPrice", model.ListPricingType, new DateTime(1));
        }
}

and I re-load the page instead of calling the database I check the cache, if it exists I pull from there (this is where the problem is) I have just commented out the pulling from the cache and it works the dropdowns no longer remember the previous values but why?

回答1:

I know this is an old question, but as there was no concrete answer here for me when I stumbled onto this question during my own similar issue, I thought I would go ahead and put an answer in that worked for me and explains why its happening.

The best answer above is from @StephenMuecke, as his suggestion about storing the collections instead of a SelectList is spot on.

The reason is because with any form of in-memory caching, the cached objects returned are pointers to the object in cache, so any change made to the returned cache object is actually written to the cache. In my case I was storing a List<SelectListItem>. Each SelectListItem has a selected attribute, and on my cshml pages when I used that List<SelectListItem> in a DropDownListFor(...) razor statement, it would assign whatever item was selected back into the cache.

The problem would arise on the next page load for a different record, if that dropdownvalue was null, the cached list I retrieved retained the last saved selected item, and because the new item was null, it was not overwritten, thus it would show the previously selected value when it should have been null and nothing should have been selected.

To fix:

  1. Cache List<YourObjectName>, and on retrieval convert it to a List<SelectListItem>.
  2. Other options include cloning or deserializing/serializing the List<SelectListItems> from cache.
  3. Final option is don't use in-memory cache, use an out of process or distributed cache mechanism, as this will effectively serialize and deserialize the object.

Good day sirs.