我是MVC的新手,正在尝试了解视图模型。
我有Staff
,Service
,BookingSlot
,Appointments
和ApplicationUser
实体。我有以下viewmodel:
public class AppointmentBookingViewModel
{
[Display (Name ="Select Staff")]
public int StaffId { get; set; }
public IEnumerable<Staff> Staffs { get; set; }
[Display(Name = "Select Service")]
public int ServiceId { get; set; }
public IEnumerable<Service> Services { get; set; }
[Display(Name = "Select Slot")]
public int BookingSlotId { get; set; }
public IEnumerable<BookingSlot> BookingSlots { get; set; }
}
这是控制器:
public class AppointmentBookingController : Controller
{
private readonly SalonContext _context;
private AppointmentBookingViewModel _appointmentBookingViewModel = new AppointmentBookingViewModel();
public AppointmentBookingController(SalonContext context)
{
_context = context;
ConfigureViewModel(_appointmentBookingViewModel);
}
public void ConfigureViewModel(AppointmentBookingViewModel appointmentBookingViewModel)
{
appointmentBookingViewModel.Staffs = _context.Staffs;
appointmentBookingViewModel.Services = _context.Services;
appointmentBookingViewModel.BookingSlots = _context.BookingSlots;
}
// GET: AppointmentBooking
public ActionResult Index()
{
return View(_appointmentBookingViewModel);
}
}
我的问题是,如何在视图中创建表单并将数据发布到“约会”表中,以下操作不起作用。
@model HairStudio.Services.ViewModels.AppointmentBooking.AppointmentBookingViewModel
@{
ViewData["Title"] = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="row">
<div class="col-12">
<form asp-action="Create">
<div class="form-group">
<label asp-for="ServiceId" class="control-label"></label>
<select asp-for="ServiceId" class="form-control"></select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
答案 0 :(得分:0)
您已经将表单定向到具有asp-action
属性的名为“ Create” 的操作,但是控制器中没有此类操作。提交表单会发送HTTP POST请求,该请求需要由您的控制器处理。因此,请在您的Create()
中添加一个AppointmentBookingController
方法:
// POST: Create
public IActionResult Create(AppointmentBookingViewModel appointmentViewModel)
{
if (!ModelState.IsValid)
{
// Server side validation of form has failed.
// Return to the calling view and inform the user about the errors.
return View(appointmentViewModel, "Index");
}
return View(appointmentViewModel, "<NAME_OF_YOUR_CREATED_APPOINTMENT_VIEW>");
}
根据设计模式Post/Redirect/Get,在成功接受HTTP POST请求后,请考虑重定向。
另外,请查看ASP.NET Core文档中的this part,有关使用表单的信息。我相信您会在其中找到有价值的东西。
答案 1 :(得分:0)
视图模型没有什么神奇之处。这只是一堂课。这个想法是,实体类(即您通过Entity Framework持久存储到数据库中的事物)应该只与数据库的需求有关。视图可以并且经常确实有完全不同的需求集,因此您专门为此创建一个类:视图模型。这只是基本的SRP(单一职责原则):单个类不应尝试做太多事情。
然后,您只需要一种桥接两者的方法。换句话说,您需要将值从实体复制到视图模型,反之亦然。该过程称为映射,可以通过多种不同方式来实现。最常见的方法是使用第三方库,例如AutoMapper。但是,您也可以手动映射每个值,甚至可以使用类似于工厂模式的方式,在该模式下,您可以拥有另一个类,该类掌握如何进行映射的知识,并且可以从视图模型中吐出实体,反之亦然。
现在,由于我们没有您的实体,实际上不可能给您确切的指导,但您似乎想选择特定的Staff
,Service
和{{ 1}},并将其与您创建的BookingSlot
相关联。这不是很关键,但是为了提高效率,您不应在视图模型中随身携带所有这些实体的完整集合。您只需要一个Appointment
,它就可以使用效率更高的查询:
例如,代替IEnumerable<SelectListItem>
属性:
Staffs
然后:
public IEnumerable<SelectListItem> StaffOptions { get; set; }
您认为:
model.StaffOptions = await _context.Staffs.AsNoTracking()
.Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() })
.ToListAsync();