MVC Razor 5:模型从视图中作为null传递给控制器

时间:2018-06-21 06:20:47

标签: c# asp.net-mvc razor

我有一个视图,其模型是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.
    }

视图中使用的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 })

1 个答案:

答案 0 :(得分:0)

多亏了斯蒂芬·穆克(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有关的操作(例如,在上面的示例中,我需要它来计算页面数),我可以引用attributedList。但这在将其传递给Controller时仍然不起作用,后者仍将其视为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>

                        }

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