Передайте SelectList "SelectedValue" в метод действия контроллера - PullRequest
2 голосов
/ 31 мая 2009

У меня есть форма регистрации, в которой отображаются имя пользователя (текстовое поле), электронная почта (текстовое поле) и подразделение (SelectList). Имя и адрес электронной почты предварительно заполнены (я использую аутентификацию Windows, приложение для внутренней сети), и я хочу отправить SelectedValue из DropDown на мой контроллер как Int32, я не хочу отправлять весь список SelectList обратно. Этот список сейчас невелик, но увеличится до значительных размеров.

Я класс с именем RegistrationViewModel, он содержит публичные свойства для этих полей. Однако, когда я использую SelectList для DivisionList, я получаю эту ошибку: No parameterless constructor defined for this object..

Если я изменяю Тип, это не проблема, но Деление равно нулю или 0. Есть ли способ передать SelectedValue из DropDown в метод Controller Action как Int32?

Редактировать 1:

Я не совсем уверен, что я делаю, я использую MVC около 48 часов, смотрел видео в формате PDF, TechEd и TechDays.

Мои извинения, вот мой код контроллера:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(RegistrationViewModel rvm)
{
    IApplicationContext context = ContextRegistry.GetContext();
    IValidationErrors errors = new ValidationErrors();

    IValidator validator = (IValidator)context.GetObject("RegistrationValidator");
    bool valid = validator.Validate(rvm, errors);

    if (valid)
        repo.SaveRegistration();
    else
        ViewData["DivisionList"] = repo.GetDivisions();

    return View(rvm);
}

RegistrationViewModel Класс

public class RegistrationViewModel
{
    public string Name { get; set; }
    public string Email { get; set; }
    //public SelectList DivisionList { get; private set; }
    public int Division { get; set; }    
}

Вот вид

<%@ Page Language="C#" 
MasterPageFile="~/Views/Shared/Site.Master" 
Inherits="System.Web.Mvc.ViewPage<RegistrationViewModel>" %>

<%@ Import Namespace="Project1.Entities"%>
<%@ Import Namespace="Project1.Models"%>

<asp:Content ID="registerTitle" ContentPlaceHolderID="TitleContent" runat="server">
    Register
</asp:Content>

<asp:Content ID="registerContent" ContentPlaceHolderID="MainContent" runat="server">
...
    <% using (Html.BeginForm())
       { %>
        <div>
            <fieldset>
                <legend>Account Information</legend>
                <p>
                    <label for="name">Name:</label>
                    <%= Html.TextBox("Name", User.Identity.Name.GetDisplayName()) %>
                    <%= Html.ValidationMessage("username") %>
                </p>
                <p>
                    <label for="email">Email:</label>
                    <%= Html.TextBox("email", User.Identity.Name.GetEmailFromLogin()) %>
                    <%= Html.ValidationMessage("email") %>
                </p>              
                <p>
                    <label for="division">Division:</label>
                    <%= Html.DropDownList("DivisionList", ViewData["DivisionList"] as SelectList)%>
                    <%= Html.ValidationMessage("confirmPassword") %>
                </p>
                <p>                
                    <input type="submit" value="Register" />
                </p>
            </fieldset>
        </div>
    <% } %>
</asp:Content>

Редактировать 2:

Эйлон: Вот что я тоже изменил:

Контроллер:

public ActionResult Register()
{
  ViewData["DivisionList"] = repo.GetDivisions();
  return View();
}

Вид:

<%= Html.DropDownList("DivisionValue", ViewData["DivisionList"] as SelectList)%>

Я получаю это исключение: Нет элемента ViewData с ключом «DivisionValue» типа «IEnumerable».

Когда я обновил вид на это:

<%= Html.DropDownList("DivisionList", ViewData["DivisionList"] as SelectList)%>

Работает просто отлично! Кажется, это работает, только если все элементы «Разделение» названы одинаково. Если я меняю имя, вид сбой или свойство ViewModel «Division» отправляется как 0.

Почему это?

Ответы [ 2 ]

5 голосов
/ 31 мая 2009

Тип RegistrationViewModel должен содержать свойство простого типа, например:

public string DivisionValue { get; set; }

Или измените тип на int, DateTime или любой другой подходящий тип.

В HTML и HTTP единственное, что возвращается для выпадающего списка, - это имя поля и выбранное значение.

Чтобы все совпадало, вам также нужно изменить представление для отображения другого входного имени для выпадающего списка:

<%= Html.DropDownList("DivisionValue", ViewData["DivisionList"] as SelectList)%>

Обратите внимание, что я использую "DivisionValue" - это значение списка и DivisionList в качестве списка всех доступных элементов.

0 голосов
/ 01 июня 2009

Я бы просто был более явным с типом SelectList. Я бы предложил создать SelectList в действии контроллера и забыть о приведении его в представление. Мой код работает следующим образом (страница редактирования CRUD):

.. в действии:

            ViewData["WorkType.ID"] = new SelectList(this._vacancySvc.GetVacancyWorkTypes(),
            "ID", "Name", ViewData["WorkType.ID"] ?? vacancy.WorkType.ID);

.. и в представлении:

<p><% =Html.Encode("Work Type:") %><br />
            <% =Html.DropDownList("Worktype.ID")%><span class="smallgrey">(required)</span><br />

.. вы можете видеть, что либо первоначальный выбор (из БД) сохраняется, либо ViewData из постов (например, если форма не проходит проверку) через использование [оператора объединения нулей] [1] (??) .

Кроме того, если бы я рефакторинг этого кода, я хотел бы использовать объект ViewModel, как вы. Единственное, что: (1) вам никогда не понадобится ссылаться на свойство ViewModel SelectList в представлении, потому что MVC auto связывает это для нас с помощью перегрузки Html.DropDownList() .. и (2) мне все равно нужно сос в любом случае ViewData в действии, чтобы получить выбранное значение из сообщения о неудачной проверке, так какой смысл в действительности ??

...