I'm a student and new to working with MVC Asp.net.
I'm trying to create a booking system and would like to have all of the steps on one page, by using an accordion of sorts.
I'm trying to understand if I will be able to achieve it by using several different models and calling asp-actions from different partial views.
At the moment if i set model attribute on Partial view of SittingTimes, it comes up as null reference, as SittingTimeVM has to be set after Sitting action is performed.But if i dont set it its just returns me a partial view in a completely separate page.
What can I do about that? Or should I just look into a different options for creating One Page system?
Controller:
public async Task<IActionResult> Restaurants()
{
var company = await _context.Companies.Include(c => c.Restaurants).FirstAsync(c => c.Id == 1);
return View(company);
}
public async Task<IActionResult> SittingOne(int restaurantId)
{
var restaurant = await _context.Restaurants.FirstOrDefaultAsync(s => s.Id == restaurantId);
var parent = new Models.ParentModel
{
sittingVM = CreateNewSittingVM(restaurantId)
};
return View(parent);
}
public Models.Sittings.SittingVM CreateNewSittingVM(int restaurantId) => new
Models.Sittings.SittingVM
{
RestaurantId = restaurantId,
SittingType = new SelectList(_context.SittingTypes, "Id", "Description")
};
[HttpPost]
public async Task<IActionResult> SittingTimes(Models.Sittings.SittingVM s)
{
var allSittings = await _context.Sitings.Where(st => st.StartTime.Day ==
s.Date.Day && st.SittingTypeId == s.SittingTypeId).FirstOrDefaultAsync();
if (allSittings == null)
{
s.ErrorNumber = 1;
return RedirectToAction("ErrorNoSitting", s);
}
if (allSittings.isClosed == true)
{
s.ErrorNumber = 2;
return RedirectToAction("ErrorNoSitting", s);
}
var sittimes = new SittingTimesVM
{
SittingId = allSittings.Id,
NumberOfGuests = s.NumberOfGuests,
Date = s.Date,
RestaurantId = s.RestaurantId,
SittingsStart = allSittings.StartTime,
SittingsEnd = allSittings.EndTime,
CutOffTime = allSittings.CutOff,
};
var sitting = await _context.Sitings.FirstOrDefaultAsync(r => r.Id == sittimes.SittingId);
if (sitting.Capacity < sittimes.NumberOfGuests)
{
s.ErrorNumber = 3;
return RedirectToAction("ErrorNoSitting", s);
}
return PartialView("SittingTimes",sittimes);
}
Main View with Partial Views in it:
@model ReservationSystemTeamD.Models.ParentModel;
<div class="accordion">
<div class="accordion-item">
<h2 class="accordion-header" id="headingOne">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="false" aria-controls="collapseOne">
Choose Date
</button>
</h2>
<div id="collapseOne" class="accordion-collapse collapse show" aria-labelledby="headingOne" data-bs-parent="#accordionExample">
<div class="accordion-body">
<partial name="Sittings" model="Model.sittingVM" />
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingTwo">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
Choose Time
</button>
</h2>
<div id="collapseTwo" class="accordion-collapse collapse show" aria-labelledby="headingTwo" data-bs-parent="#accordionExample">
<div class="accordion-body" id="div2">
<partial name="SittingTimes"/>
</div>
</div>
</div>
</div>
Parent Model:
using ReservationSystemTeamD.Models.Sittings;
namespace ReservationSystemTeamD.Models
{
public class ParentModel
{
public SittingVM sittingVM { get; set; }
public SittingTimesVM sittingTimesVM { get; set; }
}
}
PartialView of Sitting:
@model ReservationSystemTeamD.Models.Sittings.SittingVM
<form asp-action="SittingTimes" method="post">
<div class="form-group row bg-info bg-gradient p-3">
<div class="col-md-4">
<label asp-for="Date" class="control-label">Choose the Date</label>
<input class="form-control" id="datefield" type="date" min="" value="" asp-for="Date" />
<span asp-validation-for="Date" style="color: red;"></span>
</div>
<div class="col-md-3">
<label asp-for="NumberOfGuests" class="control-aslabel">Number of Guests</label>
<input type="number" asp-for="NumberOfGuests" id="NumberofGuest" class="form-control" min=1 max=10 />
<span asp-validation-for="NumberOfGuests" style="color: red;"></span>
</div>
<div class="col-md-3">
<label asp-for=SittingTypeId class="control-label">Sitting Type</label>
<select asp-for=SittingTypeId asp-items=Model.SittingType type="text" class="form-select">
<option value="" data-val="true">Please Select</option>
</select>
<span asp-validation-for="SittingTypeId" style="color: red;"></span>
</div>
<div class="col-md-2 mt-4">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
<input type="hidden" asp-for=RestaurantName />
<input type="hidden" asp-for=RestaurantId />
<input type="hidden" asp-for=SittingType />
<input type="hidden" asp-for=SittingTypeId />
</form>
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
<script>
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1;
var yyyy = today.getFullYear();
if (dd < 10) {
dd = '0' + dd;
}
if (mm < 10) {
mm = '0' + mm;
}
today = yyyy + '-' + mm + '-' + dd;
document.getElementById("datefield").setAttribute("min", today).setAttribute("value", today);
</script>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
SittingVM:
using Microsoft.AspNetCore.Mvc.Rendering;
using System.ComponentModel.DataAnnotations;
namespace ReservationSystemTeamD.Models.Sittings
{
public class SittingVM
{
[Required(ErrorMessage = "Please enter a date")]
[DataType(DataType.Date)]
public DateTime Date { get; set; }
public int RestaurantId { get; set; }
public string RestaurantName { get; set; }
public int NumberOfGuests { get; set; }
public int? SittingTypeId { get; set; }
public SelectList SittingType { get; set; }
public List<SittingTimesVM>? SittingTimes { get; set; }
public int ErrorNumber { get; set; }
}
}
SittingTimesVM:
using System.ComponentModel.DataAnnotations;
namespace ReservationSystemTeamD.Models.Sittings
{
public class SittingTimesVM
{
public int SittingId { get; set; }
public int SittingTypeId { get; set; }
public DateTime Date { get; set; }
public int RestaurantId { get; set; }
public int NumberOfGuests { get; set; }
[DataType(DataType.Time)]
[DisplayFormat(DataFormatString = "{0:HH:mm tt}")]
public DateTime ChosenTime { get; set; }
public DateTime SittingsStart { get; set; }
public DateTime SittingsEnd { get; set; }
public int CutOffTime { get; set; }
public string Email { get; set; }
}
}