views:

190

answers:

2

ASP.NET MVC Model Binding is still new to me and I'm trying to understand exactly how it works. Right now, I appear to be having problems with a feature of Html.Textbox()

Specifically, I have a View where I set Html.Textbox to a value both in the "Get" and the "Post". It sets fine in the "Get", but after the user submits a value during the "Post", I have the class change one of the values internally based on the other value submitted.

(I'm basically validating one value based on the other... I'm not sure if this is the right way to do this...)

Tracing through, I can see that the value has actually changed as expected both in the Model and in the View, but when it displays on my screen after the "Post", the value does not display as it was changed. Instead it is what it was set to originally.

Here's my simplified example:

The View shows a:

  • Drop-down with items from a SelectList (pre-selected as "Other")
  • a Read-only Text Box (with a pre-loaded value of 0)
  • Submit Button

User should pick a new value from the Drop-Down and click submit. The "Post" method in the controller picks up the new value from the Drop-Down and changes the Value in the Read-only text-box and re-displays.

(Yes, I'll eventually be doing this with JQuery, too...)

Here's my sample Model class:

public class SampleSubmission
{
    public string Name { get; set; }
    public int Volume { get; set; }
    public readonly SortedList<string, int> NameVolumeList = new SortedList<string, int>();
    // Standard Constructor
    public SampleSubmission()
    {
        NameVolumeList.Add("Sample1", 10);
        NameVolumeList.Add("Sample2", 20);
        NameVolumeList.Add("Sample3", 50);
        NameVolumeList.Add("Other", 0);
        this.Name = NameVolumeList.Keys[0];
        this.Volume = NameVolumeList[Name];
    }
    // Copy Constructor
    public SampleSubmission(SampleSubmission samSub) : this()
    {
        this.Name = samSub.Name;
        this.Volume = NameVolumeList[Name];
    }
}

Here's the Controller:

public class SampleSubmissionController : Controller
{
    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Index()
    {
        SampleSubmission sampleSub = new SampleSubmission();
        return View(sampleSub);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Index(SampleSubmission sampleSub)
    {
        SampleSubmission samSub = new SampleSubmission(sampleSub);
        return View(samSub);
    }
}

Here's the View:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
Inherits="System.Web.Mvc.ViewPage<MvcModelBindTest.Models.SampleSubmission>" %>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm()) {  %>
<%= Html.DropDownList("Name", new SelectList(Model.NameVolumeList.Keys.ToList())) %>
<%= Html.TextBox("Volume",Model.Volume) %>
<input type="submit" name="pick" id="pick" value="Pick" /> <% } %>
</asp:Content>

Any ideas as to why the new value does not display?

EDIT:

In order to fix the problem, I read the link given by "jfar" and made a 1-line change.

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Index(SampleSubmission sampleSub)
    {
        SampleSubmission samSub = new SampleSubmission(sampleSub);
        // Reset Model Value
        ModelState.SetModelValue("Volume", new ValueProviderResult(
           samSub.Volume, "", System.Globalization.CultureInfo.CurrentCulture));
        return View(samSub);
    }

This definitely works. Unfortunately, this feels like a gross hack to me. What if I had to update the values of multiple fields? There must be a better (simpler?) way of doing this.

EDIT2: Found my answer. See below...

+1  A: 

From: http://stackoverflow.com/questions/3444994/how-to-clear-textboxes-defined-with-mvc-html-helpers

"The HTMLHelper's first look at the ModelState and ViewData to see if any values match their key and then finally use whatever value you provide them.

If you need to reset the textboxe's value you also need to clear the ModelState entry with the matching key. Another alternative is redirecting to the same page instead of simply rendering a view via javascript or with MVC.

jfar
@jfar probably he want to show new values instead of clearing it.
TheVillageIdiot
Yes, new values -- that's exactly what I want to do. I read the link and the answers that the user "Cynthia" gave. I fixed the issue and noted it above, but I don't like how it happens. It feels like a hack.
Pretzel
@TheVillageIdiot, well right, the concept is the same though. @Pretzel you probably take advantage of this feature when preserving state. Its pretty easy to write your own HTML helpers too. Pretty sure there are existing libraries you could google too.
jfar
A: 

I figured out the answer to my own question when I stumbled upon another variable that needed to be reset. As I was looking at the data structure, I realized what I wanted was the pristine state where there were no Keys in the ModelState.

        ModelState.Remove(key);

Where "key" is the value you're trying to reset.

Pretzel