1

I managed to populate DropDownList with value from a Database in ASP.NET MVC 5. My goal is to assing one of the dropDownList's value to a specific model, and send it back to the Database. So, if i leave the default value in the dropdownlist, the data in SQL server is null, which is Okay, but if I choose an option, I get an error : Exception thrown: 'System.InvalidOperationException' in System.Web.Mvc.dll ("There is no ViewData item of type 'IEnumerable' that has the key 'Status'."). I tried everything so far and i am opened for suggestions. Thank you !!! In Controller :

ViewBag.Status = new SelectList(db.Status, "Id", "Name");

in View

    @Html.DropDownList("Status","Select status...")

In Controller so far..

public ActionResult Index()
        {
            return View();
        }
         [HttpGet]
         public ActionResult Apply(ViewModelVM vm,int x=0)
         {
            myDb db = new myDb();
            ViewBag.SocialStatus = new SelectList(db.SocialStatuses, "Id", "StatusDescription");
            return View();
         }
        [HttpPost]
        public ActionResult Apply(ViewModelVM vm)
        {
            if (ModelState.IsValid)
            {
                using (myDb db = new myDb())
                {
                    var personalinfo = new PersonalInformation()
                    {
                        FirstName = vm.PersonalInformation.FirstName,
                        LastName = vm.PersonalInformation.LastName,
                        Birthdate = vm.PersonalInformation.Birthdate,
                        SocialStatus = vm.SocialStatus
                    };
                    ViewBag.SocialStatus = new SelectList(db.SocialStatuses, "Id", "StatusDescription");
                    db.PersonalInformations.Add(personalinfo);
                    db.SaveChanges();
                }
                return View("Success");
                }

            return View();
        }

The model:

public partial class Status
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public SocialStatus()
        {
            PersonalInformations = new HashSet<PersonalInformation>();
        }

        public int Id { get; set; }

        [StringLength(20)]
        public string StatusDescription { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<PersonalInformation> PersonalInformations { get; set; }
    }
}

The ViewModel:

 public class ViewModelVM
    {
        ...
        public Status SocialStatus { set; get; }
        ...
    }
FarCry88
  • 15
  • 5
  • Because the value of `Status` is `null` (probably because your returning the view from the POST action). –  Sep 01 '15 at 22:00
  • Yes, I do, but what is the proper solution to this problem if so ? I stuck in this problem for ages... I will highly appreciate you help :) – FarCry88 Sep 01 '15 at 22:03
  • Do you have a property in your model named `Status`? How do current populate the collection in the GET method? (you need to show the relevant code) –  Sep 01 '15 at 22:06
  • After post request you want to redirect user somewhere? If not you stay on the same form - so you need fill the ViewBag.Status again in POST action – jgasiorowski Sep 01 '15 at 22:06
  • Edit your question! (not in comments) –  Sep 01 '15 at 22:09
  • and add your POST action method – jgasiorowski Sep 01 '15 at 22:11
  • Still have the same issues.. – FarCry88 Sep 01 '15 at 22:14
  • You still have not shown your model (you don't even appear to have a property named `Status`) –  Sep 01 '15 at 22:18
  • It is SocialStatus, but I renamed it for another reason, just assume its SocialStatus istead of Status everywhere. I feel desperate .. – FarCry88 Sep 01 '15 at 22:24
  • There is no point posting the wrong code and saying it does not work! (I have edited your question). There are multiple problems with your code so I will add an answer shortly. –  Sep 01 '15 at 22:29
  • Thank you. This means a lot for me. I will be very grateful if you tell me where are these problems, without taking in mind "SocialStatus" ones. – FarCry88 Sep 01 '15 at 22:32
  • The `SocialStatus` one is critical to your problems! –  Sep 01 '15 at 22:33
  • I realize that, but i replaced on purpose for stackoverflow. In VS my code is well named, just i can't choose SocialStatus, and send it back to MSSQL. I Will wait for you to review my code. Thank you one more time – FarCry88 Sep 01 '15 at 22:42

1 Answers1

2

Firstly your using a view model so include a property in your view model for the SelectList

public IEnumerable<SelectListItem> StatusList { get; set; }

Next remove the parameter for the model from the GET method (and since you don't appear to be using the value of x, that should be removed also)

[HttpGet]
public ActionResult Apply(ViewModelVM vm,int x=0)
{
  myDb db = new myDb();
  ViewModelVM model = new ViewModelVM()
  {
    StatusList = new SelectList(db.SocialStatuses, "Id", "StatusDescription");
  };
  return View(model); // return the model to the view
}

Next, your dropdown is binding to a property named Status but your view model does not contain a property named status (its SocialStatus) and SocialStatus is a complex object and you cannot bind a <select> to a complex object (a <select> only posts back a single value (or array or values in the case of <select multiple>).

In addition, because your view model contains a property which is a complex object with validation attributes on its properties, ModelState will always be invalid because you do not post back a value for StatusDescription. As a result you always return the view in the POST method, and because you have not reassigned ViewBag.Status = ...., it is null, hence the error.

Remove property public Status SocialStatus { set; get; } and include

[Display(Name = "Social Status")]
[Required(ErrorMessage = "Please select a status")]
public int SocialStatus { get; set; }

an then in the view, strongly bind to your model using

@Html.LabelFor(m => m.SocialStatus)
@Html.DropDownListFor(m => m.SocialStatus, Model.StatusList, "-Please select-")
@Html.ValidationMessageFor(m => m.SocialStatus)

Then, in the POST method, if ModelState is invalid, populate the select list again before returning the view

if(!ModelState.IsValid)
{
  model.StatusList = new SelectList(db.SocialStatuses, "Id", "StatusDescription");
  return View(model);
}
// save and redirect

Finally, review What is ViewModel in MVC?.

Community
  • 1
  • 1