Unusual behavior DropDownList MVC 5

时间:2015-09-01 21:54:38

标签: asp.net asp.net-mvc

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; }
        ...
    }

1 个答案:

答案 0 :(得分: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?.