4

私はMVC3を学び、学習演習として小さな「やること」のWebサイトを構築しているので、私は完全に間違った道を進んでいるという考えを受け入れています。

とにかく、私は通常のポストバックで完璧に機能するページを持っています。jQueryとUnobtrusiveAjaxを使用してAjaxを実行しようとしていますが、技術的にはすべて正しく機能します(データはコントローラーに渡され、データベースに保存されます)。問題は、私が置き換える要素では、各フォームのフィールドがすべて、1つのフォームに渡したばかりの値で埋められていることです。

Index.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回ある理由がわかります。

これは、最初にページを読み込んだときに表示されるものです。 前

次に、1番目の目標の2番目のタスクのチェックボックスをオンにして、名前を「更新されたタスク#2」に変更し、更新ボタンをクリックします。これが発生するのはそのときです。 後

フォームの一部ではないタスク名がすべて正しく(今のところ並べ替えを無視して)、進行状況の値が正しく更新されていることを確認します(完了したタスクを取得し、タスクの総数で割るだけです)。すべてのフォーム値が置き換えられた理由がわかりません。AddTaskフォームでさえ、Ajaxを使用するように変更していませんが、入力されています。私はこの理由を2日間探していましたが、空っぽになりました。

4

1 に答える 1

2

さらに検索した後、私はついに問題を発見しました。基本的に、それはModelStateがMVCで機能する方法と関係があります。このヘルプスレッドこの記事を読むことは、私のページで何が起こっているのかを理解するのに本当に役立ちました。部分ビューを返す直前にコントローラーでModelState.Clear()を呼び出すことになりましたが、このSOの質問と回答 は別のメソッドを示唆しています。

于 2012-06-06T13:37:27.857 に答える