将SelectList“SelectedValue”传递给Controller Action Method

时间:2009-05-30 20:41:17

标签: asp.net-mvc selectlist

我有一个注册表单,显示用户名称(文本框),电子邮件(文本框)和分部(SelectList)。名称和电子邮件已预先填充(我正在使用Windows身份验证,Intranet应用程序),我想将DropDown中的SelectedValue作为Int32发送到我的控制器,我不想再发送整个SelectList。这个清单现在很小,但会增长到相当大的范围。

我是一个名为RegistrationViewModel的类,它包含这些字段的公共属性。但是,当我使用SelectList作为DivisionList时,我收到此错误:No parameterless constructor defined for this object.

如果我更改Type,它没有问题,但是Division为null或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:

Eilon:这也是我改变它的原因:

控制器:

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

查看:

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

我接受了这个例外: 没有带有'IEnumerable'类型的键'DivisionValue'的ViewData项。

当我将视图更新为:

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

效果很好!如果所有“Division”项目命名相同,它似乎才有效。如果我更改名称视图崩溃或ViewModel“Division”属性发送为0。

为什么?

2 个答案:

答案 0 :(得分:5)

RegistrationViewModel 类型应包含简单类型的属性,例如:

public string DivisionValue { get; set; }

或者将类型更改为int,DateTime或任何合适的类型。

在HTML和HTTP中,为下拉列表返回的唯一内容是字段名称和所选值。

要使所有内容匹配,您还需要更改视图以为下拉列表呈现不同的输入名称:

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

请注意,我使用“DivisionValue”是列表的 DivisionList 是所有可用项目的列表。

答案 1 :(得分:0)

我只是更明确地使用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 />

..你可以通过使用[null coalescing operator] [1](??)看到初始选择(来自DB)是持久的还是来自post backs的ViewData(如果表单验证失败)

此外,如果我重构了这段代码,我可能会像你一样使用ViewModel对象。 唯一的事情是:(1)你永远不需要在视图中引用ViewModel SelectList属性,因为Html.DropDownList()重载,MVC auto为我们绑定了这一点。(2)我是仍然需要在动作中引用ViewData以从失败的验证帖子中获取所选值,那么真正的重点是什么?