Search code examples
c#.netasp.net-mvcdropdownlistfor

DropDownListFor not selecting value of view model field


Not sure what I'm doing wrong, but my dropdown doesn't want to select the value I want it to select. I have the following

Controller actions

// GET: /Contract/Create
public ActionResult Create()
{
    var model = new ContractViewModel();

    var authors = _authorService.GetAuthors();
    var publishers = _publisherService.GetPublishers();

    model.AuthorsList = new SelectList(authors, "AuthorID", "Name", authors.First());
    model.PublishersList = new SelectList(publishers, "PublisherID", "Name", publishers.First());

    return View(model);
}

// POST: /Contract/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ContractViewModel contractViewModel)
{
    if (ModelState.IsValid)
    {
        Contract contract = new Contract();
        contract.CanUsePublisherPartners = contractViewModel.CanUsePublisherPartners;

        contract.Author.AuthorID = Convert.ToInt32(contractViewModel.SelectedAuthorID);
        contract.Publisher.PublisherID = Convert.ToInt32(contractViewModel.SelectedPublisherID);


        var success = _contractService.AddContract(contract);
        if (success)
        {
            return RedirectToAction("Index");
        }
    }

    contractViewModel.AuthorsList = new SelectList(_authorService.GetAuthors(), "AuthorID", "Name");
    contractViewModel.PublishersList = new SelectList(_publisherService.GetPublishers(), "PublisherID", "Name");

    ViewBag.ErrorMessage = "An error occured when trying to add the Contract. A contract between this Author and Publisher may already exist! Please try again and if the problem persists, contact the Sys Admin.";
    return View(contractViewModel);
}

ViewModel

public class ContractViewModel
{
    [Display(Name = "Can the author distribute through the publisher's partners?")]
    public bool CanUsePublisherPartners { get; set; }
    [Display(Name="Author")]
    public int? SelectedAuthorID { get; set; }
    [Display(Name = "Publisher")]
    public int? SelectedPublisherID { get; set; }

    public SelectList AuthorsList { get; set; }
    public SelectList PublishersList { get; set; }

}

View binding of drop down lists

<div class="form-group">
    @Html.LabelFor(model => model.SelectedAuthorID, new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.HiddenFor(m => m.SelectedAuthorID)
        @Html.DropDownListFor(m => m.SelectedAuthorID, Model.AuthorsList)
    </div>
</div>
<div class="form-group">
    @Html.LabelFor(model => model.SelectedPublisherID, new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.HiddenFor(m => m.SelectedPublisherID)
        @Html.DropDownListFor(m => m.SelectedPublisherID, Model.PublishersList)
    </div>
</div>

What's the problem? When I submit my form, the values of SelectedAuthorID and SelectedPublisherID are the default of int - 0.

I am really at wits end here, I looked at some details trying to find out if they impact anything. E.g. some people had trouble when the Selected container property had the same name as the value property of the list items and so forth.

If anyone has any suggestions would be great to share them!


Solution

  • I believe the issue is that you have the SelectedPublisherID and SelectedAuthorID on the page twice.

    The Html.HiddenFor(m => m.SelectedAuthorID) should not be necessary alongside the DropDownListFor.

    A minor thing, general C# naming conventions use PascalCase, which means that the properties should be named SelectedAuthorId instead of ID.