【问题标题】:How can I post a list of items in MVC如何在 MVC 中发布项目列表
【发布时间】:2013-04-25 15:54:21
【问题描述】:

我有一个包含项目列表的简单表单,我想将它们发布到控制器,但有趣的是我不能。除了列表之外,其他一切都正常进行。我检查了firebug中的ajax调用,帖子值是这样的:

Answers[0].IsMissing    False
Answers[0].Text Ja
Answers[0].Value    0
Answers[1].IsMissing    False
Answers[1].Text Nein
Answers[1].Value    1
Id  1cd14b08-ce3b-4671-8cf8-1bcf69f12b2d
Name    Ja/Nein

我有一个具有以下属性的 AnwserScheme 类:

public string Name { get; set; }
public bool IsMissing { get; set; }
public List<AnswerDisplayItem> Answers { get; set; }

public AnswerScheme()
{
    Answers = new List<AnswerDisplayItem>();
}

我有这个查看代码:

@for (int i = 0; i < Model.Answers.Count; i++) {
    <tr>
        <td>
            @Html.HiddenFor(model => Model.Answers[i].IsMissing)
            @Html.TextBoxFor(model => Model.Answers[i].Value, 
                             new { @class = "inputValue" })
        </td>
        <td>
            @Html.TextBoxFor(model => Model.Answers[i].Text, 
                             new { @class = "inputAnswer" })
        </td>
        <td>
            <span class="span-delete" 
                  data-answer-scheme-id="@Model.Id" 
                  data-answer-id="@Model.Answers[i].Id" >x</span>
        </td>
    </tr>
}

我有这段负责发布的 ajax 代码:

$.ajax({
    url: "/AnswerScheme/AddAnswer",
    type: "post",
    data: $("#formAnswerScheme").serialize(),
    success: function (data) {
                 console.log(data);
                 $("#divAnswerSchemeContainer").html(data);
             }
});

我的控制器中有一个添加答案操作:

[HttpPost]
public PartialViewResult AddAnswer(AnswerScheme answerScheme)
{
    ...some logic comes here
}

所以最终控制器会收到模型,但只有简单的属性,而不是列表。任何帮助将不胜感激!干杯。

【问题讨论】:

  • 您可以查看这篇文章以获取有关如何将模型绑定到集合的教程:haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
  • 您使用的是 MVC3 还是 MVC4?因为您的代码在新创建的 MVC4 项目中运行良好...您可以发布完整的 #formAnswerScheme 表单代码吗?
  • 请从 BeginForm 向下发布您的整个 AnswerScheme 模型和整个表单(并包括您的 @model 声明)
  • 我可以在您发布的代码中看到视图迭代列表项以显示它们,但我不清楚您如何将列表项添加到视图中。这些列表项在网格中?隐藏标记?。项目的容器在表单内?如果不是,这可能是一个原因。您能否提供更多关于您的观点的详细信息,以便我们更好地为您提供帮助?
  • nemesv:我使用 MVC4 项目。查尔斯:这真的是一个实验,我想添加一个新行,除了 ajax 调用之外不使用任何 javascript 逻辑。所以我所做的就是发布表单,重新创建它,删除空行,然后在末尾添加一个新行。并将其放回#divAnswerSchemeContainer。 (我知道它可能不是最好的方法,但可能过多地使用服务器,只是为了创建一个新行,但重新索引也是 javascript 的麻烦。)

标签: c# jquery ajax asp.net-mvc


【解决方案1】:

我希望我能看到更多你的类和代码,因为你没有设置正确的东西。

我根据您提供的内容重新创建了一些东西,这很有效。我为此示例创建了一个 MVC 3 项目。

视图/共享/_Layout.cshtml

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
</head>

    <body>
        @RenderBody()
    </body>
</html>

视图/共享/_Partial.cshtml

@model RazorListTest.Models.AnswerScheme 

