Googling generally and on SO hasn't helped me yet, so:
I am building my first MVC application from scratch, going by the MVC Music Store example but instead building a little application where arena Fighters can be created and made to Fight each other. (Fighters
and Fight
have been made linked to underlying tables through EF).
I have controllers for both the Fighters
and the Fights
. The Edit Actionresult
for Fights
is working, but for Fighters
it is not. When I hit the button to save my alterations I return to the associated Index page, but no changes have been committed. This is my question: why is this failing?
From BarracksController, with the faulty non-updating HttpPost Edit (should have been named FighterController, but neverthemind):
//
// GET: /Barracks/Edit
public ActionResult Edit(int id)
{
ViewData.Model = _FightDb.Fighters.Single(f => f.Id == id);
return View();
}
//
// POST: /Barracks/Edit
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
var fighter = _FightDb.Fighters.Single(f => f.Id == id);
try
{
UpdateModel(fighter, "Fighter");
var x = ViewData.GetModelStateErrors();
_FightDb.SaveChanges();
return RedirectToAction("Index");
}
catch
{
var viewModel = fighter;
return View(viewModel);
}
}
(As you can see, I've included the GetModelStateErrors trick from this SO question, but the result for x is null
)
This is the controller that does work, FightController:
//
// GET: /Fights/Edit
public ActionResult Edit(int id)
{
var viewModel = new FightDetailsViewModel
{
Fight = _FightDb.Fights.Single(f => f.ID == id),
Fighters = _FightDb.Fighters.ToList()
};
return View(viewModel);
}
//
// POST: /Fights/Edit
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
var fight = _FightDb.Fights.Single(f => f.ID == id);
try
{
UpdateModel(fight, "Fight");
_FightDb.SaveChanges();
return RedirectToAction("Index");
}
catch
{
var viewModel = new FightDetailsViewModel
{
Fight = _FightDb.Fights.Single(f => f.ID == id),
Fighters = _FightDb.Fighters.ToList()
};
return View(viewModel);
}
}
This is edit.aspx for the Fighters: (Edited after comment)
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Mvc3_EF_BW_Fight.Models.Fighter>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="cphMain" runat="server">
<h2>Edit</h2>
<%: Html.EditorForModel() %>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="head" runat="server">
</asp:Content>
Which uses the following Fighter.ascx in Shared:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Mvc3_EF_BW_Fight.Models.Fighter>" %>
<% using (Html.BeginForm())
{%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fighter</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Id) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Id) %>
<%: Html.ValidationMessageFor(model => model.Id) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.FighterName) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.FighterName) %>
<%: Html.ValidationMessageFor(model => model.FighterName) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.FighterStyleDescription) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.FighterStyleDescription) %>
<%: Html.ValidationMessageFor(model => model.FighterStyleDescription) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.FighterLongDescription) %>
</div>
<div class="editor-field">
<%: Html.TextAreaFor(model => model.FighterLongDescription) %>
<%: Html.ValidationMessageFor(model => model.FighterLongDescription) %>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
This is the edit.aspx for Fights
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Mvc3_EF_BW_Fight.ViewModels.FightDetailsViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="cphMain" runat="server">
<h2>Edit</h2>
<%: Html.EditorFor(model => model.Fight, new { Fighters = Model.Fighters })%>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="head" runat="server">
</asp:Content>
And this is the Fight.ascx:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Mvc3_EF_BW_Fight.Models.Fight>" %>
<% using (Html.BeginForm())
{%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.ID) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.ID) %>
<%: Html.ValidationMessageFor(model => model.ID) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.FightName) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.FightName) %>
<%: Html.ValidationMessageFor(model => model.FightName) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Fighter1ID) %><br />
<%: Html.LabelFor(model => model.Fighter1Reference.Value.FighterName)%>
</div>
<div class="editor-field">
<%: Html.DropDownList("Fighter1ID", new SelectList(ViewData["Fighters"] as IEnumerable, "ID", "FighterName", Model.Fighter1ID))%>
<%: Html.ValidationMessageFor(model => model.Fighter1ID) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Fighter2ID) %>
</div>
<div class="editor-field">
<%: Html.DropDownList("Fighter1ID", new SelectList(ViewData["Fighters"] as IEnumerable, "ID", "FighterName", Model.Fighter1ID))%>
<%: Html.ValidationMessageFor(model => model.Fighter2ID) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Fighter1Login) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Fighter1Login) %>
<%: Html.ValidationMessageFor(model => model.Fighter1Login) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Fighter2Login) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Fighter2Login) %>
<%: Html.ValidationMessageFor(model => model.Fighter2Login) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.FightStatusID) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.FightStatusID) %>
<%: Html.ValidationMessageFor(model => model.FightStatusID) %>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
And this is my viewmodel for Fights:
public class FightDetailsViewModel
{
public Fight Fight { get; set; }
public List<Fighter> Fighters { get; set; }
}
There is no ViewModel for Fighters (none that is involved in this scenario, anyway).
I can post any code you may wish to see.
Edit: I've looked at http://stackoverflow.com/questions/2160171/using-viewmodel-pattern-with-mvc-2-strongly-typed-html-helpers and http://stackoverflow.com/questions/2936927/asp-net-mvc-2-updatemodel-is-not-updating-values-in-memory-or-database , but i haven't seen a solution there yet.