asp.net Core.在一个页面中有多个部分视图.传递模型和调用动作



我是一名学生,刚开始使用MVC Asp.net。

我正在尝试创建一个预订系统,并希望有一个页面上的所有步骤,通过使用各种手风琴。

我正在试图理解我是否能够通过使用几个不同的模型和从不同的部分视图调用asp-actions来实现它。

目前,如果我在SittingTimes的部分视图上设置模型属性,它将作为空引用出现,因为SittingTimeVM必须在执行坐姿动作后设置。但是如果我不设置它,它只是返回一个完全独立的页面的部分视图。

我该怎么办呢?或者我应该寻找创建One Page系统的不同选项?

控制器:

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" />
}

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; }

}

}

分部视图,顾名思义,只是另一个视图的一部分。

在MVC中,你创建一个模型,一个带有操作的控制器和一个通过该操作提供服务的视图。视图现在已经完全构建好了,它的视图模型已经创建,所有的东西都将被提供给请求者。

在你的例子中,你只写了

<partial name="SittingTimes"/>

表示"在当前主视图中呈现该部分,然后将其提供给请求方"。

如果你想在你的部分中使用数据,你必须使用这样的东西:

@await Html.PartialAsync("_PartialName", model)

Where 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) 

最新更新