(更新:我发现视图中的Model
是只读的,因此我最初的想法是无法通过ViewData填充模型属性。还有其他解决方法吗? )
我有一些CRUD功能作为局部视图。如果提交的表单无效,则无法使用不完整的数据重新显示该表单。能做到吗?
在我的项目主视图(Details.cshtml)中,我用它来显示该项目的注释:
<partial name="_notes" model="@new ProjectNotesViewModel
{
ProjectId = Model.Id,
Notes = Model.Notes,
ProjectNoteId = Model.ProjectNoteId,
ProjectNoteAction = Model.ProjectNoteAction,
ProjectCompleted = Model.Completed
}" />
这是项目的控制器方法“ Details()”:
public async Task<IActionResult> Details(int? id, int n, string a)
// n = ProjectNoteId, a = ProjectNoteAction ("c"=create, "e"=edit, "d"=delete, "v"=view (details))
{
Project project = await db.Projects
.Include(n => n.Notes)
.Include(p => p.ParentProject)
.Include(c => c.ChildProjects)
.ThenInclude(o => o.ProjectOwner)
.Include(o => o.ProjectOwner)
.FirstOrDefaultAsync(m => m.Id == id);
if (project == null) { return NotFound(); }
ProjectViewModel vm = auto.Map<ProjectViewModel>(project);
vm.ProjectNoteId = n;
vm.ProjectNoteAction = a;
vm.ProjectCompletedAction = a;
return View(vm);
}
部分“ _notes.cshtml”等同于Index.cshtml作为项目注释。
在_notes.cshtml中,我有这个:
@foreach (ProjectNoteViewModel note in Model.Notes)
{
if (note.Id == Model.ProjectNoteId)
{
// Then we want to do something to this particular note:
<tr class="alert-black-50">
<td class="align-text-top text-light rounded-left" width="1">
<span class="fas fa-clipboard fa-fw"></span>
</td>
<td class="pb-2 pr-2 text-light rounded-right">
@if (Model.ProjectNoteAction == "v") // v = view (details)
{
// View the details of the note
<partial name="_noteDetails" model="@note" />
}
@if (Model.ProjectNoteAction == "e") // = edit
{
// Edit the note
<partial name="_noteEdit" model="@note" />
}
@if (Model.ProjectNoteAction == "d") // = delete
{
// Delete the note
<partial name="_noteDelete" model="@note" />
}
</td>
</tr>
}
else
{
// Just display the date and title:
<tr>
<td colspan="2">
<a asp-action="Details"
asp-route-n="@note.Id"
asp-route-a="v">
<span class="fas fa-clipboard fa-fw"></span>
@note.Created – @note.Title
</a>
</td>
</tr>
}
}
例如,如果我们想创建一个新的项目注释,则发生这种情况(“ _noteCreate.cshtml”):
@model Projects.Models.ProjectNoteViewModel
<form asp-action="CreateNote">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="ProjectId" />
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Contents" class="control-label"></label>
<textarea asp-for="Contents" class="form-control"></textarea>
<span asp-validation-for="Contents" class="text-danger"></span>
</div>
<div class="form-group">
<a asp-action="Details" asp-route-id="@Model.ProjectId" class="btn btn-primary btn-split">
<span class="fas fas-split fa-chevron-circle-left fa-fw"></span> Cancel
</a>
<button type="submit" class="btn btn-success btn-split">
<span class="fas fas-split fa-save fa-fw"></span> Save
</button>
</div>
</form>
“ CreateNote”控制器方法:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreateNote(int projectId, [Bind("Title,Contents")] ProjectNote note)
{
Project project = await db.Projects.Where(p => p.Id == projectId).FirstOrDefaultAsync();
if (project == null)
{
return NotFound();
}
if (project.Completed)
{
// Prevent new notes from being created on completed projects.
return RedirectToAction("Details", new { id = project.Id });
}
note.ProjectId = projectId;
note.Created = DateTime.Now;
if (ModelState.IsValid)
{
db.Add(note);
await db.SaveChangesAsync();
return RedirectToAction("Details", new { id = projectId });
}
ProjectNoteViewModel vm = auto.Map<ProjectNoteViewModel>(note);
vm.Project = auto.Map<ProjectViewModel>(project);
ViewData["draft"] = vm; // Can I somehow populate the form from ViewData?
return RedirectToAction("Details", new { id = projectId });
//return View(vm); // I can't do this, because there is no "CreateNote.cshtml"
}
我不知道上面方法的最后五行。在正常的CRUD情况下,控制器方法的名称为Create()
,并且我们有一个名为“ Create.cshtml”的视图,这就是做到这一点的方法:
ProjectNoteViewModel vm = auto.Map<ProjectNoteViewModel>(note);
vm.Project = auto.Map<ProjectViewModel>(project);
return View(vm);
但是我不能return View()
,因为没有名为“ CreateNote”的视图。我需要将用户带回“ Projects / Details / 5?a = c”,其中a=c
(action = create)表示我们正在对该项目创建新的注释。而且我想带上不完整的表格数据。