1

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,...

Community
  • 1
  • 1
nwash57
  • 37
  • 1
  • 8

4 Answers4

1

Maybe try this?

<div class="col-md-10">
     @Html.DropDownListFor(x => model.currentSalesStage.salesStageID, (SelectList)Model.salesStages)
</div>
Lee Englestone
  • 4,545
  • 13
  • 51
  • 85
  • or
    @Html.DropDownListFor(x => model.currentSalesStage.salesStageID, new SelectList(Model.salesStages))
    – Lee Englestone Jun 09 '14 at 16:13
  • That gave me a much easier error to handle, but I still don't understand why it won't work. It tells me that the "model" in model.currentSalesStage.salesStageID doesn't exist in this context. – nwash57 Jun 09 '14 at 16:14
  • 1
    In Razor, the only time you should use a lowercase "model" is when you are declaring the type of model at the top of the view. Otherwise, you should use "Model". @nwash57 Try using a name other than model in your lambdas. See: http://stackoverflow.com/questions/7562393/how-to-set-model-attribute-in-razor-view – xDaevax Jun 09 '14 at 17:27
1

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
nwash57
  • 37
  • 1
  • 8
0

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();
TheNorthWes
  • 2,661
  • 19
  • 35
  • This solution also fixes the previous error, but gives me a compilation error that "model" does not exist in the current context for @Html.DropDownListFor(x => model... – nwash57 Jun 09 '14 at 16:35
  • You passed in `x` as the lamda name. Try something like this `model => model...` – TheNorthWes Jun 09 '14 at 16:39
  • I can't use model as the lamda name because that makes it into a dynamic operation and throws me a bunch of errors – nwash57 Jun 09 '14 at 16:44
  • It should be this: `@Html.DropDownListFor(model => model.currentSalesStage.salesStageID, Model.salesStages)` where `model => ` comes from your declaration at the top of the page `@model Yournamespace.salesStages` [Read here for more explantion](http://stackoverflow.com/questions/23293886/mvc-uppercase-model-vs-lowercase-model) – TheNorthWes Jun 09 '14 at 16:47
  • The compiler gives me "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." When I try to use model instead of x. Isn't this why in the SO thread I originally linked the answer uses x? I thought it was so the View would reference the same "x" in the "Action" ActionResult – nwash57 Jun 09 '14 at 16:55
  • I think you mean the *controller*, not the view. You cannot access drop downs progmatically like you did with web forms. That first item you pass in needs to be a string for the ID of the drop down, and the second needs to be a `SelectList`. This class can help you create those [`SelectList`](http://msdn.microsoft.com/en-us/library/dd505286(v=vs.118).aspx) lists. – TheNorthWes Jun 09 '14 at 17:04
  • So now I have `@Html.DropDownListFor(model => model.currentSalesStage.salesStageID, new SelectList(Model.salesStages, "Value", "Text"))` but using that it highlights everything using `model.` and gives the error "An expression tree may not contain a dynamic operation" My SelectList is the correct format, right? – nwash57 Jun 09 '14 at 17:17
  • Yes but I would guess you are not typing your view? Do you want that? [If not see this](http://stackoverflow.com/questions/4155392/razor-view-engine-an-expression-tree-may-not-contain-a-dynamic-operation) – TheNorthWes Jun 09 '14 at 17:19
0

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.

Kundan Singh Chouhan
  • 13,952
  • 4
  • 27
  • 32
  • This tells me that model does not exist in the current context for @Html.DropDownListFor(x => model.currentSalesStage.salesStageID... – nwash57 Jun 09 '14 at 16:25
  • The compiler gives me "Cannot impicitly convert type 'Pipeline9.Models.pipeline' to 'Pipeline9.models.MyViewModel'", won't this not work since I already told it that 'model = new MyViewModel();'? – nwash57 Jun 09 '14 at 16:48
  • This could be because you're passing in object of type Pipeline to the view but your model declaration at the top of the view page could of of type MyViewModel. What is the model declaration at the top of the view page? – Dennis R Jun 09 '14 at 16:54
  • @DennisR Well the model declaration was MyViewModel, but I've changed it back and forth in accordance with some other suggestions and it didn't seem to change much. The error above is given regardless of which model declaration I use. – nwash57 Jun 09 '14 at 16:59