简体   繁体   中英

drop down list value is null after posting to controller in ASP.NET MVC

I am new to ASP.NET MVC. I have a simple form with a submit button and an html select element, populated with two items. When the form posts to my controller, all the form values are null. I've even tried doing it with $.POST instead and the id variable I am sending is null when it gets to the controller. Here is my code:

HTML

 @using (Html.BeginForm("SetOptionForUser", "MyController", FormMethod.Post, new { @class="form-inline" }))
{
    @Html.AntiForgeryToken() 
    <div class="text-center">
        <div class="form-group">
            <select id="ddlSelect" class="form-control">
                @foreach (var item in Model.Persons)
                {
                    <option value="@item.Id">@item.Name</option>
                }
            </select>
        </div>
        <button type="submit" class="btn btn-primary" id="btnEnter">Go</button>
    </div>
}

MVC Controller

[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult SetOptionForUser(FormCollection form)
    {
        string option = form["ddlSelect"].ToString(); //null error
        return RedirectToAction("AnotherAction", "AnotherController");
    }

It seems nothing in the form is being sent. I also tried this:

JS

$("#btnEnter").click(function (e) {
    var optionId = $("#ddlSelect").val(); //this get val correctly
    $.post(@Url.Action("SetOptionForUser", "MyController"), optionId);
  });

MVC Controller for JS method

**MVC Controller**

[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult SetOptionForUser(int optionId) //null
    {
        string option = optionId.ToString(); //null error
        return RedirectToAction("AnotherAction", "AnotherController");
    }

What I am doing wrong?

Normal form submit

Your normal form submit should work if your select element name and your http post action method parameter name is same.

<select name="selectedPerson" id="selectedPerson" class="form-control">
  <!-- Options goes here --> 
</select>

and your action method

[HttpPost]
public ActionResult SetOptionForUser(string selectedPerson)
{
    string option = selectedPerson;
    return RedirectToAction("AnotherAction", "AnotherController");
}

You might also consider using the Html.DropDownListFor or Html.DropDownList helper methods to generate the SELECT element from a list of items ( instead of manually writing the loop to render the option items).

Sending data with Ajax

Now if you want this to be ajaxified, you can send the data in either querystring or the request body

$(function(){
  $("#btnEnter").click(function (e) {
    e.preventDefault();
    var optionId = $("#selectedPerson").val(); 
    $.post('@Url.Action("SetOptionForUser", "MyController")', { selectedPerson:optionId});
  });
});

Now there is no point in returning a RedirectResult for an ajax call. You might consider returning a json response (indicating whether your action was successful or not) from your action methodo and in the success callback of $.post you can inspect the value and do needed.

[HttpPost]
public ActionResult SetOptionForUser(string selectedPerson)
{
    string option = selectedPerson;
    return Json(new {status="success"});
}

And you can check the response in the callback

 var optionId = $("#selectedPerson").val();
 var url="@Url.Action("SetOptionForUser", "MyController")";
 $.post(url, { selectedPerson:optionId}, function(response){
   if(response.status==="success")
   {
      alert("Success");
   }
   else
   {
     alert("Some trouble!");
   }
 });

The FormCollection in ASP.NET MVC is tied to the name attribute of input elements, add the name attribute to your select HTML element, like this:

<select id="ddlSelect" name="ddlSelect" class="form-control">

Note: The id attribute is how to find things in the DOM and the name attribute is for what gets included/submitted in the form


As for the JavaScript jQuery AJAX POST issue, I believe the issue is that jQuery is making an intelligent guess that your optionId is text. You should create an object literal to hold the JSON data and then stringify that value to send to the controller, like this:

var dataForServer = {
    optionId: optionId
};

$.post(@Url.Action("SetOptionForUser", "MyController"), 
       JSON.stringify(optionId), 
       null, 
       json);

The only thing that I see missing in your code is the name property of your dropdown.

   <select id="ddlSelect" name="ddlSelect" class="form-control">
            @foreach (var item in Model.Persons)
            {
                <option value="@item.Id">@item.Name</option>
            }
        </select>

for your first example your using FormCollection

string option = form["ddlSelect"].ToString();

but your DropDown doesn't have a name property and form collection is using the name property as reference that is why you are getting a null value.

same goes with your second example reference the DropDown name property instead of ID in your Parameter

public ActionResult SetOptionForUser(int myDropDownName) //null
{
    string option = myDropDownName.ToString(); //null error
    return RedirectToAction("AnotherAction", "AnotherController");
}

The FormCollection in ASP.NET MVC is getting to the name attribute of input elements

so add this attribute name="ddlSelect"

MattoMK,

Please post code for your Model. Typically, a model will hold all the data required for your webform to run and your post to send the data back. In your view, you should be selecting to a Model field. You seem to have Model.Persons, which is likely an enumerable of a class describing people.

MODEL

You did not describe your model, so a fake one is shown with just two properties, a string to hold the list selection and your list of Persons. Hopefully, your HttpGet Action populates your model correctly.

public class MyModel 
{
 public string ddSelect { get ; set; }
 public List<Person> Persons { get ; set; }
}

HTML (often called the View)

We explicitly tell the world that this view uses this Model.

@model MyModel // Tell MVC what model we are using for this view
@using (Html.BeginForm("SetOptionForUser", "MyController", FormMethod.Post, new { @class="form-inline" }))
    {
    @Html.AntiForgeryToken()
    <div class="text-center">
        <div class="form-group">
        @Html.DropDownListFor(m => m.ddSelect, Model.PersonList, new {id = "ddlSelect"})        
        </div>
        <button type="submit" class="btn btn-primary" id="btnEnter">Go</button>
    </div>
}

MVC Controller Your controller is expecting your view to return a model of type MyModel and thus will try to push the form variables into a copy of your model (if it can). Since your form does not fill out a model property, you get nulls back.

[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult SetOptionForUser(MyModel theModel, FormsCollection collection) 
{
    var selectedName = theModel.ddSelect;
    return RedirectToAction("AnotherAction", "AnotherController");
}

This should return the value you selected from the dropdown list. Pay attention to the generated HTML from your site (Press F12 in browser and view source) to see how MVC does things. It's easier to play along than to fight it. In the above POST Action, see the included parameter collection... That holds all of the form variables. It can be gone through to find non model values if required. It is not necessary and can be removed, but poking around in that collection affords a nice view of how data is structured upon POST.

Hope this Helps.

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