【问题标题】:Return a ViewBag ViewModel back to Controller in BeginForm Post method in the View在 View 中的 BeginForm Post 方法中将 ViewBag ViewModel 返回给 Controller
【发布时间】:2016-03-24 13:27:56
【问题描述】:

我有一个在页面上显示 ViewModel 的视图。我想让用户按下一个按钮来创建一个 CSV 文件,然后通过电子邮件发送给他们。我有 POST 工作,但是即使页面清楚地显示了很多行,被发回的 ViewModel 始终是空的。

这是相关视图的一部分:

<table style="width:99%" cellpadding="3" class="ContentTable" border="1" align="center">

    @using (Html.BeginForm("SubmitExcel", "AllRecognition", new { AllRecognitions = ViewBag.AllRecognitionBigViewModel.AllRecognitionViewModel }, FormMethod.Post, new { id = "submitExcel" }))
    {
        <tr>
            <td style="padding:3px;">
                <input type="submit" name="BtnSubmitExcel" id="BtnSubmitExcel" value="Export to Excel" />
            </td>
        </tr>
    }

    <tr style="background-color:#5D7B9D;color:white;">
        <th style="width:4%;padding:3px;font-size:12px;">Date</th>
        <th style="width:8%;padding:3px;font-size:12px;">Employee</th>
        <th style="width:8%;padding:3px;font-size:12px;">Recognized By</th>
        <th style="width:6%;padding:3px;font-size:12px;">5-Star Standard</th>
        <th style="width:70%;padding:3px;font-size:12px;">Description</th>
        <th style="width:4%;padding:3px;font-size:12px;">Points</th>
    </tr>

    @{

        if (ViewBag.AllRecognitionBigViewModel.AllRecognitionViewModel != null)
        {
            foreach (Recognition.ViewModels.AllRecognitionViewModel item in ViewBag.AllRecognitionBigViewModel.AllRecognitionViewModel)
            {
                @:<tr>
                    @:<td style="width:4%;padding:3px;font-size:12px;">@item.Date</td>
                    @:<td style="width:8%;padding:3px;font-size:12px;">@item.Employee</td>
                    @:<td style="width:8%;padding:3px;font-size:12px;">@item.RecognizedBy</td>
                    @:<td style="width:6%;padding:3px;font-size:12px;">@item.FiveStarStandard</td>
                    @:<td style="width:70%;padding:3px;font-size:12px;">@item.Description</td>
                    @:<td style="width:4%;padding:3px;font-size:12px;">@item.Points</td>
                @:</tr>
                }



        }
    }

</table>

这是接收POST方法的控制器端:

public ActionResult SubmitExcel(List<ViewModels.AllRecognitionViewModel> AllRecognitions)
    {
        ViewBag.NoSearch = "block";
        ViewBag.SupervisorSearch = "none";
        ViewBag.DepartmentSearch = "none";
        ViewBag.EmployeeSearch = "none";

        DataTable dtAllRecognitions = Base.SQLHelper.ConvertListToDataTable(AllRecognitions.ToList());
        DataSet dsAllRecognitions = new DataSet();
        dsAllRecognitions.Tables.Add(dtAllRecognitions);
        FHSBase.FHS.DataHelper.SendMeExcelFile(dsAllRecognitions, "Recognitions", CurrentUser);

        ViewModels.AllRecognitionBigViewModel AllRecognitionBigViewModel = new ViewModels.AllRecognitionBigViewModel();
        AllRecognitionBigViewModel.AllRecognitionViewModel = null;
        Models.DateRange DateRange = new Models.DateRange();
        DateRange.fromDate = DateTime.Today.Date;
        DateRange.toDate = DateTime.Today.Date;
        AllRecognitionBigViewModel.DateRange = DateRange;
        ViewBag.AllRecognitionBigViewModel = AllRecognitionBigViewModel; 

        List<SelectListItem> empList = new List<SelectListItem>();
        string VPath = "Index";
        return View(VPath, empList);

    }

“AllRecognitions”视图模型在 ActionResult 中为空,但在视图本身中不为空。如何使用视图中看到的当前值将当前视图模型返回到 ActionResult (SubmitExcel)?