<table>
@for (int i = 0; i < Model.Answers.Count; i++) {
    <tr>
        <td>
            @Html.HiddenFor(model => Model.Answers[i].IsMissing)
            @Html.TextBoxFor(model => Model.Answers[i].Value, new { @class = "inputValue" })
        </td>
        <td>
            @Html.TextBoxFor(model => Model.Answers[i].Text, new { @class = "inputAnswer" })
        </td>
        <td><span class="span-delete" data-answer-scheme-id="@Model.Id" data-answer-id="@Model.Answers[i].Id" >x</span></td>
    </tr>
}
</table>

模型/AnswerDisplayItem.cs

using System.Collections.Generic;

namespace RazorListTest.Models
{
    public class AnswerDisplayItem
    {
        public bool IsMissing { get; set; }
        public string Text { get; set; }
        public string Value { get; set; }
        public string Id { get; set; }
    }

    public class AnswerScheme
    {
        public List<AnswerDisplayItem> Answers { get; set; }
        public string Id { get; set; }

        public AnswerScheme()
        {
            Answers = new List<AnswerDisplayItem>();
        }
    }
}

首页/Index.cshtml

@model RazorListTest.Models.AnswerScheme

    @using (Html.BeginForm(null, null, FormMethod.Get, new { name="formAnswerScheme", id = "formAnswerScheme"}))
    {
        {Html.RenderPartial("_Partial");}

        <div>
            <input type="button" value="Click me" id="btnClick"/>
        </div>

        <div id="divAnswerSchemeContainer">

        </div>
    }

<script type="text/javascript">
    $("#btnClick").click(function () {

        $.ajax({
            url: 'Home/AddAnswer',
            type: 'POST',
            dataType: 'json',
            data: $("#formAnswerScheme").serialize(),
            success: function (data) {
                console.log(data);
                $("#divAnswerSchemeContainer").html(data);
            },
            error: function (xhr, textStatus, exceptionThrown) { alert(JSON.parse(xhr.responseText)); }
        });
    });
</script>

控制器/HomeController.cs

using System.Collections.Generic;
using System.Web.Mvc;
using RazorListTest.Models;

namespace RazorListTest.Controllers
{
    public class HomeController : Controller
    {

        public ActionResult Index()
        {
            AnswerScheme a = new AnswerScheme();

            a.Id = "1cd14b08-ce3b-4671-8cf8-1bcf69f12b2d";

            List<AnswerDisplayItem> adi = new List<AnswerDisplayItem>();
            AnswerDisplayItem a1 = new AnswerDisplayItem();
            a1.IsMissing = false;
            a1.Text = "Ja";
            a1.Value = "0";
            a1.Id = "1234";
            AnswerDisplayItem a2 = new AnswerDisplayItem();
            a2.IsMissing = false;
            a2.Text = "Nein";
            a2.Value = "1";
            a2.Id = "5678";
            adi.Add(a1);
            adi.Add(a2);
            a.Answers = adi;
            return View(a);
        }

        [HttpPost]
        public JsonResult AddAnswer(AnswerScheme answerScheme)
        {
            return Json("the list is in the Model.");
        }
    }
}

【讨论】:

  • 感谢您的所有努力,真的很彻底。顺便说一句,我基本上像你一样做了所有事情,但它仍然只是不想工作。恼人的。我要发布我所有的代码,也许某处有一个我缺少或我不知道的设置。
  • 在一个全新的 MVC4 项目中,您的代码可以完美运行。但是那我做错了什么?!
  • 我不知道。我把你的放到一个新项目中,它也可以工作。我创建了一个 Code、CodeList 和 Category 类,这样我就可以坚持使用您的确切代码。我很困惑。
  • 快速提问,所以这意味着在序列化时,mvc 会识别所有 hiddensFor 和 textBoxFor,并将其 Add() 到 model.List 中?我知道您正在使用 data: $("#formAnswerScheme").serialize() 回复,因为问题是这样说的,但是如果我对执行常规帖子的 执行相同操作会发生什么?会有同样的结果吗?
【解决方案2】:

它几乎与 TheGeekYouNeed 发布的内容相同,但我想只是缺少一些东西。我不知道那可能是什么。

AnswerScheme 视图:

