Reputation: 37
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,...
Upvotes: 1
Views: 3309
Reputation: 37
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
Upvotes: 1
Reputation: 14282
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, e.g.
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.
Upvotes: 0
Reputation: 2739
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();
Upvotes: 0
Reputation: 4667
Maybe try this?
<div class="col-md-10">
@Html.DropDownListFor(x => model.currentSalesStage.salesStageID, (SelectList)Model.salesStages)
</div>
Upvotes: 1