简体   繁体   中英

pass selected dropdown list value from View to Controller

I want to pass a parameter (string) to my Controller from my View. The value should be that which is selected from a dropdown list in the view. The method is called after a button-click, but in the Controller, the parameter is always null.

In the View:

    @using (Html.BeginForm("Send", "Overview", FormMethod.Get))
    {
        <p>Email: @Html.DropDownList("Emails", Model.GetEmails())
        <input type="submit" value="Send" />
        </p>

    }

In the Controller:

    public ActionResult Send(string email)
    {
        // email is always null!
        return null;
    }

In the Overview model:

    private List<SelectListItem> emails;
    ...
    public Overview()
    {
        emails = new List<SelectListItem>();
        emails.Add(new SelectListItem() { Text = "a@b.com", Value = "a@b.com", Selected = true });
        emails.Add(new SelectListItem() { Text = "b@c.com", Value = "b@c.com", Selected = false });
        emails.Add(new SelectListItem() { Text = "c@d.com", Value = "c@d.com", Selected = false });
    }
    ...
    public List<SelectListItem> GetEmails()
    {
        return emails;
    }

Could you please help me get this work? What am I missing? (Btw, never mind the Controller returning null for now please :)).

From your terminology I'm guessing you're confused about what's going on. You never send anything from the view to the controller. Instead the view is something that assembles Html to send to the web browser. So what's actually happening is this:

  • Your browser requests /MyApp/Overview from your server (IIS)
  • IIS picks it up and sends that to Asp.Net
  • Asp.Net Mvc sees the request and through routing figures out that you want to call the Overview method on the MyAppController class
  • The method runs and produces a Model
  • Asp.Net Mvc passes the model to the view engine which runs your view to produce html
  • The html is returned to IIS which sends it to your browser
  • Your browser displays the html as a select control.
  • The user makes a selection and clicks "submit" on the form
  • The browser encodes their submission and sends it to the url in the form's action attribute (eg <form method=POST action="/MyApp/Send> )
  • IIS picks that up and sends that to Asp.Net
  • Asp.Net Mvc sees the request and through routing figures out that you want to call the Send method on the MyAppController class
  • Asp.Net Mvc sees that your method expects a string parameter named email and tries to find this information in the submitted form data using model binding
  • Asp.Net Mvc invokes the Send method with the found parameter value (if available)
  • ...

You do not provide quite enough context for me to be able to analyze what is wrong but my guess is that @Html.DropDownList("Emails", Model.GetEmails()) is generating something like <select name="Emails"> ....</select> . This means that when model binding is happening it is looking for submitted "email" input but finds nothing. Instead try something like @Html.DropDownList("email", Model.GetEmails()) to get it to work.

Semantically this is more correct anyways, because while the control displays emails (plural), a user actually interacts with it by selecting an email (singular). Think of it as if it was just a text box, you wouldn't name that in the plural.

I should note by the way, that you have several HUGE security holes here. By taking the email address as input into your method it seems like anyone can open up the developer tools in their browser and use your service to send emails to any email address! Spammers love to find unsecured services like this. A much better solution would be to have the value in the generated select list be an id for the user you want emailed, and in the Send method take the id as input. Also, Send should definitely not be accessible via Http GET (so put an [HttpPost] attribute on there!). If it allows GET, even if this is behind a login page, I can trick users who are logged in into visiting a form with an <img src="http://yoursite.com/MyApp/Send/?email=personIWantToSpam@example.com" /> and every time they visit the page someone will receive a spam email.

You could just use a string in your model,

public string emails { get; set; };

then Use a DropDownListFor on your view,

@Html.DropDownListFor(x => x.emails, Model.GetEmails())

and get the value directly from the model on the POST .

[HttpPost]
public ActionResult Send(OverviewViewModel overviewModel)
{
    //here is the value from the drop down
    var theEmail = overviewModel.emails;
}

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