I'm learning MVC3 and building a little "to-do" website as a learning exercise, so I'm open to the idea that I'm just completely going down the wrong path!
Anyway, I have a page working perfectly with regular postbacks. I'm trying to Ajax it up with jQuery and UnobtrusiveAjax and everything still technically works correctly (the data is passed to the controller and saved in my database). The problem is that in the element I replace, each form's fields are all filled with the values that I just passed in on the one form.
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");
}
}
I have the time there just to make sure that the AJAX refresh has actually happened, and you'll see why I have the task name there twice.
This is what I see when I first load the page:
Then I check the checkbox of the the 2nd task of the 1st goal, rename it "Updated Task #2", and click the update button. That's when this happens:
Seeing how the task names NOT part of the form are all correct (ignoring the re-ordering for now), and the progress value has been updated correctly (it just takes the completed tasks and divides by the total number of tasks), I have no idea why all the form values have been replaced. Even the AddTask form has been filled in, even though I haven't changed that one to use Ajax yet. I've been searching for reasons for this for 2 days now, and have come up empty.