简体   繁体   English

将SelectList“ SelectedValue”传递给控制器​​操作方法

[英]Pass SelectList “SelectedValue” to Controller Action Method

I have a registration form which displays a users Name (textbox), Email (textbox) and Division (SelectList). 我有一个注册表单,其中显示了用户名(文本框),电子邮件(文本框)和部门(SelectList)。 The Name and Email are pre-populated (I'm using Windows Authentication, Intranet app), and I want to send the SelectedValue from the DropDown to my controller as an Int32, I don't want to send the entire SelectList back. 名称和电子邮件已预先填充(我正在使用Windows身份验证,Intranet应用程序),并且我希望将Dropdown中的SelectedValue作为Int32发送到我的控制器,我不想将整个SelectList发送回去。 This list is small now, but will grow to considerable size. 该列表现在很小,但是将会增长到可观的规模。

I a class called RegistrationViewModel , it contains public properties for these fields. 我的类称为RegistrationViewModel ,它包含这些字段的公共属性。 However, when I use SelectList for the DivisionList, I receive this error: No parameterless constructor defined for this object. 但是,当我将SelectList用于DivisionList时,会收到此错误: No parameterless constructor defined for this object. .

If i change the Type, it works no problem, but Division is null or 0. Is there a way to pass the SelectedValue from a DropDown to a Controller Action method as a Int32? 如果我更改Type,则没问题,但是Division为null或0。是否可以将SelectedValue从DropDown传递给Int32的Controller Action方法?

Edit 1: 编辑1:

I'm not really sure what I'm doing, I've been using MVC for about 48 hours, watched the PDF, TechEd, and TechDays videos. 我不确定自己在做什么,我已经使用MVC约48个小时,观看了PDF,TechEd和TechDays视频。

My apologies, here is my controller code: 抱歉,这是我的控制器代码:

[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 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; }    
}

Here's the view 这是视图

<%@ 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>

Edit 2: 编辑2:

Eilon: Here is what I changed it too: Eilon:这也是我所做的更改:

Controller: 控制器:

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

View: 视图:

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

I recieve this exception: There is no ViewData item with the key 'DivisionValue' of type 'IEnumerable'. 我收到此异常:没有键类型为“ DinumValue”的“ IEnumerable”类型的ViewData项目。

When I updated the View to this: 当我将视图更新为:

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

It works just great! 效果很好! It only seems to work if all the "Division" items named identically. 如果所有“部门”项目都相同地命名,这似乎才起作用。 If I change the name the View crashes or the ViewModel "Division" property is sent as 0. 如果更改名称,则视图崩溃或ViewModel的“ Division”属性发送为0。

Why is that? 这是为什么?

The RegistrationViewModel type should contain a simple-typed property such as: RegistrationViewModel类型应包含一个简单类型的属性,例如:

public string DivisionValue { get; set; }

Or change the type to int, DateTime, or whatever the appropriate type is. 或将类型更改为int,DateTime或任何适当的类型。

In HTML and HTTP the only thing that gets posted back for a drop down list is the name of the field and the selected value. 在HTML和HTTP中,唯一返回到下拉列表的内容是字段名称和所选值。

To get everything to match up you also need to change the view to render a different input name for the drop down list: 为了使所有内容匹配,还需要更改视图以为下拉列表呈现不同的输入名称:

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

Notice that I'm using "DivisionValue" is the value of the list, and DivisionList as the list of all available items. 请注意,我使用“DivisionValue”是列表的价值 ,并作为DivisionList所有可用项的列表。

I'd just be more explicit with the SelectList type. 我只是对SelectList类型更明确。 I'd suggest creating the SelectList in the controller action and forget about casting it in the view. 我建议在控制器动作中创建SelectList ,而SelectList在视图中进行转换。 My code works like this (CRUD Edit page): 我的代码如下所示(“ CRUD编辑”页面):

..in the Action: ..在动作中:

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

..and in the view: ..并在视图中:

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

.. you can see that either the initial selection (from DB) is persisted or the ViewData from post backs (like if the form fails validation) thru the use of the [null coalescing operator][1] (??). ..您可以看到,通过使用[null合并运算符] [1](??),持久化了初始选择(来自数据库)或来自回发的ViewData(例如,表单验证失败)。

Moreover, if i refactored this code, i'd prob like to use a ViewModel object like you are. 此外,如果我重构此代码,则可能会像您一样使用ViewModel对象。 The only thing is: (1) you'd never need to reference the ViewModel SelectList property in the view coz MVC auto binds this for us by the Html.DropDownList() overload.. and (2) i'd still need to ref the ViewData in the action anyway to get the selected value from a failed validation post back so what's the point really?? 唯一的事情是:(1)您永远不需要在视图视图中引用ViewModel SelectList属性Html.DropDownList()通过Html.DropDownList()重载为我们自动绑定此视图。和(2)我仍然需要引用无论如何,操作中的ViewData都会从失败的验证帖子中获取选定的值,那么真正的意义是什么?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM