Edit model object doesn't bind to view as expected
-
07-07-2019 - |
Question
I'm using ASP.NET MVC (1.0), Spark View Engine (1.0) and SubSonic (3.0.0.3).
I'm having some trouble getting an "Edit" view to work correctly. So, in my controller, I have the following controller action that displays the edit form view:
[AcceptVerbs(HttpVerbs.Get)]
public virtual ActionResult Edit(string name)
{
var plot = Plot.SingleOrDefault(p => p.UserID == LoggedInUser.ID && p.UrlFriendlyName == name);
// ViewData["plot"] = plot;
return View(plot);
}
The form on that view posts back to the following controller action:
[AcceptVerbs(HttpVerbs.Post)]
public virtual ActionResult Edit(Plot plot)
{
var validator = new PlotValidator();
try
{
var results = validator.Validate(plot);
if (!results.IsValid)
{
...
}
}
}
The problem that I'm having, is that the first controller action doesn't actually populate the form with the values from the Plot object submitted to it. The only way I can get it to populate the form is by adding the Plot to ViewData:
ViewData["plot"] = plot;
That populates the edit form, but when I edit the values, and submit it back to the second controller action listed above, it just sends back, basically a new plot with the new values, not the plot sent to the edit form with updated values.
I'm sure I'm probably just missing something simple, but I can't seem to figure out what it is. All of the fields on my form have IDs that are prefixed with "plot."
Anyone know/see what I'm doing wrong? Thanks.
Solution
I don't know how it's done in the Spark view engine, but in the out-of-the-box view engine that comes with ASP.NET MVC, this is done by inheriting a strongly-typed view model object in the page using a page directive, rather than using the dictionary that comes with the plain-vanilla ViewPage.
So, instead of the first line of code in the view looking like this:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage" %>
It will look more like this:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<HomePageViewModel>" %>
Your current controller code is expecting a strongly-typed object, but it is getting back a ViewData Dictionary instead. So no binding is occurring.
Consider reviewing the following podcast:
Exploring how to use ViewData (Strongly typed and weak typed) with Spark http://www.dimecasts.net/Casts/CastDetails/117
OTHER TIPS
Hey Robert - I don't know how Spark handles it's data, but I can tell you that the second part is pretty simple to fix.
First - you have to remember MVC won't reach into the DB for you. In your case your criteria for pulling out a record seems to involve two criteria - so you'll have to pull that again if you want to make sure the data is set properly. So on POST change your signature to this:
[AcceptVerbs(HttpVerbs.Post)]
public virtual ActionResult Edit(string id, FormCollection form)
{
//assuming you have some kind of PK
var plot = Plot.SingleOrDefault(p => p.ID == id);
UpdateModel(plot, form.ToValueProvider());
var validator = new PlotValidator();
try
{
var results = validator.Validate(plot);
if (!results.IsValid)
{
...
}
}
}
This is freehanded - but it's how you have to do it with L2S anyway...