@using System.Web.Mvc.Html
@using MetaDataPortal.Models
@model AnswerScheme

 @{
ViewBag.Title =  @Model.IsMissing ? "Missing" : "AnswerScheme";
Layout = "~/Views/Shared/_Layout.cshtml";
}

@section CssContent{
<link href="../../Content/CSS/AnswerScheme.css" rel="stylesheet" />
}


 @using (Html.BeginForm("Save", "AnswerScheme", FormMethod.Post, new { id = "formAnswerScheme" })) {

<div id="divAnswerSchemeContainer">
    @{Html.RenderPartial("_AnswerScheme", Model);}
</div>
<input type="button" class="clear inputButton" id="buttonAddCode" value="Add @(Model.IsMissing ? "Missing" : "Answer")" />

<input type="submit" value="Save" />
}

 @section Javascript{
<script type="text/javascript">
    $(function () {
        $("#buttonAddCode").click(function () {
            $.ajax({
                url: "/AnswerScheme/AddAnswer",
                type: "post",
                async: false,
                data: $("#formAnswerScheme").serialize(),
                success: function (data) {
                    console.log(data);
                    $("#divAnswerSchemeContainer").html(data);
                }
            });
            return false;
        });
    });

</script>
<script type="text/javascript" src="~/Content/JavaScript/AnswerScheme.js"></script>
 }

_AnswerScheme 部分视图

        @model MetaDataPortal.Models.AnswerScheme

        @Html.HiddenFor(model => model.Id, new { Id = "AnswerSchemeId" })
            <ul class="ulGeneralForm">
                <li>
                    @Html.LabelFor(model => model.Name, "Name", new { @class = "labelGeneral" })
                    @Html.TextBoxFor(model => model.Name, Model.Name, new { @class = "textBoxGeneral" })
                </li>
                <li>
                    @Html.Label(@Model.IsMissing ? "Missings" : "Answers", new { @class = "labelGeneral" })
                    <table class="textualData links downloadList">
                        <thead>
                            <tr>
                                <th>Value</th>
                                <th> @(Model.IsMissing ? "Missing" : "Answer")</th>
                                <th></th>
                            </tr>
                        </thead>
                        <tbody id="tbodyCodeContainer">
                            @for (int i = 0; i < Model.Answers.Count; i++) {
                                <tr>
                                    <td>
                                        @Html.HiddenFor(model => Model.Answers[i].IsMissing)
                                        @Html.TextBoxFor(model => Model.Answers[i].Value, new { @class = "inputValue" })
                                    </td>
                                    <td>
                                        @Html.TextBoxFor(model => Model.Answers[i].Text, new { @class = "inputAnswer" })
                                    </td>
                                    <td><span class="span-delete" data-answer-scheme-id="@Model.Id" data-answer-id="@Model.Answers[i].Id" >x</span></td>
                                </tr>
                            }
                        </tbody>
                    </table>
                </li>
            </ul>

AnswerScheme.cs:

 using System;
 using System.Collections.Generic;
 using System.Linq;

 using Opit.Rogatus.DomainObjects;


 namespace MetaDataPortal.Models
 {
public class AnswerScheme : BaseModel
{
    public string Name { get; set; }
    public bool IsMissing { get; set; }

    public List<AnswerDisplayItem> Answers { get; set; }

    public AnswerScheme()
    {
        Answers = new List<AnswerDisplayItem>();
    }

    public AnswerScheme(CodeList codeList, bool isMissing) : this()
    {
        Id = codeList.Id;
        Name = codeList.Name;
        IsMissing = isMissing;
        foreach (Code code in codeList.Codes.Where(code => code.Category.IsMissing == isMissing))
        {
            Answers.Add(new AnswerDisplayItem(code));
        }
    }
      }
    }

AnswerDisplayItem.cs:

    using System;

    using Opit.Rogatus.DomainObjects;


    namespace MetaDataPortal.Models
    {
        public class AnswerDisplayItem
        {
            public Guid Id { get; private set; }
            public short Value { get; private set; }
            public string Text { get; private set; }
            public Guid AnswerSchemeId { get; set; }
            public bool IsMissing { get; private set; }

            public AnswerDisplayItem()
            {
            }

            public AnswerDisplayItem(Code code)
            {
                Id = code.Id;
                Value = code.Value;
                Text = code.Category.Name;
                IsMissing = code.Category.IsMissing;
                if (code.CodeList == null) return;

                AnswerSchemeId = code.CodeList.Id;
            }
        }
    }

