【问题标题】:MVC Razor 5: Model is passed as null to the controller from a viewMVC Razor 5:模型作为 null 从视图传递给控制器
【发布时间】:2018-06-21 06:20:46
【问题描述】:

我有一个视图,它的Model是一个ViewModel,用来显示一些数据。对于以这种方式显示的每一行,用户可以从 DropDownList 中选择一个值,然后单击一个按钮将他们的选择保存到数据库中。 每次按钮点击都可以通过这种方式处理多个“选择”。

为此,我使用 Html.BeginForm 方法,如下所示(命名为更改):

        @using (Html.BeginForm("DatabaseSave", "Save", new { attr = Model.attributedList }, FormMethod.Post))

而我在控制器中的方法是:

[HttpPost]
[ValidateAntiForgeryToken]       
public ActionResult DatabaseSave(AttributionViewModel attr)
{
   // Data processing.
}

但是当我使用它时,attr 为空。我仍然可以通过使用 Request.Form 和正确的索引来获取我的数据,但这不是我宁愿使用的解决方案。我有一个准备好执行此操作的模型,并且专门使用了 ViewModel,因此我不必询问 Request.Form。但我就是看不到我错过了什么。有人可以帮帮我吗?

为了快速找到答案,您将在下面找到所有相关类和视图的伪代码。

包含数据的类:

public class Attribution
{
    public Attribution()
    {
        listToAttribute = new List<SelectListItem>();
    }
    public string Title { get; set; }
    public int ID { get; set; }
    public string Description { get; set; }
    public int? Number { get; set; }
    public IEnumerable<SelectListItem> listToAttribute { get; set; }
    public int AttributedNumber { get; set; } // Mostly used internally to properly send dropdownlist data.
    // Other methods that are not relevant.
    }

View中使用的ViewModel:

public class AttributionViewModel : Attribution
{
    public AttributionViewModel()
    {

    }
    public IPagedList<Attribution> attributedList { get; set; }
}

视图的相关部分:

 @model Project.ViewModels.AttributionViewModel 
 @using PagedList.Mvc
 @using PagedList