【问题讨论】:

  • 您需要 TempData 用于您的 AllRecognitions。当您发布时,它会在那里为您服务。如果需要,您仍然可以使用 ViewBag 进行渲染,但是除非您将其与表单输入元素匹配,否则它会丢失。 TempData 在内存中的往返过程中幸存下来,并且不依赖于表单。

标签: c# asp.net-mvc post viewmodel


【解决方案1】:

这对你有用吗?这是一种不同的方法。既然您没有在视图中操作任何内容,只是想导出到 Excel,为什么不将结果放在 TempData 而不是 ViewBag 中,然后在 POST 时检索它呢? TempData 对那一趟的记忆很好。

因此,在您的初始控制器渲染中,执行以下操作:

TempData["AllRecognition"] = ThisIsMyAllRecognitionViewModelData;

然后当他们提交到 excel 时,该数据仍在 Temp 中。

public ActionResult SubmitExcel()
    {
var MyDataMadeIt = TempData["AllRecognition"];
// do some stuff
}

【讨论】:

  • 这很有效并且很容易实现!谢谢!
【解决方案2】:

您的表单是空的。所以没有数据被发布到服务器。

当您提交表单时,它不会将整个页面发送到服务器。 (服务器如何知道如何处理 HTML 以从中获取您想要的值?)它从表单元素发送键/值对。而且你只有一个表单元素:

<input type="submit" name="BtnSubmitExcel" id="BtnSubmitExcel" value="Export to Excel" />

所以只有一个键/值被发送到服务器。

您需要做的第一件事是将表单包裹在要发布到服务器的数据周围。所以基本上在你的整个桌子周围。

接下来,您需要发出实际的表单元素。页面上的文本不是可用数据,它只是页面内容。由于模型是List&lt;ViewModels.AllRecognitionViewModel&gt;,那么您应该能够通过对循环进行简单修改来完成它。所以不要这样:

foreach (Recognition.ViewModels.AllRecognitionViewModel item in ViewBag.AllRecognitionBigViewModel.AllRecognitionViewModel)

你会想要这个:

for (var i = 0; i < ViewBag.AllRecognitionBigViewModel.AllRecognitionViewModel.Count(); i++)

表单元素可以是hidden,因此您无需更改页面中的当前用户体验。 也许是这样的:

@Html.HiddenFor(x => x[i].Date)

或许:

@Html.HiddenFor(x => x.AllRecognitionViewModel[i].Date)

我实际上在这里猜测了一下,因为我更习惯于为此使用模型而不是 ViewBag。 (您可能想尝试改用它,它可能会使事情变得更简单。)您可能需要进行一些调试以确定此处服务器端代码中发生的确切情况。

最终,您希望在 客户端 代码中看到的元素类似于以下内容:

<input type="hidden" name="AllRecognitionViewModel.Date[0]" value="..." />

因此,如果上述@Html.EditorFor 建议不起作用,您可以随时手动执行。在循环中,它可能看起来像这样:

<input type="hidden" name="AllRecognitionViewModel.Date[@i]" value="@ViewBag.AllRecognitionBigViewModel.AllRecognitionViewModel[i].Date" />

要注意的关键是name 属性。通过将这些键/值对“数组”发送到服务器,模型绑定器应该能够构造List&lt;ViewModels.AllRecognitionViewModel&gt;

【讨论】:

  • 我确实决定将 BeginForm 帖子包裹在整个表格周围,但控制器中仍然有一个空视图模型。我尝试了您显示的两种 hiddenfor 方法,但我收到一条错误消息,提示无法与 IEnumerable 列表一起使用,该列表是视图上方进一步使用的另一个模型。我无法将 ViewBag Viewmodel 传递回控制器,这对我来说似乎很奇怪。
  • @pldiguanaman:您可以将数据传回控制器。您只需要在表单元素中包含该数据。我在答案末尾添加了另一个可能的建议。如果@Html.HiddenFor 方法不起作用,您始终可以手动构建表单元素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-21
相关资源
最近更新 更多