0

This is giving me a hard time to implement. I've generated a controller and view to handle updating a model.

However in the Create.cshtml I need to add a drop down with database users (using db.Users.Tolist()) to populate the dropdown.

<div class="form-group">
    @Html.LabelFor(model => model.UserId, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        // @Html.EditorFor(model => model.UserId, new { htmlAttributes = new { @class = "form-control" } })
        @Html.DropDownListFor(model => model.UserId, ViewData["u"] as IEnumerable<SelectListItem>)
    </div>
</div>

So I've taken @Html.EditorFor() and replaced it with @Html.DropDownListFor() to show the dropdown list. And this does work but I get an error when I click submit.

The ViewData item that has the key 'UserId' is of type 'System.String' but must be of type 'IEnumerable'.

Here's the Model.

public class pdf
{
    [Key]
    public int ID { get; set; }
    public string UserId { get; set; }
    public Guid FileGuid { get; set; }
    public string FileName { get; set; }
    public string FileLocation { get; set; }
}

And the Create controller.

public ActionResult Create()
{
    if (ModelState.IsValid)
    {
        var u = db.Users.Select(x => new { UserId = x.Id, UserName = x.UserName }).ToList();
        //u[0].UserName
        ViewBag.userinfo = new System.Web.Mvc.MultiSelectList(u, "UserId", "UserName");
        IEnumerable<SelectListItem> u1 = new SelectList(db.Users.ToList(), "Id", "UserName");
        ViewData["u"] = u1;
    }
    return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,UserId,FileGuid,FileName,FileLocation")] pdf pdf)
{
    if (ModelState.IsValid)
    {
        db.tblPDF.Add(pdf);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(pdf);
}

I feel that I'm almost there. But just need a push in the right direction to make this work.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272
Prescient
  • 1,051
  • 3
  • 17
  • 42
  • Please note that the model-view-controller tag is for questions about the pattern. There is a specific tag for the ASP.NET-MVC implementation. –  Jul 25 '16 at 23:12
  • The duplicate explains it very well: in your HttpPost action method, if you're going to render the view again, you must initialize the SelectList again. Last line of the second paragraph: _"If you return the view, you must first reassign the value of CategoryList, just as you did in the GET method"_. Also, don't add commentary about the close reasons inside your question, add a comment and `@notify` the close-voter. – CodeCaster Jul 26 '16 at 14:59

2 Answers2

1

This is how you can make your SelectListItems

ViewData["items"] = db.UserProfiles
    .Select(x => new SelectListItem() { Text = x.UserName, Value = x.UserId.ToString() });

This is how you would use it

@Html.DropDownListFor(model => model.UserId, ViewData["items"] as IEnumerable<SelectListItem>)
  • This certainly populates the list perfectly. However when clicking submit I still get. {"The ViewData item that has the key 'UserId' is of type 'System.String' but must be of type 'IEnumerable'."} could it be that I need to change something in the post in the controller? – Prescient Jul 25 '16 at 20:52
  • @Prescient You might have to create a new model just for displaying your view that has UserId as a string(a View Model, if you will). You will then have to change your Create method to conver the db model to a view model, and then change your CreatePost method to convert that back to your db model. There might also be another way that's simpler too. I don't use razor that much. – Sam I am says Reinstate Monica Jul 25 '16 at 21:04
0

I've never tried passing a selectlistitem collection directly to the page. I typically add the list to the model and then create a new selectlistitem collection with razor.

Do you have the choice to modify your model?

@Html.DropDownListFor(model => model.UserId, Model.availableUsers.Select(user => new SelectListItem() { Text = user.displayVariable, Value = user.userId, Selected = user.userId == model.UserId }).ToArray())
Broom
  • 596
  • 2
  • 18