2

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

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

如果我更改类型,它没有问题,但 Division 为 null 或 0。有没有办法将 SelectedValue 从 DropDown 传递给控制器​​ 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)%>

它工作得很好!只有在所有“部门”项目名称相同的情况下,它似乎才有效。如果我更改名称,View 崩溃或 ViewModel“Division”属性被发送为 0。

这是为什么?

4

2 回答 2

5

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

public string DivisionValue { get; set; }

或者将类型更改为 int、DateTime 或任何适当的类型。

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

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

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

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

于 2009-05-31T00:57:45.640 回答
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 合并运算符][1] (??),您可以看到初始选择(来自 DB)或来自回发的 ViewData(例如,如果表单验证失败)。

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

于 2009-06-01T05:41:56.257 回答