Как получить строго типизированный DropDownList для привязки к действию элемента управления

Я только что начал новый проект MVC, и у меня возникли проблемы с получением результата публикации из формы.

Это мой класс модели:

public class User
{
    public int id { get; set; }

    public string name { get; set; } 
}

public class TestModel
{
    public List<User> users { get; set; }
    public User user { get; set; }
    public SelectList listSelection { get; set; }

    public TestModel()
    {
        users = new List<User>()
        {
            new User() {id = 0, name = "Steven"},
            new User() {id = 1, name = "Ian"},
            new User() {id = 2, name = "Rich"}
        };

        listSelection = new SelectList(users, "name", "name");
    }
}

Это мой класс просмотра

@model MvcTestApplicaiton.Models.TestModel

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>
@using (Html.BeginForm())
{
    @Html.DropDownListFor(x => x.user, @Model.listSelection)

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

@if (@Model.user != null)
{
    <p>@Model.user.name</p>
}

А это мой контроллер:

public class TestModelController : Controller
{
    public TestModel model;
    //
    // GET: /TestModel/

    public ActionResult Index()
    {
        if(model ==null)
            model = new TestModel();

        return View(model);
    }

    [HttpPost]
    public ActionResult Test(TestModel test)
    {
        model.user = test.user;

        return RedirectToAction("index", "TestModel");
    }

}

Раскрывающийся список выглядит просто отлично, но я не вижу, чтобы запустить тестовую функцию ActionResult. Я думал, что он просто свяжется с отражением, но что бы ни случилось, я этого не вижу.


person HatiHrootvitnir    schedule 11.02.2014    source источник


Ответы (2)


У вас есть две основные ошибки в вашем коде.

  1. Как сказал Бретт, вы публикуете метод Index, но у вас нет метода Index, который поддерживает глагол POST. Самый простой способ исправить это изменить Html.BeginForm() на Html.BeginForm("Test", "TestModel")
  2. Вы неправильно используете Html.DropDownListFor. Вы можете передать туда только типы значений, потому что не забывайте, что представление будет генерировать HTML-страницу. Таким образом, вместо пользователя в вашей модели у вас должен быть идентификатор пользователя, а в вашем представлении у вас должен быть @Html.DropDownListFor(x => x.UserID, @Model.listSelection). И, наконец, в своем действии вы должны запросить свой источник данных, чтобы получить сведения о пользователе с этим идентификатором.

Надеюсь это поможет.

person ssimeonov    schedule 11.02.2014
comment
В том случае, если бы я это сделал, мой выпадающий список выглядел бы так: @using (Html.BeginForm("Test", "TestModel")) { @Html.DropDownListFor(x => x.user.id, @Model.listSelection) <p> <input type="submit" value="Submit" /> </p> } Верно? И мой SelectionList изменится на новый SelectList (пользователи, идентификатор, имя)? Какой параметр примет мое действие? - person HatiHrootvitnir; 11.02.2014
comment
Он примет TestModel, но имейте в виду, что пользовательское свойство не будет заполнено. У вас будет только user.id выбранного элемента. Если вы хотите получить весь элемент, вы должны снова запросить свой список, используя user.id. - person ssimeonov; 11.02.2014

Похоже, вы отправляете обратно в index. Либо используйте метод действия GET Test(), либо укажите параметр ACTION в BeginForm().

Например,

@using (Html.BeginForm("Test", "TestModel"))
{
    @Html.DropDownListFor(x => x.user, @Model.listSelection)

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

Или используйте представление с именем Test (переименуйте index.cshtml в test.cshtml):

public ActionResult Test()
{
    if(model ==null)
        model = new TestModel();

    return View(model);
}
person Brett    schedule 11.02.2014