Select dropdown list doesn't save selected option - asp.net core web app
I'm trying to save data on a table but for some reason the Select element of Html always saves the first DateTime option item instead of saving the one I selected.
Here I select the option corresponding to the date highlighted but when I save the information the first option (22-01-08) is the one that it´s saved on the database table
My View Model:
public class BookNowViewModel
{
public string FilmeName { get; set; }
public DateTime FilmeDate { get; set; }
public string seatNum { get; set; }
public int Price { get; set; }
public int FilmeId { get; set; }
}
My Controller where i set the functions do save the data retrieved from the view to the "Cart" table:
[HttpGet]
public IActionResult BookNow(int Id)
{
BookNowViewModel vm = new BookNowViewModel();
var item = _context.Filme.Where(a => a.Id == Id).FirstOrDefault();
var it = _context.Sessao.Where(n => n.FilmeId == Id).FirstOrDefault();
vm.FilmeName = item.Name;
vm.FilmeDate = it.Date;
vm.FilmeId = Id;
vm.Price = Convert.ToInt32(item.Price);
ViewBag.FilmeDate = _context.Sessao.Where(a => a.FilmeId == Id)
.Select(i => new SelectListItem
{
Value = i.Id.ToString(),
Text = i.Date.ToString()
}).ToList();
return View(vm);
}
[HttpPost]
public async Task<IActionResult> BookNow(BookNowViewModel vm,int Id)
{
List<Cart> carts = new List<Cart>();
string seatNum = vm.seatNum.ToString();
int filmeId = vm.FilmeId;
var filme = _context.Filme.Where(a => a.Id == Id).FirstOrDefault();
var sessao = _context.Sessao.Where(n => n.FilmeId == Id).FirstOrDefault();
string[] seatNumArray = seatNum.Split(",");
count = seatNumArray.Length;
if (checkSeat(seatNum, filmeId) == false)
{
foreach (var item in seatNumArray)
{
carts.Add(new Cart
{
Price = Convert.ToInt32(filme.Price),
MovieId = vm.FilmeId,
UserId = _userManager.GetUserId(HttpContext.User),
Date = sessao.Date,
seatNum = item
});;
}
foreach (var item in carts)
{
_context.Cart.Add(item);
await _context.SaveChangesAsync();
//_context.SaveChanges();
}
TempData["Sucess"] = "Seat Booked, See your Cart";
}
else
{
TempData["seatnummsg"] = "Please Change you seat number";
}
return RedirectToAction("Index");
}
My View :
div class="col-md-4">
<form asp-action="BookNow" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="FilmeName" class="control-label"></label>
@Model.FilmeName
<span asp-validation-for="FilmeName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="FilmeDate" class="control-label"></label>
<select name="ok" id="FilmeDate" asp-for="FilmeDate" class="form-control" asp-items="ViewBag.FilmeDate"></select>
</div>
<div class="form-group">
<label asp-for="seatNum" class="control-label"></label>
<input asp-for="seatNum" class="form-control" />
<span asp-validation-for="seatNum" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="FilmeId" class="control-label"></label>
<input asp-for="FilmeId" class="form-control" />
<span asp-validation-for="FilmeId" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Add to Cart" class="btn btn-default btn-success text-white" />
</div>
</form>
Solution 1:
I can see a couple of issues here.
The <select>
element has the wrong name
attribute. You can remove name="ok"
(and the id) as the tag-helper asp-for
will automatically set the name
and id
attributes. It should correctly bind to the FilmeDate
property if you change it to:
<select asp-for="FilmeDate" class="form-control" asp-items="ViewBag.FilmeDate"></select>
You're populating the ViewBag with dates, but you're assigning the value to the Id
not the Date. Use the date in the value field too:
...
.Select(i => new SelectListItem
{
Value = i.Date.ToString(),
Text = i.Date.ToString()
}
However, another problem is that you're not using the value from the viewmodel when saving to the database. It looks like you're saving a value which you just read from the database: Date = sessao.Date
. You should use the value from the ViewModel: Date = vm.FilmeDate
.
...
// only 1 for loop required
foreach (var item in seatNumArray)
{
var cart = new Cart
{
Price = Convert.ToInt32(filme.Price),
MovieId = vm.FilmeId,
UserId = _userManager.GetUserId(HttpContext.User),
Date = vm.FilmeDate, // use the value selected the viewmodel
seatNum = item
};
_context.Cart.Add(cart);
}
// save changes after adding all items
await _context.SaveChangesAsync();
You only need a single loop and you can save changes after adding all items too. Since you're no longer using sessao
in the Post method it can be removed.
Aside: if you're checking for seat availability for a particular film in checkSeat(seatNum, filmeId)
, you may also need to consider the film date too.