MVC3 - 部分视图中的多个 Ajax 表单在刷新时都填充了相同的数据

Posted

技术标签:

【中文标题】MVC3 - 部分视图中的多个 Ajax 表单在刷新时都填充了相同的数据【英文标题】:MVC3 - Multiple Ajax forms in a partial view are all filled with the same data on refresh 【发布时间】:2012-06-09 03:10:40 【问题描述】:

我正在学习 MVC3 并构建一个小的“待办事项”网站作为学习练习,所以我对我完全走错路的想法持开放态度!

无论如何,我有一个页面可以完美地处理常规回发。我正在尝试使用 jQuery 和 UnobtrusiveAjax 对其进行 Ajax 处理,并且一切在技术上仍然正常工作(数据被传递到控制器并保存在我的数据库中)。问题是在我替换的元素中,每个表单的字段都填充了我刚刚在一个表单上传递的值。

索引.cshtml

@model WebUI.Models.HomeViewModel

@
    ViewBag.Title = "Index";
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>


<h2>My Goals</h2>
...snip...
<div id="goal_div">
@foreach (var goal in Model.Goals)

    Html.RenderPartial("GoalDetail", goal);

</div>

GoalDetail.cshtml

@model Domain.Entities.Goal
<div class="goal" id='goal_id@(Model.ID)'>
    <h4>@Model.Name</h4>
    <p>@DateTime.Now.ToString()</p>
    <p class="goal_description">@Model.Progress % complete</p>
    <ul>
        @foreach (var task in Model.Tasks)
        
            using (Ajax.BeginForm("UpdateTask", "Home", new AjaxOptions  UpdateTargetId = "goal_id" + Model.ID ))
            
                @Html.HiddenFor(g => g.ID)
                @Html.Hidden("TaskID", task.ID)
                <li class="task">
                    @Html.CheckBox("IsComplete", task.IsComplete) 
                    @Html.TextBox("TaskName", task.Name)
                    @task.Name
                    <input class="actionButtons" type="submit" value="Update task" />
                </li>
            
        
        <li>
        @using (Html.BeginForm("AddTask", "Home"))
        
            @Html.HiddenFor(g => g.ID)
            @Html.Editor("TaskName")
            <input class="actionButtons" type="submit" value="Add task" />
        
        </li>
    </ul>
</div>

HomeController.cs

public class HomeController : Controller

    private IGoalRepository Repository;

    public HomeController(IGoalRepository repo)
    
        Repository = repo;
    

    public ViewResult Index()
    
        HomeViewModel viewModel = new HomeViewModel();
        viewModel.Goals = Repository.Goals;
        return View(viewModel);
    

    public ActionResult AddTask(int ID, string TaskName)
    
        bool success = Repository.SaveTask(ID, 0, TaskName, DateTime.Today, false);
        return RedirectToAction("Index");
    

    public ActionResult UpdateTask(int ID, int TaskID, bool IsComplete, string TaskName)
    
        bool success = Repository.SaveTask(ID, TaskID, TaskName, DateTime.Today, IsComplete);
        Goal updatedGoal = Repository.Goals.FirstOrDefault(g => g.ID == ID);
        return PartialView("GoalDetail", updatedGoal);
    

    public ActionResult AddGoal(string Name, DateTime Enddate)
    
        bool success = Repository.SaveGoal(0, Name, DateTime.Today, Enddate);
        return RedirectToAction("Index");
    

    public ActionResult UpdateGoal(int GoalID, string Name, DateTime Enddate)
    
        bool success = Repository.SaveGoal(GoalID, Name, DateTime.Today, Enddate);
        return RedirectToAction("Index");
    

我有时间只是为了确保 AJAX 刷新确实发生了,你会明白为什么我有两次任务名称。

这是我第一次加载页面时看到的:

然后我选中第一个目标的第二个任务的复选框,将其重命名为“更新任务#2”,然后单击更新按钮。这就是发生这种情况的时候:

查看不属于表单的任务名称如何全部正确(暂时忽略重新排序),并且进度值已正确更新(它只取已完成的任务并除以任务总数) ,我不知道为什么所有的表单值都被替换了。甚至 AddTask 表单也已填写,尽管我还没有更改该表单以使用 Ajax。我已经搜索了 2 天的原因,但结果是空的。

【问题讨论】:

我对此进行了更多研究,似乎大多数使用 MVC 和 Ajax 的示例都返回 JSON 对象而不是部分视图。今天下班后我会尝试这样做,看看是否会有所作为。 【参考方案1】:

经过更多的搜索,我终于发现了这个问题。基本上,它与 ModelState 在 MVC 中的工作方式有关。阅读this help thread 和this article 确实帮助我了解我的页面发生了什么。在返回部分视图之前,我最终在我的控制器中调用了 ModelState.Clear(),但是 this SO question and answer 建议另一种方法。

【讨论】:

我有/遇到过类似的问题,ModelState.Clear() 是唯一似乎有效的方法,虽然不是很好,但确实有效。如果您之前检查过模型状态是否有效,则可以正常工作,但如果模型状态无效,我可以看到此解决方案会遇到更多问题。

以上是关于MVC3 - 部分视图中的多个 Ajax 表单在刷新时都填充了相同的数据的主要内容,如果未能解决你的问题,请参考以下文章

带有 Razor 的 MVC3 - 避免在部分视图上定义多个 javascript 函数

MVC 3 Razor Form Post w/ 多个强类型的部分视图不绑定

在ajax请求期间处理MVC表单身份验证到期[重复]

具有多个模型的 MVC3 视图

在MVC3中,同一个页面有3个按钮是要用ajax异步刷新的,不想用@html.ActionLink,@html.BeginForm()的话,不行

一个 Django 视图和 url,多个应用程序