// Some code later...

            @using (Html.BeginForm("DatabaseSave ", "Save", new { attr = Model.attributedList }, FormMethod.Post))
        {
                        @Html.ValidationSummary(false, "", new { @class = "text-danger" })
            @Html.AntiForgeryToken()
            <table class="contentTable contentTable-evo fixedTableHeader">
                <thead>
                   // Headers are not relevant.
                </thead>
                <tbody id="processingTable">
                    @{
                        int i = 0;
                    }
                    @foreach (var item in Model.attributedList)
                    {

                        <tr>
                            <text>@Html.EditorFor(modelItem => Model.attributedList[i].ID, new { htmlAttributes = new { @class = "form-control", @hidden = "hidden", @style = "width:0px display:none", @type = "hidden" } })</text>
                            <td class="noWrap width1percent tri">@item.Title</td>
                            <td class="noWrap width1percent tri">@item.ID</td>
                            <td class="noWrap width1percent tri">@item.Description</td>
                            <td class="noWrap width1percent tri">@item.Number</td>
                            <td class="noWrap width1percent tri">
                                <text>@Html.DropDownListFor(modelItem => Model.attributedList[i].AttributedNumber, Model.attributedList[i].listToAttribute , "" , new { htmlAttributes = new { @class = "form-control", @style = "width:90px" } })</text>
                            </td>
                        </tr>
                        i++;
                    }
                </tbody>
            </table>
            <br />
            <center>
                <input value="Processing" class="add" type="submit" onclick="javascript:return ShowConfirm();" >
            </center>

            Page @(Model.attributedList.PageCount < Model.attributedList.PageNumber ? 0 : Model.attributedList.PageNumber) out of @Model.attributedList.PageCount | @Model.attributedList.TotalItemCount <br />
        <text>@Resources.Views.PaginationResource.GoToPage </text>@Html.DropDownList("PageChanger", new SelectList(Enumerable.Range(1, Model.attributedArticles.PageCount), "", ""), new { onchange = "PageChangedFromDropDown()" })

        @Html.PagedListPager(Model.attributedList, page => Url.Action("Attribute", new { page, searchString = Session["Search"], currentFilter = ViewBag.CurrentFilter, sortColumn = ViewBag.sortAttr }), new PagedListRenderOptions { LiElementClasses = new[] { "needsLoading" }, DisplayEllipsesWhenNotShowingAllPageNumbers = false })

【问题讨论】:

  • 首先从BeginForm 中删除new { attr = Model.attributedList }
  • 如果这样做,我会收到“System.MissingMethodException:无法创建接口的实例”异常(在提交表单时)。我把它放在那里是因为我之前遇到过这个错误。
  • 这是一个单独的问题(它需要被删除 - 查看您生成的表单属性 - action 属性以了解它为什么永远不会绑定)
  • 你为什么使用IPagedList? (我认为这是另一个错误的原因)
  • 抱歉,这没有任何意义 - IPagedList 用于阅读,而不是编辑,它不起作用,因为您正在尝试初始化 IPageList&lt;Attribution&gt;,但它不起作用。一种可能的选择是回发到包含相同属性的不同模型,但集合为 LIst&lt;Attribution&gt;

标签: c# asp.net-mvc razor


【解决方案1】:

感谢 Stephen Muecke,我设法找到了我做错的地方。

问题出在 ViewModel 中:

    public IPagedList<Attribution> attributedList { get; set; }

我需要使用它,因为 ViewModel 通常不能使用 PagedList。

但是,这并不意味着它可以用于包含和解析数据。我需要一个单独的列表,添加以下内容:

    public IPagedList<Attribution> attributedList { get; set; }
    public List<Attribution> parsableListOfAttributed { get; set; } // Otherwise passing to the controller WILL NOT WORK.

对于与 PagedList 相关的任何操作(例如,在我上面的示例中,我需要它来计算页数)我可以参考属性列表。但这在将它传递给控制器​​时不起作用,控制器仍然认为它是一个 PagedList,因此不能用于该目的。

更正视图:

        @using (Html.BeginForm("DatabaseSave", "Save", FormMethod.Post))
        {
                        @Html.ValidationSummary(false, "", new { @class = "text-danger" })
            @Html.AntiForgeryToken()
            <table class="contentTable contentTable-evo fixedTableHeader">
                <thead>
                    // Headers are still not relevant.
                </thead>
                <tbody id="processingTable">
                    @{
                        int i = 0;
                    }
                    @foreach (var item in Model.attributedArticles)
                    {

                        <tr>
                            <text>@Html.EditorFor(modelItem => Model.parsableListOfAttributed[i].ID, new { htmlAttributes = new { @class = "form-control", @hidden = "hidden", @style = "width:0px display:none", @type = "hidden" } })</text>
                            <td class="noWrap width1percent tri">@item.GTIN</td>
                            <td class="noWrap width1percent tri">@item.SMP</td>
                            <td class="noWrap width1percent tri">@item.DescriptionFr</td>
                            <td class="noWrap width1percent tri">@item.AuthorisationNumber</td>
                            <td class="noWrap width1percent tri">
                                <text>@Html.DropDownListFor(modelItem => Model.parsableListOfAttributed[i].AttributedNumber, Model.parsableListOfAttributed[i].listToAttribute, "" , new { htmlAttributes = new { @class = "form-control", @style = "width:90px"} })</text>
                            </td>
                        </tr>
                        i++;
                    }
                </tbody>
            </table>
            <br />
            <center>
                <input value="Processing"" class="add" type="submit" onclick="javascript:return ShowConfirm();" >
            </center>

                        }

使用此方法正确传递模型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-08
    • 1970-01-01
    • 2020-04-24
    • 2016-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多