简体   繁体   中英

Passing data to a controller with $.ajax (MVC 4)

I have the following editor template:

DropDownListEditorTemplate

@model DropDownListViewModel

<script type="text/javascript">
    $(function() {
        $("select").on("change", function () {
            $.ajax({
                type: "POST",
                url: '@Url.Action("ListItemChanged", "Controller")',
                data: { "Value": "@Model.Items.FirstOrDefault(x => x.Selected).Value" }
            });
        });
    })
</script>

@Html.DropDownListFor(m => m.Value, Model.Items, "(Select)")

Controller

public ActionResult ListItemChanged(string selectedItem)
{
    // Stuff.
}

The problem is that when the editor template loads, I get an error saying that @Model.Items is null ("Object reference not set to an instance of an object"). That makes sense, except why would that line be evaluating without any select items changing? Even when I change the $.ajax call to only execute when 1 == 2, it still gives me that error. So clearly that line is being evaluated even when the jQuery function isn't executing.

Given that, how do I prevent that error from occurring? @Model.Items.First(x => x.Selected).Value is only going to have a value once a drop down list item has been selected.

Try this:

@model DropDownListViewModel

<script type="text/javascript">
    $(function() {
        $("select").on("change", function () {
            $.ajax({
                type: "POST",
                url: '@Url.Action("ListItemChanged", "Controller")',
                data: { "Value": $(this).val() }
            });
        });
    })
</script>

@Html.DropDownListFor(m => m.Value, Model.Items, "(Select)")

What you have to understand is, the @expressions are parsed inside the server. You also have to understand that MVC model binder distinguishes the fields based on their name. Inside the data object of the jquery ajax function, where you are passing the object literal, you have to specify the name of the variable as your action method is expecting it to be ( in your case, selectedItem ). So the correct approach should be:

$("select").on('change', function () {
      $.ajax({
            type: 'POST',
            url: '@Url.Action("ListItemChanged", "Controller")',
            data: { "selectedItem": $(this).val() }
      });
});

//Server
[HttpPost]
public ActionResult ListItemChanged(string selectedItem)
{
    // Stuff.
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM