0

I am using Entity Framework and MVC with Individual User Accounts and I have a table called "Kit" that has a UserId column which is linked to the AspNetUser 'ID' as the foreign key.

When I go to create a new kit and save to the database I want the 'UserId' of my Kit table to be the current ASPNetUser that is logged in.

But currently when I create the new Kit object it just sets the UserId to NULL and never picks up the current user logged in.

What am I missing here?

Controller Create()

[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Admin")]
public ActionResult Create([Bind(Include = "KitId,KitName,ProductId,UserId")] Kit kit)
{
    if (ModelState.IsValid)
    {
        db.Kits.Add(kit);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    ViewBag.ProductId = new SelectList(db.Products, "ProductId", "ProductName", kit.ProductId);
    ViewBag.UserId = new SelectList(db.AspNetUsers, "Id", "Email", kit.UserId);
    return View(kit);
}

View

<div class="form-group">
    @Html.LabelFor(model => model.AspNetUser.Id, "User", htmlAttributes: new { @class = "control-label col-md-2"})
    <div class="col-md-10">
        @Html.EditorFor(model => model.UserId, "Email", new { htmlAttributes = new { @class = "form-control", @disabled = "disabled" } })
    </div>
</div>

Here is the row in my database and you can see UserId was never populated

KitId   KitName ProductId   Available   LoanId  UserId
 3      TestKit    12         NULL       NULL    NULL
Tim
  • 952
  • 3
  • 12
  • 31
  • Ok, so no way to have it displayed in an @Html.EditFor that the user can't edit? That's the only reason I disabled the field. Thank you by the way, that's helpful. – Tim Jan 07 '18 at 03:39
  • Makes sense. But this is good to know for other views. How would I set it before saving to the database. I have "kit.UserId =" right before db.SaveChanges(); but I am not sure what value I am setting to UserId. I thought it would be AspNetUser.Id but I get "An object reference is required for the non-static field, method, or property 'AspNetUser.Id'" – Tim Jan 07 '18 at 03:48
  • Worked perfectly! Thank you very much. – Tim Jan 07 '18 at 04:04

1 Answers1

2

Disabled controls do not submit a value, so the value of UserId in the POST method will be null (the default for the property - although its unclear why you have made it nullable). While you could make the input readonly (using new { @readonly = "readonly" }), the correct approach is to set the value of the property in the POST method immediately before saving the record to prevent malicious users posting back invalid data and discovering the ID's of other users.

if (ModelState.IsValid)
{
    kit.UserId = User.Identity.GetUserId(); // assumes your using Identity
    db.Kits.Add(kit);
    ...

At the very least, your [Bind] attribute should exclude KitId and UserId properties, however the preferred method, especially when editing data, is to use a view model containing only those properties you need in the view, and that view model will also include IEnumerable<SelectListItem> properties from you dropdownlists rather than using ViewBag. Refer What is ViewModel in MVC?.

As a side note, your naming your SelectList the same as the property your binding to which will not work correctly (refer Can the ViewBag name be the same as the Model property name in a DropDownList? for a detailed explanation), and there is no point setting the Selected property using the 4th parameter of the SelectList constructor (its ignored when binding to a model property)