【发布时间】:2021-12-13 16:18:12
【问题描述】:
我正在尝试制作一个简单的 Todo 应用来学习 asp net core mvc。
我使用 CRUD 来管理待办事项,它运行良好。对于下一步,我想尝试向其中添加 Ajax(避免重新加载整个页面),删除工作正常,也创建,但是当我想编辑一个待办事项(基本上是一个表单)时,Ajax 请求的响应集所有待办事项的所有输入都具有相同的值。
如果我将“购买巧克力”作为一个待办事项的标题更新为“购买巧克力”,则所有其他待办事项都会有一个标题“购买巧克力”。
如果我刷新页面(或者只是包含待办事项的部分),一切都会恢复正常,这意味着数据库只更新了我想要的待办事项。
这真的很奇怪,这可能是因为输入具有相同的名称值(todo 1 title => todo.Title、todo 2 title => todo.Title 等),即使它工作正常其余的。
这是包含待办事项容器的页面:
@model IEnumerable<TodoApp.Models.Todo>
@section Css{
<link href="/css/todos.css" rel="stylesheet" />
<link href="~/lib/fontawesome/css/all.css" rel="stylesheet" />
}
@{
ViewData["Title"] = "List of todos";
}
<h1>My list of Todos</h1>
<span class="error-span" style="color:red"></span>
<div id="main_container">
<i onclick="createTodo()" id="create-button" class="fas fa-plus-circle" title="Add new todo"></i>
<div id="todos_container">
@await Html.PartialAsync("_TodoList", Model)
</div>
</div>
<partial name="_DeleteModal">
@section Scripts{
<script src="~/js/todos.js"></script>
}
这是显示所有待办事项的 foreach,也是部分视图“_TodoList”:
@model IEnumerable<TodoApp.Models.Todo>
@foreach (Todo todo in Model)
{
<form class="todo" asp-action="Edit" asp-controller="Todos" data-id="@todo.Id">
<input type="hidden" asp-for="@todo.Id" id="id_@todo.Id" />
<div class="todo-up todo-row">
<textarea autocomplete="off" placeholder="Put the title here..." class="todo-header" asp-for="@todo.Title" id="title_@todo.Id" ></textarea>
<textarea autocomplete="off" placeholder="Put the description here..." class="todo-description" asp-for="@todo.Description" id="decription_@todo.Id" ></textarea>
</div>
<div class="todo-down todo-row">
<div class="todo-validation-row">
<span></span>
<i class="fa-regular fa-check todo-edit" alt="Saved"></i>
<span class="tooltip-text">Saved</span> @*Tooltip for edition*@
</div>
<div class="todo-footer">
<div class="todo-updated"><img src="~/assets/img/update.svg" alt="Updated at" /><span>@todo.UpdatedDate</span></div>
<a onclick="showDeleteModal(@todo.Id)" title="Delete todo">
<i class="fas fa-trash"></i>
</a>
</div>
</div>
</form>
}
控制器方法的开始:
[HttpPatch]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit([Bind("Id", "Title", "Description")] Todo todo)
{
if (ModelState.IsValid)
{
var matchingTodo = await _context.Todos.FindAsync(todo.Id);
if (matchingTodo != null)
{
if (GetConnectedUserId() == matchingTodo.UserId)
{
matchingTodo.Title = todo.Title;
matchingTodo.Description = todo.Description;
matchingTodo.UpdatedDate = DateTime.Now;
_context.Update(matchingTodo);
await _context.SaveChangesAsync();
var todos = GetTodosOfConnectedUser();
var partialView = PartialView("_TodoList", todos);
return partialView;
GetTodosOfConnectedUser 方法(返回属于当前连接的用户的 Todos 的 Enumerable 对象):
private IEnumerable<Todo> GetTodosOfConnectedUser()
{
return _context.Todos.Where(t => t.UserId == Convert.ToInt32(HttpContext.User.FindFirst("user_id").Value)).OrderByDescending(t => t.UpdatedDate);
}
还有用于 Ajax 请求的 JS:
${'.todo'}.on("change", function (ev) {
let form = ev.currentTarget;
editTodo(form);
});
function editTodo(form) {
try {
$.ajax({
type: 'PATCH',
url: form.action,
data: new FormData(form),
processData: false,
contentType: false,
success: function (res) {
$(".error-span").html("");
$('#todos_container').html(res);
},
error: function (err) {
console.log(err);
$(".error-span").html("An error occured please try again.");
}
});
return false;
}
catch (ex) {
console.log(ex);
}
}
感谢您的宝贵时间
【问题讨论】:
-
我在我的 vs 中尝试了你的代码,它工作正常,你可以尝试另一个浏览器并显示更多细节。
-
遗憾的是,它在 Firefox 中也不起作用:/
-
你能提供你的
HomePage,PartialView和GetTodosOfConnectedUser()吗?顺便问一下,$('#todos_container').html(res);是什么?我没有看到任何id=todos_container。 -
我正在编辑我的帖子 :) 我没有提供这些信息,因为我真的不认为它会改变任何东西,问题可能来自名称属性的“重复”但如果它可以帮忙,我会发布它们
-
嗨,
GetTodosOfConnectedUser()中的UserId是什么?建议你把这行代码移到_context.Todos.Where(t => t.UserId == Convert.ToInt32(HttpContext.User.FindFirst("user_id").Value)).OrderByDescending(t => t.UpdatedDate);外面去调试看看返回值是什么
标签: javascript jquery ajax asp.net-core-mvc asp.net-ajax