复杂视图模型.视图返回一个空的视图模型.[httppost] 操作
本文关键字:视图 模型 httppost 操作 返回 复杂 一个 | 更新日期: 2023-09-27 18:32:27
我对通过 POST 接收复杂 ViewModel 的操作有问题,并且它的所有对象组件都是空的,即使我已经在 Action 中初始化了它们并使用 GET 方法将整个视图模型返回到视图。
让我解释一下情况。我有一个由三个部分组成的视图的复杂模型:Applicant
详细信息、Application
详细信息和Recordings
列表。此视图很复杂,以 (1) 让我查看我正在为其创建应用程序Applicant
的详细信息,(2) 有一个我想选择的录音列表,然后我可以添加到Application
。这是我的观点模型:
public class ApplicantApplicationRecordingsViewModel
{
// Applicant
public Applicant Applicant { get; set; }
// Application
public Application Application { get; set; }
public SelectList UsageTypeSelectList { get; private set; }
public SelectList UsageEndAppSelectList { get; private set; }
// Recordings
public IEnumerable<RecordingViewModelApp>
RecordingsViewModelApp { get; set; }
public ApplicantApplicationRecordingsViewModel()
: this(new MyDBContext())
{
}
public ApplicantApplicationRecordingsViewModel(MyDBContext dbContext)
{
PopulateUsageTypeSelectList(dbContext);
PupulateUsageEndAppSelectList(dbContext);
}
private void PopulateUsageTypeSelectList(MyDBContext dbContext,
int? usageTypeSelected = null)
{
IEnumerable<UsageType> utQuery =
dbContext.UsageTypes.OrderBy(
ut => ut.UsageTypeName).ToList();
this.UsageTypeSelectList =
new SelectList(utQuery,
"UsageTypeID",
"UsageTypeName",
usageTypeSelected);
}
private void PupulateUsageEndAppSelectList(
MyDBContext dbContext,
int? usageEndAppSelected = null)
{
IEnumerable<UsageEndApp> ueaQuery =
dbContext.UsageEndApps.OrderBy(uea => uea.UsageEndAppName).ToList();
this.UsageEndAppSelectList =
new SelectList(ueaQuery,
"UsageEndAppID",
"UsageEndAppName",
usageEndAppSelected);
}
}
在控制器中,我只是简单地填充RecordingViewModelApp
的记录列表,将申请人的详细信息放在Applicant
,并将Application
对象留空以在视图中填写。
public ActionResult Create(int? ApplicantID)
{
if (ApplicantID == null)
{
// Error 400. Bad Request Exception
}
ApplicantApplicationRecordingsViewModel viewModel = null;
using (MyDBContext dbContext = new MyDBContext())
{
Applicant applicant =
dbContext.Applicants.Find(ApplicantID);
if (applicant == null)
{
// Error 404. Http not found
}
List<RecordingViewModelApp> recordings =
getViewModel(
dbContext.Recordings.ToList(),
dbContext);
viewModel =
new ApplicantApplicationRecordingsViewModel(dbContext);
viewModel.Applicant = applicant;
viewModel.RecordingsViewModelApp = recordings;
}
return View(viewModel);
}
问题是,当我将视图模型(ApplicantApplicationRecordingsViewModel
)返回到[HttpPost] Create()
操作时,视图模型的所有组件都是空的,例如RecordingViewModelApp
列表为空。我错过了什么?我需要了解幕后发生了什么,以及为什么默认模型绑定不起作用。
[HttpPost]
[ActionName("Create")]
public ActionResult Create_post(
ApplicantApplicationRecordingsViewModel viewModelToValidate)
{
// Validation against Application only and TryToUpdate() etc.
}
干杯!
<小时 />编辑:
景观
@model Project.ApplicantApplicationRecordingsViewModel
@{
string applicantDetails = string.Format("{0} {1} {2}",
Model.Applicant.title, Model.Applicant.firstName, Model.Applicant.lastName);
ViewBag.Title = "Create a new application for " + applicantDetails;
}
<h2>@ViewBag.Title</h2>
<hr />
@using (Html.BeginForm())
{
<h3>Details of the applicant</h3>
@Html.HiddenFor(item => Model.Applicant.ApplicantID)
@Html.HiddenFor(item => Model.Application.ApplicationID)
<table>
<tr>
<th>@Html.DisplayNameFor(item => Model.Applicant.title)</th>
<th>@Html.DisplayNameFor(item => Model.Applicant.firstName)</th>
<th>@Html.DisplayNameFor(item => Model.Applicant.lastName)</th>
<th>@Html.DisplayNameFor(item => Model.Applicant.telephone)</th>
<th>@Html.DisplayNameFor(item => Model.Applicant.mobile)</th>
<th>@Html.DisplayNameFor(item => Model.Applicant.email)</th>
</tr>
<tr>
<td class="display-field">@Html.DisplayFor(item => Model.Applicant.title)</td>
<td class="display-field">@Html.DisplayFor(item => Model.Applicant.firstName)</td>
<td class="display-field">@Html.DisplayFor(item => Model.Applicant.lastName)</td>
<td class="display-field">@Html.DisplayFor(item => Model.Applicant.telephone)</td>
<td class="display-field">@Html.DisplayFor(item => Model.Applicant.mobile)</td>
<td class="display-field">@Html.DisplayFor(item => Model.Applicant.email)</td>
</tr>
</table>
<hr /> // ----------------------------------------------------------------------------------------------
<h3>Details of the application</h3>
<table id="main">
<tr>
<td>
<table>
<tr>
<td class="editor-label first-label">@Html.DisplayNameFor(item => Model.Application.ApplicationNo)</td>
<td class="editor-field">
@Html.EditorFor(item => Model.Application.ApplicationNo)
@Html.ValidationMessageFor(item => Model.Application.ApplicationNo)
</td>
</tr>
<tr>
<td class="editor-label first-label">@Html.DisplayNameFor(item => Model.Application.StartDate)</td>
<td class="editor-field">
@Html.EditorFor(item => Model.Application.StartDate)
@Html.ValidationMessageFor(item => Model.Application.StartDate)
</td>
</tr>
<tr>
<td class="editor-label first-label">@Html.DisplayNameFor(item => Model.Application.EndDate)</td>
<td class="editor-field">
@Html.EditorFor(item => Model.Application.EndDate)
@Html.ValidationMessageFor(item => Model.Application.EndDate)
</td>
</tr>
<tr>
<td class="editor-label first-label">@Html.DisplayNameFor(item => Model.Application.UsageTypeID)</td>
<td class="editor-field">
@Html.DropDownListFor(item => Model.Application.UsageTypeID, Model.UsageTypeSelectList, "-- Select Usage --")
@Html.ValidationMessageFor(item => Model.Application.UsageTypeID)
</td>
</tr>
<tr>
<td class="editor-label first-label">@Html.DisplayNameFor(item => Model.Application.UsageEndAppID)</td>
<td class="editor-field">
@Html.DropDownListFor(item => Model.Application.UsageEndAppID, Model.UsageEndAppSelectList, "-- Select Type --")
@Html.ValidationMessageFor(item => Model.Application.UsageEndAppID)
</td>
</tr>
<tr>
<td class="editor-label first-label">@Html.DisplayNameFor(item => Model.Application.linkToPaperVer)</td>
<td class="editor-field">
@Html.EditorFor(item => Model.Application.linkToPaperVer)
@Html.ValidationMessageFor(item => Model.Application.linkToPaperVer)
</td>
</tr>
</table>
</td>
<td class="editor-label">
@Html.DisplayNameFor(item => Model.Application.Info)
</td>
<td class="editor-field">
@Html.EditorFor(item => Model.Application.Info)
@Html.ValidationMessageFor(item => Model.Application.Info)
</td>
</tr>
</table>
<hr /> // ----------------------------------------------------------------------------------------------
<h3>List of recordings</h3>
Html.RenderPartial("~/Views/Recordings/_List_App.cshtml", Model.RecordingsViewModelApp);
<hr /> // ----------------------------------------------------------------------------------------------
<p>
<input type="submit" value="Create" />
</p>
}
<div>
@Html.ActionLink("Back to List", "Index", "Applicants")
</div>
<小时 />编辑 2
部分视图:
@model IEnumerable<Project.ViewModels.RecordingViewModelApp>
@if (Model != null)
{
<div>
<table class="data-in-table">
<tr>
<th>@Html.DisplayNameFor(model => model.IsSelected)</th>
<th>@Html.DisplayNameFor(model => model.FileLocation)</th>
<th>@Html.DisplayNameFor(model => model.EnteredDate)</th>
<th>@Html.DisplayNameFor(model => model.Duration)</th>
<th>@Html.DisplayNameFor(model => model.Status)</th>
</tr>
@foreach (var item in Model)
{
<tr>
<td class="display-field">@Html.EditorFor(model => item.IsSelected)</td>
<td class="display-field">@Html.DisplayFor(model => item.FileLocation)</td>
<td class="display-field">@Html.DisplayFor(model => item.EnteredDate)</td>
<td class="display-field">@Html.DisplayFor(model => item.Duration)</td>
<td class="display-field">@Html.DisplayFor(model => item.Status)</td>
</tr>
}
</table>
</div>
}
else
{
<h3>No recordings attached to this Patient</h3>
}
<小时 />编辑 3
RecordingViewModelApp
:
public class RecordingViewModel
{
public int RecordingID { get; set; }
public string FileLocation { get; set; }
public DateTime EnteredDate { get; set; }
public int Duration { get; set; }
public string Status { get; set; }
}
public class RecordingViewModelApp : RecordingViewModel
{
public bool IsSelected { get; set; }
}
首先修复视图模型。视图模型应仅包含表示要显示和/或编辑的内容的简单属性
查看模型
public class ApplicantApplicationRecordingsViewModel
{
public Applicant Applicant { get; set; }
public Application Application { get; set; }
public IEnumerable<RecordingViewModelApp> Recordings { get; set; }
public string Title { get; set; }
public SelectList UsageTypeSelectList { get; private set; }
public SelectList UsageEndAppSelectList { get; private set; }
}
控制器(注意省略验证检查)
public ActionResult Create(int ApplicantID) // assume you must have a custom route for this?
{
ApplicantApplicationRecordingsViewModel viewModel = new ApplicantApplicationRecordingsViewModel();
Applicant applicant = dbContext.Applicants.Find(ApplicantID);
viewModel.Applicant = applicant;
viewModel.Title = string.Format("Create a new application for {0} {1} {2}", applicant.title, applicant.firstName, applicant.lastName);
viewModel.Recordings = getViewModel(dbContext.Recordings.ToList(), dbContext); // not sure what this is?
viewModel.UsageTypeSelectList = new SelectList(dbContext.UsageTypes.OrderBy(ut => ut.UsageTypeName), "UsageTypeID", "UsageTypeName");
viewModel.UsageEndAppSelectList = new SelectList(dbContext.UsageEndApps.OrderBy(uea => uea.UsageEndAppName), "UsageEndAppID", "UsageEndAppName");
return View(viewModel);
}
视图
@model Project.ApplicantApplicationRecordingsViewModel
<h2>@Model.Title</h2>
@using (Html.BeginForm())
{
@Html.HiddenFor(item => Model.Applicant.ApplicantID) // include for post back but Application.ApplicationID not necessary (its a new application!)
<h3>Details of the applicant</h3>
// Add display detail for applicant, but use css for layout (position, floats etc), not tables (which are for tabular data)
<h3>Details of the application</h3>
// Add controls for Application but use LabelFor() so the label is associated with the control (otherwise its not a label)
@Html.DisplayNameFor(m => m.Application.ApplicationNo)
@Html.EditorFor(m => m.Application.ApplicationNo)
@Html.ValidationMessageFor(m => m.Application.ApplicationNo)
....
<h3>List of recordings</h3>
<table>
<thead>
.... // add table headings
</thead>
<tbody>
@Html.EditorFor(m => m.Recordings) // This uses a custom editor template to display and select recordings
</tbody>
</table>
<input type="submit" value="Create" />
}
编辑器模板 ( /Views/Shared/EditorTemplates/RecordingViewModelApp.cshtml
)
请注意,必须使用 for
循环或自定义EditorTemplate
来呈现集合。您使用的 foreach
循环仅呈现重复的id
(无效 html)和name
属性,而没有正确的索引器,因此不会回发到集合。
@model RecordingViewModelApp
<tr>
<td class="display-field">
@Html.CheckBoxFor(m => m.IsSelected) // required for postback
@Html.HiddenFor(m => m.RecordingID) // required for postback
</td>
<td class="display-field">@Html.DisplayFor(m => m.FileLocation)</td>
.... // other display properties
</tr>
开机自检方法
[HttpPost]
public ActionResult Create(ApplicantApplicationRecordingsViewModel model)
{
// model is now bound with the Applicant ID, all the properties of Application
// and the collection of Recordings with their ID and IsSelected property.
}