和控制器差不多。

【讨论】:

  • 你能贴出你的 Code、CodeList 和 Category 类吗?
【解决方案3】:

你可以这样创建模型

 public class ApplicationInfo
{
        public List<ApplicationAccessRoles> ApplAccessRoleInfo { get; set; }
    }

 public class ApplicationAccessRoles
{
    public int app_access_role_key { get; set; }
    public int app_key { get; set; }
    public string access_role { get; set; }
    public bool inactive { get; set; }
}

把它放在眼里

       <div class="step-pane" id="step3">
                    <div class="form-horizontal" style="vertical-align:central;margin-left:150px">
                        <table id="RolesDetails" cellpadding="0" cellspacing="0" class="data_table">
                            <tr class="dataheader">
                                <td class="width5">
                                    &nbsp;
                                    @Html.HiddenFor(m => m.app_access_role_key)
                                </td>
                                <td class="width200">
                                    Access Roles Name
                                </td>
                                <td class="width10">
                                    Inactive
                                </td>

                            </tr>
                            @if (Model.ApplAccessRoleInfo.Count!= 0)
                            {
                                var chk = Model.ApplAccessRoleInfo.Count;
                                for (int a = 0; a < Model.ApplAccessRoleInfo.Count; a++)
                                {
                                    <tr class="exp_col_header top_border_nil">
                                       @if ((chk - 1) == a)
                                        { 
                                        <td><a href="#" class="gridexpand" rel="1"></a></td>
                                        }
                                        else
                                        {
                                            <td></td>
                                        }
                                        <td>
                                            @Html.HiddenFor(m => m.ApplAccessRoleInfo[a].app_access_role_key)
                                            @Html.EditorFor(m => m.ApplAccessRoleInfo[a].access_role)
                                        </td>
                                        <td>
                                            @Html.CheckBox("ApplTeamAccessInfo[" + a.ToString() + "].inactive", false, new { @class = "check-box"})
                                        </td>
                                    </tr>
                                }
                            }
                            else
                                {
                                    <tr class="exp_col_header top_border_nil">
                                    <td>
                                        <a href="#" class="gridexpand" rel="1"></a>
                                    </td>
                                    <td>
                                        @*@Html.EditorFor(model => model.access_role)*@
                                        @*@Html.EditorFor(m => m.ApplAccessRoleInfo[0].access_role)*@
                                        @Html.EditorFor(model=>model.access_role)
                                    </td>
                                    <td>
                                        @Html.CheckBoxFor(model => model.inactive)
                                    </td>
                                    </tr>

                            }
                        </table>

                    </div>
                </div>

在控制器中

  var main = (from a in db.mas_app_access_roles
                    where a.app_key == AppInfo.app_key
                    select new  ApplicationAccessRoles
                    {
                        app_access_role_key = a.app_access_role_key,
                        access_role = a.access_role,
                        inactive = a.inactive,
                    }).ToList();
        access = main;
        AppInfo.ApplAccessRoleInfo = access;
        ViewBag.check = access;

        return View(AppInfo);

【讨论】:

    【解决方案4】:

    问题在于文本框和其他输入控件的 name/id 属性。您可以使用editor templates 使事情变得无缝且可重复使用。另一个例子here

    但是,如果您仍想循环遍历事物,则您的循环必须在这些示例中查看 herehere

    【讨论】:

    • 不,他的命名没有问题。是的,他应该使用编辑器模板,但他的命名方式很好。
    【解决方案5】:

    尝试将控制器参数名称更改为“answers”或将属性名称更改为 AnswerScheme,如果您帖子中的部分控制器应该接收列表,则将类型更改为:

    List<AnswerScheme> answers
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-25
      相关资源
      最近更新 更多