简体   繁体   中英

New to MVC, Populating a DropDownList from a database

I am trying to make a system where, while filling out a webform to add an entry to a database, there are dropdownlists populated from another editable database. So an admin could say, add another name to a list of employees on a payroll and then that name would be populated into the dropdownlist next time it's accessed.

I tried following a lot of other answers to questions like mine on SO, but I haven't been able to get anything to work. This is the one I think i got closest with: MVC 4 Simple Populate DropDown from database model

Using that I created a "Pipeline" object, (Name of the project I'm working on):

[Table("Entries")]
public class pipeline
{
    [Key]
    public int entryID { get; set; }
    public salesStage currentSalesStage { get; set; }
    public string Name { get; set; }

}

A "salesStage" object, (This is what I want an admin to be able to change, so they could theoretically add or delete a sales stage and an employee would see that reflected when they create a new entry into the "pipeline"):

[Table("salesStages")]
public class salesStage
{
    [Key]
    public int salesStageID { get; set; }
    [Display(Name = "Name")]
    public string Name { get; set; }
}

Then I have the ViewModel that the answer from that link outlined:

public class MyViewModel
{
    public pipeline Entry { get; set; }
    public IEnumerable<SelectListItem> salesStages { get; set; }
}

The Database context:

public class PipelineDB : DbContext
{
    public DbSet<pipeline> Entries { get; set; }
}

The ActionResult outlined in the linked answer:

public ActionResult Action(int id)
    {
        var model = new MyViewModel();
        using (var db = new PipelineDB())
        {
            model.salesStages = db.Entries.ToList().Select(x => new SelectListItem
                {
                    Value = x.currentSalesStage.ToString(),
                    Text = x.Name
                });
        }
        return View(model);
    }

And finally where I tried to integrate it into my "Create" View: @Model Pipeline9.Models.MyViewModel

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>


@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>pipeline</h4>
        <hr />
        @Html.ValidationSummary(true)

        <div class="form-group">
            @Html.LabelFor(model => model.Name, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.currentSalesStage, new { @class = "control-label col-md-2"})
            <div class="col-md-10">
                @Html.DropDownListFor(x => model.currentSalesStage.salesStageID, Model.salesStages)
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

I think the create view is where I am going wrong, because it gives me an error on that @Html.DropDownListFor. The Error is:

CS1973: 'System.Web.Mvc.HtmlHelper' has no applicable method named 'DropDownListFor' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.

Edit: So far everything has worked to a point, but the compiler keeps telling me that "model does not exist in the current context" for @Html.DropDownListFor(x => model.currentSalesStage.salesStageID,...

Maybe try this?

<div class="col-md-10">
     @Html.DropDownListFor(x => model.currentSalesStage.salesStageID, (SelectList)Model.salesStages)
</div>

When you do this: model.salesStages = db.Entries.ToList().Select(x => new SelectListItem { Value = x.currentSalesStage.ToString(), Text = x.Name });

You are setting model.salesStages to an enumerable expression. If you call ToList() after your select it should enumerate your Select(...) into a List of concrete objects.

Code:

 model.salesStages = db.Entries.ToList().Select(x => new SelectListItem
            {
                Value = x.currentSalesStage.ToString(),
                Text = x.Name
            }).ToList();

Try this instead:

@Html.DropDownListFor(x => model.currentSalesStage.salesStageID, 
    new SelectList(Model.salesStages, "Value", "Text"))

Edit

@nwash57 as per your recent comment your currentSalesStage model is null so in order to resolve it assign new instance of your pipeline class into this property in your controller and pass it to your view, eg

public ActionResult Action(int id)
{
    var model = new MyViewModel();
    using (var db = new PipelineDB())
    {
        model.salesStages = db.Entries.ToList().Select(x => new SelectListItem
            {
                Value = x.currentSalesStage.ToString(),
                Text = x.Name
            });

        model = new pipeline();
    }
    return View(model);
}

This will fix your issue.

Finally figured it out. used ViewBag to populate the dropdown.

First add the database you need to your controller:

private MyDataBase db = new MyDataBase();

Then set a ViewBag as a new SelectList in the controller:

ViewBag.MyViewBagVariable = new SelectList(db.MyDataBaseModels, "ID", "ID");

And finally, under the View use the DropDownListFor helper with your ViewBag to populate the dropdown list:

@Html.DropDownListFor(model => model.MyDataBaseValue, (SelectList)ViewBag.MyViewBagVariable

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM