MVC Razor同视图实现列表展示与单条编辑求助
Hey there! Let's walk through how to implement the in-view list display and edit-save functionality you need in MVC Razor. I'll break this down step by step so it's easy to follow for a beginner.
First, let's make sure your model structure is set up correctly—this is key for proper binding and updates:
// 主视图模型,包含Incident列表 public class IncidentListViewModel { public List<IncidentViewModel> IncidentListmodel { get; set; } = new List<IncidentViewModel>(); } // 单个Incident的视图模型,必须包含唯一ID用于定位更新记录 public class IncidentViewModel { public int Id { get; set; } public string Note { get; set; } // 可以添加其他需要展示/编辑的属性 }
方式一:用for循环实现基础版(简单直接)
foreach can cause issues with model binding because it iterates over a copy of the collection. Using a for loop lets MVC correctly map each item via its index:
@model IncidentListViewModel <h3>Incident Notes</h3> @* 用表单包裹,提交到UpdateInc方法 *@ @using (Html.BeginForm("UpdateInc", "Incident", FormMethod.Post)) { for (int i = 0; i < Model.IncidentListmodel.Count; i++) { <div class="incident-item mb-3"> @* 隐藏ID,用于后台定位要更新的记录 *@ @Html.HiddenFor(m => m.IncidentListmodel[i].Id) @* 文本域绑定到当前项的Note属性 *@ @Html.TextAreaFor(m => m.IncidentListmodel[i].Note, 2, 20, new { maxlength = 50, @class = "form-control" }) @* 保存按钮,携带当前记录的ID *@ <button type="submit" name="targetId" value="@Model.IncidentListmodel[i].Id" class="btn btn-sm btn-primary mt-2">Save</button> </div> <hr /> } }
方式二:用EditorTemplate实现优雅版(适合复杂模型)
If you want cleaner code, create an EditorTemplate to reuse the rendering logic for each Incident:
- Create a folder
Views/Shared/EditorTemplates, then addIncidentViewModel.cshtml:
@model IncidentViewModel <div class="incident-item mb-3"> @Html.HiddenFor(m => m.Id) @Html.TextAreaFor(m => m.Note, 2, 20, new { maxlength = 50, @class = "form-control" }) <button type="submit" name="targetId" value="@Model.Id" class="btn btn-sm btn-primary mt-2">Save</button> </div> <hr />
- Then use it in your main view:
@model IncidentListViewModel <h3>Incident Notes</h3> @using (Html.BeginForm("UpdateInc", "Incident", FormMethod.Post)) { @* MVC会自动遍历IncidentListmodel,用上面的模板渲染每个项 *@ @Html.EditorFor(m => m.IncidentListmodel) }
控制器的UpdateInc方法(处理保存逻辑)
Now let's write the backend code to handle the save request:
public class IncidentController : Controller { private readonly YourDbContext _dbContext; // 替换成你的数据库上下文 public IncidentController(YourDbContext dbContext) { _dbContext = dbContext; } [HttpPost] public async Task<IActionResult> UpdateInc(int targetId, [Bind("Id,Note")] IncidentViewModel updatedIncident) { // 从数据库找到要更新的记录 var incident = await _dbContext.Incidents.FindAsync(targetId); if (incident == null) { return NotFound("Incident not found!"); } // 更新Note属性 incident.Note = updatedIncident.Note; _dbContext.Update(incident); await _dbContext.SaveChangesAsync(); // 重新加载数据,返回原视图 var viewModel = new IncidentListViewModel { IncidentListmodel = await _dbContext.Incidents .Select(i => new IncidentViewModel { Id = i.Id, Note = i.Note }) .ToListAsync() }; return View("YourViewName", viewModel); // 替换成你的视图名称 } }
额外优化:AJAX异步保存(避免页面刷新)
If you don't want the whole page to refresh when saving, use AJAX:
Update your view's button and add script:
@model IncidentListViewModel <h3>Incident Notes</h3> @foreach (var item in Model.IncidentListmodel) { <div class="incident-item mb-3"> <textarea class="form-control note-input" data-id="@item.Id" rows="2" cols="20" maxlength="50">@item.Note</textarea> <button type="button" class="btn btn-sm btn-primary mt-2 save-btn">Save</button> </div> <hr /> } <script src="~/lib/jquery/dist/jquery.min.js"></script> <script> $(document).ready(function() { $('.save-btn').click(function() { const btn = $(this); const incidentId = btn.siblings('.note-input').data('id'); const note = btn.siblings('.note-input').val(); $.ajax({ url: '@Url.Action("UpdateInc", "Incident")', type: 'POST', data: { targetId: incidentId, note: note }, success: function(res) { alert('Saved successfully!'); }, error: function() { alert('Oops, save failed.'); } }); }); }); </script>
Then modify the controller method to return JSON:
[HttpPost] public async Task<IActionResult> UpdateInc(int targetId, string note) { try { var incident = await _dbContext.Incidents.FindAsync(targetId); if (incident == null) { return Json(new { success = false, message = "Incident not found" }); } incident.Note = note; await _dbContext.SaveChangesAsync(); return Json(new { success = true, message = "Saved!" }); } catch (Exception ex) { return Json(new { success = false, message = ex.Message }); } }
That's all! Pick the approach that fits your needs best, and feel free to tweak the styling or logic as you go.
内容的提问来源于stack exchange,提问作者uZer946

