Search code examples
c#htmlasp.net-mvcrazorasp.net-core-6.0

Replace text field with a dropdown menu in ASP.NET Core MVC Application


I am working through the "Get Started with ASP.NET Core MVC" tutorial at the link below:

https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/start-mvc?view=aspnetcore-6.0&tabs=visual-studio

On the "Create New" page, where the user can enter a new movie into the database...

Create New page

...the "Rating" field is a text field where the user can enter a string of length five. I'd like to change that to a dropdown menu with the following options to choose from: G, PG, PG-13, R.

How would I go about doing this?

I believe the C# code for the dropdown would look something like this:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
     
public IActionResult Index()
{
     List<SelectRating> rating = new()
     {
                new SelectRating { Value = "1", Text = "G" },
                new SelectRating { Value = "2", Text = "PG" },
                new SelectRating { Value = "3", Text = "PG-13" },
                new SelectRating { Value = "4", Text = "R" }
            };

            ViewRating.ratings = ratings;
            return View();
}

But I'm not sure where this code would go, and I'm not sure what View file I should edit. Would it be Index.cshtml in the directory /Views/Movies?

/Views/Movies/Index.cshtml

@model MovieDBApp.Models.MovieGenreViewModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-action="Create">Create New</a>
</p>

<form asp-controller="Movies" asp-action="Index" method = "get">
    <p>
        <select asp-for="MovieGenre" asp-items="Model.Genres"> 
            <option value="">All</option> 
        </select> 

        Title: <input type="text" name="SearchString">
        <input type="submit" value="Filter" />
    </p>
</form>

<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Movies[0].Title)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Movies[0].ReleaseDate)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Movies[0].Genre)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Movies[0].Rating)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Movies[0].Runtime)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model.Movies) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Title)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.ReleaseDate)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Genre)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Rating)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Runtime)
            </td>
            <td>
                <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
                <a asp-action="Details" asp-route-id="@item.Id">Details</a> |
                <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
            </td>
        </tr>
}
    </tbody>
</table>


Solution

  • You should not put it on the Index page, because the Index is to display the data. You should change the Rating field to dropdown menu on the Creat page and Edit page.

    Below is my test code,you can refer to it:

    Controller:

    public class MoviesController : Controller
    {
         List<SelectListItem> rating = new()
         {
              new SelectListItem { Value = "G", Text = "G" },
              new SelectListItem { Value = "PG", Text = "PG" },
              new SelectListItem { Value = "PG-13", Text = "PG-13" },
              new SelectListItem { Value = "R", Text = "R" }
         };
         public IActionResult Create()
         {
              ViewBag.ratings = rating;
              return View();
         }
         [HttpPost]
         [ValidateAntiForgeryToken]
         public async Task<IActionResult> Create([Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
         {
              if (ModelState.IsValid)
              {
                    _context.Add(movie);
                    await _context.SaveChangesAsync();
                    return RedirectToAction(nameof(Index));
              }
              return View(movie);
         }
         public async Task<IActionResult> Edit(int? id)
         {
              ViewBag.ratings = rating;
              if (id == null || _context.Movie == null)
              {
                  return NotFound();
              }
    
              var movie = await _context.Movie.FindAsync(id);
              if (movie == null)
              {
                  return NotFound();
              }
              return View(movie);
         }
         [HttpPost]
         [ValidateAntiForgeryToken]
         public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
         {
              if (id != movie.Id)
              {
                  return NotFound();
              }
              if (ModelState.IsValid)
              {
                  try
                  {
                      _context.Update(movie);
                      await _context.SaveChangesAsync();
                  }
                  catch (DbUpdateConcurrencyException)
                  {
                      if (!MovieExists(movie.Id))
                      {
                          return NotFound();
                      }
                      else
                      {
                          throw;
                      }
                  }
                  return RedirectToAction(nameof(Index));
              }
              return View(movie);
         }
    }
    

    Creat.cshtml:

    @model _2022071801.Models.Movie
    
    @{
        ViewData["Title"] = "Create";
    }
    
    <h1>Create</h1>
    
    <h4>Movie</h4>
    <hr />
    <div class="row">
        <div class="col-md-4">
            <form asp-action="Create">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <div class="form-group">
                    <label asp-for="Title" class="control-label"></label>
                    <input asp-for="Title" class="form-control" />
                    <span asp-validation-for="Title" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="ReleaseDate" class="control-label"></label>
                    <input asp-for="ReleaseDate" class="form-control" />
                    <span asp-validation-for="ReleaseDate" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Genre" class="control-label"></label>
                    <input asp-for="Genre" class="form-control" />
                    <span asp-validation-for="Genre" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Price" class="control-label"></label>
                    <input asp-for="Price" class="form-control" />
                    <span asp-validation-for="Price" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Rating" class="control-label"></label>
                    <select asp-for="Rating" asp-items="@(new SelectList(ViewBag.ratings,"Value","Text"))" >
                        <option>Please select one</option>
                    </select>
                    <span asp-validation-for="Rating" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <input type="submit" value="Create" class="btn btn-primary" />
                </div>
            </form>
        </div>
    </div>
    
    <div>
        <a asp-action="Index">Back to List</a>
    </div>
    
    @section Scripts {
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    }
    

    Edit.cshtml:

    @model _2022071801.Models.Movie
    
    @{
        ViewData["Title"] = "Edit";
    }
    
    <h1>Edit</h1>
    
    <h4>Movie</h4>
    <hr />
    <div class="row">
        <div class="col-md-4">
            <form asp-action="Edit">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <input type="hidden" asp-for="Id" />
                <div class="form-group">
                    <label asp-for="Title" class="control-label"></label>
                    <input asp-for="Title" class="form-control" />
                    <span asp-validation-for="Title" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="ReleaseDate" class="control-label"></label>
                    <input asp-for="ReleaseDate" class="form-control" />
                    <span asp-validation-for="ReleaseDate" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Genre" class="control-label"></label>
                    <input asp-for="Genre" class="form-control" />
                    <span asp-validation-for="Genre" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Price" class="control-label"></label>
                    <input asp-for="Price" class="form-control" />
                    <span asp-validation-for="Price" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Rating" class="control-label"></label>
                    <select asp-for="Rating" asp-items="@(new SelectList(ViewBag.ratings,"Value","Text"))" >
                        <option>Please select one</option>
                    </select>
                    <span asp-validation-for="Rating" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <input type="submit" value="Save" class="btn btn-primary" />
                </div>
            </form>
        </div>
    </div>
    
    <div>
        <a asp-action="Index">Back to List</a>
    </div>
    
    @section Scripts {
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    }
    

    Model:

    public class Movie
    {
         public int Id { get; set; }
         public string? Title { get; set; }
    
         [Display(Name = "Release Date")]
         [DataType(DataType.Date)]
         public DateTime ReleaseDate { get; set; }
         public string? Genre { get; set; }
         [Column(TypeName = "decimal(18, 2)")]
         public decimal Price { get; set; }
         public string? Rating { get; set; }      
    }
    

    Test Result: enter image description here enter image description here