Asp.net mvc 通过选择列表“;SelectedValue";控制器动作法

Asp.net mvc 通过选择列表“;SelectedValue";控制器动作法,asp.net-mvc,selectlist,Asp.net Mvc,Selectlist,我有一张登记表,上面显示了用户名(文本框)、电子邮件(文本框)和部门(选择列表)。姓名和电子邮件是预先填充的(我使用的是Windows身份验证、Intranet应用程序),我想将下拉列表中的SelectedValue作为Int32发送到我的控制器,我不想将整个SelectList发送回。这个名单现在很小,但将扩大到相当大的规模 我创建了一个名为RegistrationViewModel的类,它包含这些字段的公共属性。但是,当我对分区列表使用SelectList时,我收到以下错误:没有为此对象定义

我有一张登记表,上面显示了用户名(文本框)、电子邮件(文本框)和部门(选择列表)。姓名和电子邮件是预先填充的(我使用的是Windows身份验证、Intranet应用程序),我想将下拉列表中的SelectedValue作为Int32发送到我的控制器,我不想将整个SelectList发送回。这个名单现在很小,但将扩大到相当大的规模

我创建了一个名为
RegistrationViewModel
的类,它包含这些字段的公共属性。但是,当我对分区列表使用
SelectList
时,我收到以下错误:
没有为此对象定义无参数构造函数。

如果我更改了类型,它就可以正常工作,但除法为null或0。有没有办法将SelectedValue作为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
Class

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>
视图:


我收到这个例外: 没有具有类型为“IEnumerable”的键“DivisionValue”的ViewData项

当我将视图更新为以下内容时:

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

真是太棒了!只有当所有“分部”项的名称相同时,它才似乎起作用。如果更改名称,视图将崩溃,或者ViewModel“Division”属性将作为0发送


这是为什么?

RegistrationViewModel类型应该包含一个简单的类型化属性,例如:

public string DivisionValue { get; set; }
或者将类型更改为int、DateTime或任何适当的类型

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

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

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


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

我只想更明确地使用
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)被持久化,或者来自回发的ViewData(如表单未通过验证)

此外,如果我重构了这段代码,我可能会像您一样使用ViewModel对象。
唯一的问题是:(1)您不需要在视图中引用ViewModel
SelectList
属性,因为MVC通过
Html.DropDownList()。。(2)我仍然需要在操作中引用ViewData,以从失败的验证帖子中获取所选值,因此真正的意义是什么???

请向我们展示控制器操作代码。您如何传递电子邮件文本框的值?
            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 />