1

I am trying to keep dropdownlist selected value if ModelState is not valid

Because i want to keep the data the user selected even if the ModelState is not valid

My code looks like this

Get Method:

  [HttpGet]
        public ActionResult Edit(int? Id)
        {
            using (var db = new NewsDatabaseEntities())
            {
                db.Configuration.LazyLoadingEnabled = false;

                var Result = (from n in db.News.Include("Categories")
                              from c in db.Categories
                              where n.NewsId == Id
                              select new { news = n, neweCategories = n.Categories, cate = c }).ToList();


                News NewsDetails = (from news in Result
                                    select new News
                                    {
                                        NewsId = news.news.NewsId,
                                        NewsTitle = news.news.NewsTitle,
                                        NewsBody = news.news.NewsBody,
                                        NewsImagePath = news.news.NewsImagePath,
                                        Categories = news.neweCategories
                                    }).FirstOrDefault();

                var AllCategories = (from c in Result
                                     select new Category
                                     {
                                         CategoryId = c.cate.CategoryId,
                                         CategoryName = c.cate.CategoryName
                                     }).ToList();



                if (NewsDetails != null)
                {

                    var model = new NewsViewModel();
                    model.NewsId = NewsDetails.NewsId;
                    model.AllCategories = AllCategories;
                    model.Categories = NewsDetails.Categories;
                    model.NewsTitle = NewsDetails.NewsTitle;
                    model.NewsBody = NewsDetails.NewsBody;
                    model.NewsImagePath = NewsDetails.NewsImagePath;





                    Session["AllCategories"] = new MultiSelectList(AllCategories, "CategoryId", "CategoryName", model.Categories.Select(J => J.CategoryId).ToArray());
                    Session["model"] = model;
                    return View(model);
                }
                else
                {
                    return RedirectToAction("Index", "Home");
                }
            }
            return View();
        }

Post Method:

        [HttpPost]
        [ValidateInput(false)]
        public ActionResult Edit(NewsViewModel model,FormCollection col)
        {



            if (!ModelState.IsValid)
            {
                model = (NewsViewModel)Session["model"];

                return View(model);
            } 

View:

     @Html.DropDownListFor(c => c.SelectedCategoriesIds, (MultiSelectList)Session["AllCategories"], new { id = "DropDownList1", multiple = "multiple", @class = "form-control" })
Lucy
  • 243
  • 1
  • 4
  • 18

1 Answers1

2

Because you are overwriting the view model object(which has the selected option value) with your session data which you set in your GET action.

You should read the selected option value to a temp variable and use that.

 [HttpPost]
 [ValidateInput(false)]
 public ActionResult Edit(NewsViewModel model,FormCollection col)
 {
    if (!ModelState.IsValid)
    {   
       var selected=  model.SelectedCategoriesIds;
       model = (NewsViewModel)Session["model"];
       model.SelectedCategoriesIds =selected;
       return View(model);
    } 
    //save and return something**strong text**
}

A better solution is not not use session here. You may simply read the values again from your db table/or cache. Also for rendering the dropdown, you may simply add a property to your view model and use that.

public class NewsViewModel
{
  public List<SelectListItem> AllCategories {set;get;}
  //Other properties
}

and in your GET action, instead of setting the categories to Session, set it to this property

public ActionResult  Edit(int? id)
{
  var vm = new NewsViewModel();

  vm.AllCategories = GetCategories();
  return View(vm);
}

private IEnumerable<SelectListItem> GetCategories()
{
   return db.Categories
            .Select(s=>new SelectListItem { Value=s.Id.ToString(), 
                                            Text=s.Name).ToList();
}

and in your view

@model NewsViewModel 
@using(Html.BeginForm())
{
     <label> Select items <label>
   @Html.ListBoxFor(s=>s.SelectedCategoriesIds,AllCategories )
   <input type="submit" />
}

Now in your HttpPost action, when model validation fails, you do not need to use session, just call the same method to re-load the AllCategories property.

if (!ModelState.IsValid)
{ 
     model.AllCategories=GetCategories();      
     return View(model);
} 
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • Thank you so much , you are always help me :) Can you please tell me how to make the Select = true in this item exist in Model.Categories ? I tried this but won't work Selected = (item == model.Categories.Select(e=>e.CategoryId) ? true : false) – Lucy Jul 21 '16 at 21:17
  • this won't working with me ....no way to make selected true of false while getting the date from database? – Lucy Jul 21 '16 at 21:29
  • What are you trying to do ? Select an item in your listbox/dropdown ? That is the way you should handle it – Shyju Jul 21 '16 at 21:30
  • private IEnumerable GetCategories() { return db.Categories .Select(s=>new SelectListItem { Value=s.Id.ToString(), Text=s.Name Selected = (item == model.Categories.Select(e=>e.CategoryId) ).ToList(); } – Lucy Jul 21 '16 at 21:39
  • Nope. I am not sure what you are trying to do. – Shyju Jul 21 '16 at 21:55
  • @Shyiu, I marketed this question is solved..thank you!... I also posted another question. here is the link http://stackoverflow.com/questions/38515155/how-to-make-selectlistitem-selected-true-or-false-on-based-on-condition – Lucy Jul 21 '16 at 22:27