Lesson Weekend

In the last lesson, we added read functionality to our ItemsController. In this lesson, we'll add create functionality as well.

CREATE: Updating the Create() Route


In order to add categories to our newly created items, let's update the Create() GET and POST routes and views.

Let's uncomment our current GET Create() route:

Controllers/ItemsController.cs
public ActionResult Create()
{
    ViewBag.CategoryId = new SelectList(_db.Categories, "CategoryId", "Name");
    return View();
}

We use the ViewBag to hold our categories. Let's uncomment and take a look at the corresponding view, making one small edit in the process:

Views/Items/Create.cshtml
@{
  Layout = "_Layout";
}

@model ToDoList.Models.Item

<h4>Add a new task</h4>

@using (Html.BeginForm())
{
    @Html.LabelFor(model => model.Description)
    @Html.TextBoxFor(model => model.Description)

    @Html.Label("Select category")
    @Html.DropDownList("CategoryId")

    <input type="submit" value="Add new item" class="btn btn-default" />
}
<p>@Html.ActionLink("Show all items", "Index")</p>

We've replaced our HTML LabelFor method with a simple Label method, since Item no longer has an explicitly defined Category property.

Remember that we use the HTML helper method DropDownList() to create an HTML dropdown menu consisting of a select element with nested option elements. The user will see a Category's name for each option while the actual value of the option will be the CategoryId. This is because of the SelectList we created in the controller method.

The Create() GET method and corresponding view won't actually require any more updates, so let's keep these as is. Now let's uncomment the POST route and make some changes to it:

Controllers/ItemsController.cs
[HttpPost]
public ActionResult Create(Item item, int CategoryId)
{
    _db.Items.Add(item);
    _db.SaveChanges();
    if (CategoryId != 0)
    {
        _db.CategoryItem.Add(new CategoryItem() { CategoryId = CategoryId, ItemId = item.ItemId });
        _db.SaveChanges();
    }
    return RedirectToAction("Index");
}
  • The first line of code inside the route adds the new item to the database just as we've done in the past. We must save the changes afterward, because otherwise the local item object will not have and id to enter into the join entity, otherwise.

  • Then we add a conditional to handle cases where a CategoryId doesn't get passed in to the route (such as when there are no Categories).

  • The line of code inside the if block creates the association between the newly created Item and a Category. Because the Item has been added and a new ItemId has been assigned, we can create a new CategoryItem join entity. This combines the ItemId with the CategoryId specified in the dropdown menu and passed in through our route's parameters.

  • Finally, we SaveChanges() and then redirect to a chosen action.

Repository Reference

Follow the link below to view how a sample version of the project should look at this point. Note that this is a link to a specific commit in the repository.

Example GitHub Repo for To Do List

Lesson 6 of 14
Last updated February 24, 2022