views:

949

answers:

2

I am trying to use the Html.ListBoxFor helper to show a list box and return the selected Id. Is there a problem with the dataValueField not being a string?

If the SelectList contained in the model uses integers as the dataValueField then I get a "Value cannot be null - Parameter name: Source" exception raised when the list is rendered in the view.

If the Id is changed to a string then everything works and the selected Id is passed back to the view.

Any ideas?

Here is the controller (based on a cut down new project)

namespace Mvc2.Controllers
{
    public class ViewModel
    {
        public int TestId { get; set; } // if this is a string it works ok
        public SelectList ListData {get; set;}
    }

    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            var model = new ViewModel();
            model.TestId = 1; // code corrected after Lazarus' comment

            var lst = new[] { new { Id = 1, Name = "cat" }, new { Id = 2, Name = "dog" } };
            model.ListData = new SelectList(lst, "Id", "Name");

            return View("TestView", model);
        }

        public ActionResult TestSubmit(ViewModel returnedModel)
        {
            int i = 99; // break here - returnedModel has correct TestId when declared as string
        }
    }
}

here is the View - crashes on the ListBoxFor line

<%using (Html.BeginForm("TestSubmit", "Home")) { %>

    <%=Model.TestId %><br />
    <%=Html.ListBoxFor(m => m.TestId, Model.ListData) %>

    <br />
    <input type="submit" value="Save" />

<%} %>
+1  A: 

This is a known issue with ASP.NET MVC 2. It should be fixed in the March release.

George Stocker
This bug is already fixed in RC 2.
Craig Stuntz
I got this bug about 2 nights ago and I have the newest release. (Well, RC 2). Is there a *newer* release that I'm missing?
George Stocker
No, but from your description elsewhere you're having a different issue (maybe in your code, maybe in MVC code). Also, I'm close to certain that the bug Levi describes isn't causing the behavior here. No `FormCollection` is involved (yet), and the parameter has a different name. You can look at `FormCollection.GetValue()` in the RC 2 source to confirm that the `string.IsNullOrEmpty()` is, indeed, gone.
Craig Stuntz
I just did this yesterday and saw the exact same behavior. Steve's workaround worked for me as well.
Dave Swersky
A: 

Answering my own question;

I am unconviced by the comments that this might be a bug which is waiting to be fixed because I get it in RC2 and in MVC 1 (I copied the code back to a project in that release). Anyway I have implemented a work around for now which is to:-

(a) Add a dummy string version of the Id to the model (TestId)

public class ViewModel
{
    public string TestId { get; set; } // dummy Id as a string
    public List<DataToShow> Data { get; set; }
    public SelectList ListData {get; set;}
}

(b) Display the list but retrieve the value as the dummy TestId - note that the list still dumps the data values as integers!

<%=Html.ListBoxFor(m => m.TestId, Model.ListData) %>

(c) Copy the dummy string value into its proper integer location in the action

public ActionResult TestSubmit(ViewModel returnedModel)
{
    MyModel.DataId = Int32.Parse(returnedModel.TestId);

Hope this is of some Help.

Steve Davies
What is TestId for? Are you passing and presenting multiple selects on the page?
Lazarus
I think a better solution would be make your Model.TestId property a nullable int (`int?` or `Nullable<int>`). Then in your action method you can do:`if(returnedModel.TestId.HasValue)` `MyModel.DataId = returnedModel.TestId.Value;`
Alex