我是一名学生,刚接触 ASP.NET Core MVC
我正在尝试创建一个预订系统,并希望通过使用某种手风琴将所有步骤都放在一页上。
我试图了解我是否能够通过使用几种不同的模型并从不同的部分视图调用 asp-actions 来实现它。
目前,如果我在 SittingTimes 的部分视图上设置模型属性,它会显示为空引用,因为必须在执行 Sitting 操作后设置 SittingTimeVM。但是如果我不设置它,它只会返回一个完整的部分视图。单独的页面。
对此我能做什么?或者我应该研究创建一页系统的不同选项?
控制器:
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);
}
包含部分视图的主视图:
@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>
母型号:
using ReservationSystemTeamD.Models.Sittings;
namespace ReservationSystemTeamD.Models
{
public class ParentModel
{
public SittingVM sittingVM { get; set; }
public SittingTimesVM sittingTimesVM { get; set; }
}
}
坐姿局部视图:
@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" />
}
坐虚拟机:
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; }
}
}
坐次虚拟机:
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; }
}
}
正如其名称所示,部分视图只是另一个视图的一部分。
在 MVC 中,您创建一个模型、一个带有操作的控制器和一个通过该操作提供服务的视图。视图现在已完全构建,它的视图模型已创建,所有内容都将提供给请求者。
就你而言,你刚刚写了
<partial name="SittingTimes"/>
表示“在当前主视图中渲染此部分,然后将其提供给请求方”。一切都通过一个控制器操作完成。
如果你想在你的部分中使用数据,你将不得不使用这样的东西:
@await Html.PartialAsync("_PartialName", model)
模型保存物体的地方。
如果您想在一个页面内使用不同的控制器操作,您将必须使用一些 AJAX 看这里。
您走在分离关注点的正确道路上,但只是对 MVC 有误解。继续学习;)
您可以尝试在
SittingOne(int restaurantId)
中创建settingTimesVM,并将ParentModel.sittingTimesVM
传递给部分视图,如下所示:
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)
};
parent.SittingTimesVM = CreateNewSittingTimesVM(parent.SittingVM);
return View(parent);
}
public Models.Sittings.SittingVM CreateNewSittingVM(int restaurantId) => new
Models.Sittings.SittingVM
{
RestaurantId = restaurantId,
SittingType = new SelectList(_context.SittingTypes, "Id", "Description")
};
public async Models.Sittings.SittingTimesVM CreateNewSittingTimesVM(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,
};
return sittimes;
}
查看:
@await Html.PartialAsync("SittingTimes", Model.sittingTimesVM)