Client side validation error for DropDownList on int field, in IE browser

Win 7 Ult, IE9. The following list is passed to the DropDownList in the view via the view bag.

List<int> test1ddl = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

      

It worked fine for a few days and then suddenly started giving up client side validation when "Field Test1 must be a number" when posted (it never reaches the POST action). It fails when I pass a list or a list. If I replace DropDownList with EditorFor POST and the update gets updated.

The only thing I did on the computer was reinstalling IIS, this happens when debugging with IIS Express.

When I restored my computer backup, the problem went away. I subsequently deployed the application to the web using this DropDownList setting and it fails with a "must be a number" error from IE 8 to XP. Chrome and FireFox work fine. It also works fine with IE9 on Win7.

I also found that I didn't even need to click Save, just clicking the browser window to take it out of focus, after selecting the DropDownList, throws a validation error. This happens with both string and int List. This also happens from IE8 on XP with a deployed web app.

I restored a Win7 failover configuration backup and then failed to debug again using IE9 in IIS Express. If I open the deployed site with IE9 in this configuration, it works fine. (I cannot test Chrome with IIS Express because in a failover configuration VS2010 will not use the default browser, only IE. This is a separate question if anyone has any idea why this is happening).

At this point, I don't think there is anything wrong with the actual code, but it looks like it is a browser issue. Since XP and IE8 are still a very common desktop setting, I need to get this to work.

My question is, why are some browsers generating validation error?

Thanks Joe

If you create a new MVC3 web application and add these files, you can recreate my ddlTestDB application.

Add this to the _Layout.cshtml menu.         <li>@Html.ActionLink("Test", "Index", "Test")</li>

*************** Controller     TestController.cs    **********
using System.Collections.Generic;
using System.Web.Mvc;
using ddltest.Models;
using ddltest.Infrastructure;

namespace ddltest.Controllers
{
  public class TestController : Controller
  {
    ddlTestDb _db = new ddlTestDb();

    public ActionResult Index()
    {
      var model = _db.Tests;
      return View(model);
    }

    public ActionResult Edit(int id)
    {
      var test = _db.Tests.FindById(id);
      //List<string> test1ddl = new List<string> { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
      List<int> test1ddl = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
      ViewBag._Test1 = test1ddl;
      return View(test);
    }

    [HttpPost]
    public ActionResult Edit(int id, FormCollection collection)
    {
      var test = _db.Tests.FindById(id);

      if (TryUpdateModel(test)) { return RedirectToAction("Index"); }

      return View(test);
    }
  }
}

********************** Class          Test.cs **************
namespace ddltest.Models
{   public class Test   {   public int Id { get; set; }     public int Test1 { get; set; }  }  }

********************** Static data  ddlTestDb.cs *****************
using System.Collections.Generic;

namespace ddltest.Models
{
  public class ddlTestDb
  {
    static ddlTestDb()
    {
        _tests = new List<Test>();
        _tests.Add(new Test { Id = 1, Test1 = 0 });
        _tests.Add(new Test { Id = 2, Test1 = 1 });
        _tests.Add(new Test { Id = 3, Test1 = 2 });
        _tests.Add(new Test { Id = 4, Test1 = 1 });
    }

    public IList<Test> Tests { get { return _tests; } }

    static List<Test> _tests;
  }
}

*********************  Extensions.cs ************
using System.Collections.Generic;
using System.Linq;
using ddltest.Models;

namespace ddltest.Infrastructure
{
  public static class TestExtensions
  {
    public static Test FindById(this IList<Test> tests, int id)
    {
      return tests.Single(t => t.Id == id);
    }
  }
}

******************  Views\Test\Edit.cshtml ****************
@model ddltest.Models.Test

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Test</legend>

        @Html.HiddenFor(model => model.Id)

        <div class="editor-label">
            @Html.LabelFor(model => model.Test1)
        </div>
        <div class="editor-field">
            @Html.DropDownList("Test1", new SelectList(ViewBag._Test1))
            @*@Html.EditorFor(model => model.Test1)*@
            @Html.ValidationMessageFor(model => model.Test1)
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

***************Views\Test\ Index.cshtml ************
@model IEnumerable<ddltest.Models.Test>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
         <th>
            Id
        </th>
        <th>
            Test1
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Id)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Test1)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
            @Html.ActionLink("Details", "Details", new { id=item.Id }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.Id })
        </td>
    </tr>
}
</table>

      

+3


source to share


1 answer


The elements <option>

have no meaning. Look at em:

<select id="Test1" name="Test1">
    <option>0</option>
    <option>1</option>
    <option>2</option>
    <option>3</option>
    <option>4</option>
    <option>5</option>
    <option>6</option>
    <option>7</option>
    <option>8</option>
    <option>9</option>
</select>

      

See the problem? None of them have a value attribute, so nothing is sent to the server, and when you try to bind anything to an integer, you get what you get: an error message.

So:

List<int> test1ddl = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
ViewBag._Test1 = test1ddl.Select(x => new SelectListItem
{
    Value = x.ToString(),
    Text = x.ToString()
});

      



and then:

@Html.DropDownList("Test1", (IEnumerable<SelectListItem>)ViewBag._Test1)

      

Take a look now:

<select id="Test1" name="Test1">
    <option value="0">0</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
    <option value="5">5</option>
    <option value="6">6</option>
    <option value="7">7</option>
    <option value="8">8</option>
    <option value="9">9</option>
</select>

      

Much better. Oh please don't use the ViewBag. Use the model view and strongly-typed version of assistants, for example Html.DropDownListFor

.

+10


source







All Articles