0

I'm hoping someone can help me with the below issue, which is likely very basic but I'm still learning MVC 3.0 (and coding in general).

I'm getting a Value cannot be null. Parameter name: String error within my controller when attempting to load data into my city DropDownList based on the value in the state DropDownList.

I'm hoping I'm just missing something basic. The int id = int.Parse(state_id) line within the JsonResult getCity call is throwing the error.

Here is my Controller:

public ActionResult Create()
    {
        ViewBag.sessionName = HttpContext.Session["SPCompanyName"].ToString();
        var compID = HttpContext.Session["SPCompanyAccountID"].ToString();
        ViewBag.companyID = compID;

        List<SelectListItem> list = new List<SelectListItem>();
        list.Add(new SelectListItem { Text = "Select State", Value = "Default State" });
        var states = (from c in simpleDB.simpleState select c).ToArray();
            for (int i = 0; i < states.Length; i++)
            {
                list.Add(new SelectListItem { Text = states[i].stateFull, Value = states[i].Id.ToString() });
            }
        ViewData["states"] = list;//data for DropdownList State

        List<SelectListItem> list1 = new List<SelectListItem>();
        list1.Add(new SelectListItem { Text = "Select City", Value = "Default City" });
        ViewData["cities"] = list1;//data for Dropdownlist City
        return View();

    }

    [AcceptVerbs(HttpVerbs.Get)]
    public JsonResult getCity(string state_id)
    {
        int id = int.Parse(state_id);
        var myData = (from m in simpleDB.simpleCity where m.simpleStateId == id select new { text = m.cityFull, value = m.Id });

        return this.Json(myData, JsonRequestBehavior.AllowGet);
    }

Here is the full code for my View:

@using (Html.BeginForm(FormMethod.Post))

{

<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
    $('#StateId').change(function () {
        var state_id = $(this).val(); //get State ID when select value change

        $.getJSON("/SPServiceLocation/getCity/" + state_id, {},

    function (myData) {
        var options = '';
        for (var i = 0; i < myData.length; i++) {
            options += '<option value="' + myData[i].value + '">' + myData[i].text + '</option>';
        }
        $("#CityId").html();
        $("#CityId").html(options);
    });
    });
});
</script>  

@Html.ValidationSummary(true)
<fieldset>
    <legend>Step 4: Service Areas</legend>

    @Html.HiddenFor(model => model.SPCompanyAccountID, new { @Value = ViewBag.companyID })


    <div class="editor-label">
        @Html.LabelFor(model => model.state)
    </div>
    <div class="editor-field">
        @Html.DropDownList("state", (IEnumerable<SelectListItem>)ViewData["states"], new { id = "StateId", @class = "chzn-select" })
        @Html.ValidationMessageFor(model => model.state)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.city)
    </div>

    <div class="editor-field" id="SP_SelectCity">
        @Html.DropDownList("city", (IEnumerable<SelectListItem>)ViewData["cities"], new { id = "CityId", @class = "chzn-select" })
        @Html.ValidationMessageFor(model => model.city)
    </div>

    <p>
        <input type="submit" value="Submit" />
    </p>
</fieldset>

I've looked at this Controller and View code for a few hours now, and just don't know what the issue might be. Thank you for your assistance.

Roban Kearby
  • 43
  • 1
  • 7
  • put an alert in your JS right after you set your state_id variable - alert(state_id) and ensure you are actually grabbing the value. Also if you do not have a route setup for /SPServiceLocation/getCity/StateId, you will need to use the normal method of passing the parameter (/SPServiceLocation/getCity?state_id=MD) – Tommy Jul 16 '12 at 17:48
  • go through my tutorials [1]: http://www.asp.net/mvc/tutorials/javascript/working-with-the-dropdownlist-box-and-jquery/using-the-dropdownlist-helper-with-aspnet-mvc [2]: http://blogs.msdn.com/b/rickandy/archive/2012/01/09/cascasding-dropdownlist-in-asp-net-mvc.aspx – RickAndMSFT Jul 16 '12 at 18:41

1 Answers1

0

I don't know where to start. Looking at this code I really I don't where to start. I could write libraries of books about how bad this code is. But for starters:

public JsonResult getCity(string state_id)

should be:

public JsonResult getCity(string id)

This should probably fix your error. Or maybe not. Who knows. Try.

Let me just enumerate a couple of things that strike me directly when I look at your code (and I just did a single glance at it):

  • @using (Html.BeginForm(FormMethod.Post)) - Ermmm what did you mean with this? There's no such overload. You are invoking this overload: public static MvcForm BeginForm(this HtmlHelper htmlHelper, object routeValues);. Probably you meant @using (Html.BeginForm())?
  • Returning a view without passing a model to it: return View(); and yet seemingly using a strongly typed view
  • ViewBag.XXX instead of using a view model
  • list.Add(new SelectListItem { Text = "Select State", Value = "Default State" }); instead of using the proper overload of the DropDownListFor helper allowing you to add a default value as third argument
  • A horrible hardcoded url in your javascript: $.getJSON("/SPServiceLocation/getCity/" + state_idinstead of using Url helpers
  • String concatenations to manipulate the DOM: options += '<option value="' + myData[i].value + '">' + myData[i].text + '</option>';
  • @Html.HiddenFor(model => model.SPCompanyAccountID, new { @Value = ViewBag.companyID }) doesn't do what you think it does. You cannot override the value attribute. This simply generates 2 value attributes on your hidden field: one with capital V and one with lowercase v.
  • A line of javascript code that only its author could understand what its doing: $("#CityId").html();
  • Not respected C#/.NET naming conventions for properties: model => model.state. In .NET standard conventions dictate that property names should start with a capital letter
  • ...

Yeah, basically I would start over from scratch. Here's an alternative approach that I would recommend, using view models: https://stackoverflow.com/a/4459084/29407

Community
  • 1
  • 1
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    @AdamD, ohhh I have seen much worse than that. I do lots of code reviews. I actually do code reviews for living. And believe me, this is sugar compared to what I have seen :-) – Darin Dimitrov Jul 16 '12 at 21:13
  • Let me take a look at these comments and see what I can do to fix things up. This is literally my first ASP.NET project so certainly starting over may be an option. – Roban Kearby Jul 16 '12 at 22:32
  • Can you explain why you emphasize changing "state_id" to "id" ? – Asle G Aug 27 '15 at 08:49