【问题标题】:Strongly typed view with a SelectList for DropDownList via ViewData: type mismatch on submit通过 ViewData 为 DropDownList 使用 SelectList 的强类型视图:提交时类型不匹配
【发布时间】:2010-03-02 18:55:14
【问题描述】:

我正在尝试在 ASP.NET MVC2 RC 2 中创建一个基于日历事件对象的表单。该对象具有 eventTypeId,它是一个 System.Int32,我需要通过选择列表填充它。

创建初始视图的控制器是:

[WAuthorize]
public ActionResult AddCalendarEvent()
{
    CalendarEventTypesManager calendarEventTypesManager = 
        new CalendarEventTypesManager();

    ViewData["eventTypeId"] = new SelectList(
        calendarEventTypesManager.SelectAll(), "Id", "Type");

    return View();
}

View的sn-p(带header)是:

<%@ Page Title="" Language="C#" 
    MasterPageFile="~/Views/Shared/Site.Extranet.master"
    Inherits="System.Web.Mvc.ViewPage<SomeProject.Models.CalendarEvent>" %>

...

<p><%= Html.DropDownList("eventTypeId") %></p>

这会产生以下 HTML:

<p>
<select id="eventTypeId" name="eventTypeId">
    <option value="1">All school activities</option> 
    <option value="2">All school event</option> 
</select>
</p> 

接受 POST 的控制器是:

[WAuthorize]
// TODO research some more
[ValidateInput(false)]              
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
public ActionResult AddCalendarEvent(CalendarEvent newEvent)
{
    ...

(我尝试在“CalendarEvent newEvent”参数前添加[Bind (Exclude="eventTypeId")],但它不会改变行为。)

问题:当我提交表单时,我得到一个 InvalidOperationException 异常:

具有键的 ViewData 项 'eventTypeId' 是类型 'System.Int32' 但必须是类型 'IEnumerable'。

我在这里和 MVC 博客上查看了许多示例,但到目前为止还不清楚这应该如何工作(看起来基于许多示例,它应该按原样工作)。我是否需要创建具有 SelectListItem 类型变量的第二个模型来接受 SelectListItem 并将值转换为 System.Int32 以实际设置 eventTypeId?这似乎有点绕。

【问题讨论】:

    标签: asp.net-mvc post drop-down-menu selectlist selectlistitem


    【解决方案1】:

    在考虑了更多之后,我想也许我需要在接收发布值的控制器操作中填充ViewData["eventTypeID"]——而不仅仅是在设置表单的控制器操作中。我试过了,效果很好。

    接受 POST 的控制器操作已更改(在此清单中添加最后两行):

        [WAuthorize]
        [ValidateInput(false)]              // TODO research some more
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateAntiForgeryToken]
        public ActionResult AddCalendarEvent(CalendarEvent newEvent)
        {
            CalendarEventTypesManager calendarEventTypesManager = new CalendarEventTypesManager();
            ViewData["eventTypeId"] = new SelectList(calendarEventTypesManager.SelectAll(), "Id", "Type");
            ....
    

    这对我来说并不清楚,所以希望其他人也觉得这很有用。我用 Firefox 的 LiveHTTPHeaders 插件检查了实际的 HTTP POST,确实 entryTypeID 被发布为“...&entryTypeId=2&...”(我在提交之前选择了表单上的第二项)但是我们是否重新加载了选择列表中的发布到控制器进行验证?

    【讨论】:

    • 这样想吧。 DropDownList 向服务器提交单个值。用户选择的值。它不会提交下拉列表中的所有 可能 值。这不是 HTML 的工作方式,这可能有点不幸。这就是为什么您需要在 POST 请求中重新填充 viewdata 以指示可能值的范围。您无需重新填充所选值。
    • 非常感谢您提供此解决方案,这绝对不是直观的,但是当您考虑它时它确实有意义:)
    • 我今天被另一个不直观的事情抓住了:假设你有一个Html.RenderAction("LoginBox"),而LoginBox 操作同时具有 GET 和 POST。如果您为与LoginBox 无关的其他内容提交表单(但它恰好通过 RenderAction 在同一页面上)然后返回验证失败的视图,则调用/返回 LoginBox 的 POST 版本而不是 GET。这一切都有道理,但有一些棘手的角度!编辑:哎呀,在这里回复了完全错误的线程。
    • 这太疯狂了。我遇到了同样的问题,并花了最后几个小时试图解决这个问题。 +1。
    【解决方案2】:

    如果 ViewData 不包含视图上所有字段的必需值并且 ViewData 被回发到视图,则会出现此问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多