【问题标题】:MVC Pass display data between viewsMVC 在视图之间传递显示数据
【发布时间】:2016-03-25 19:28:32
【问题描述】:

我有一个视图模型,用于在一个视图上显示表单,然后也用于将 POST 数据表示为操作。然后,该操作会显示另一个视图模型,其中包含来自第一个视图模型的大部分相同数据。但是,第一个视图模型有几个“仅显示”属性,第二个视图模型也需要这些属性(也只能在第二个视图上显示)。

我想知道将这个“仅显示”数据传递给第二个视图的最佳方式是什么。目前,我想出的最佳解决方案是有一堆隐藏的表单字段,其中包含仅显示的属性值,然后模型会自动填充处理表单 POST 的操作。但是,使用隐藏的表单字段似乎非常“hackish”,并且似乎应该有更好的解决方案将此数据传递到另一个视图该操作不需要仅显示信息,它只是访问它以填充属性传递给第二个视图的第二个视图模型。

让我用代码来解释我的问题,因为我所追求的可能通过代码比文字更好地理解。

型号:

public class SearchFilters
{
    // ...
}

public class SearchResult
{
    public int Id { get; set; }
    public bool Selected { get; set; }
    public string SomeDisplayValue1 { get; set; }
    public string SomeDisplayValue2 { get; set; }
    // ...
}

public class ResultsViewModel
{
    public IList<SearchResult> Results { get; set; }
    // ...
}

public class DoSomethingWithSelectedResultsViewModel
{
    public IList<SearchResult> SelectedResults { get; set; }
    public string SomeOtherProperty { get; set; }
    // ...
}

控制器:

[HttpPost]
public ActionResult Results(SearchFilters filters)
{
    ResultsViewModel results = new ResultsViewModel();
    // ...
    return new View(results);
}

[HttpPost]
public ActionResult DoSomethingWithSelectedResults(ResultsViewModel model)
{
    // ...
    return View(new DoSomethingWithSelectedResultsViewModel
    {
        SelectedResults = model.Results.Where(r => r.Selected).ToList(),
        SomeOtherProperty = "...",
        // ...
    });
}

查看:Results.cshtml

@model ResultsViewModel
@using (Html.BeginForm("DoSomethingWithSelectedResults", "Search"))
{
    <table>
    for (int i = 0; i < Model.Results.Count; i++)
    {
        <tr>
            <td>
                @Html.CheckBoxFor(m => Model.Results[i].Selected)

                @* I would like to eliminate these hidden inputs *@
                @Html.HiddenFor(m => Model.Results[i].Id)
                @Html.HiddenFor(m => Model.Results[i].SomeDisplayValue1)
                @Html.HiddenFor(m => Model.Results[i].SomeDisplayValue2)
            </td>
            <td>@Html.DisplayFor(m => Model.Results[i].SomeDisplayValue1)</td>
            <td>@Html.DisplayFor(m => Model.Results[i].SomeDisplayValue2)</td>
        <tr>
    }
    </table>
    <button type="submit">Do Something With Selected Results</button>
}

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-4


    【解决方案1】:

    据我所知,通过 Controller 将数据从 View 传递到另一个 View 的最佳方法之一是使用 ViewBag、ViewData 或 TempData。例如,您可以传递从 View I 检索到的数据,如下所示:

    TempData[DataToBePassed] = model.CustomData;
    

    然后在类似于这样的 View II 中检索此数据:

    @if(TempData[DataToBePassed] != null)
    {
        var dataFromFirstView = TempData[DataToBePassed];
    }
    

    有关更多信息,请查看When to use ViewBag, ViewData, or TempData in ASP.NET MVC 3 applications。希望这会有所帮助...

    【讨论】:

      【解决方案2】:

      您可以将模型放在控制器的 TempData 属性中,这样它在下一个请求中自动可用。

      更多here

      【讨论】:

      • 这会起作用(或另一个答案中提到的会话解决方案),但存储在临时数据中的实例与传递给表单提交操作的实例不同。因此,我必须手动将属性值复制到 MVC 在表单提交操作中自动创建的实例(忽略表单提交中我真正关心的属性)。这似乎比只有隐藏的表单字段更糟糕。
      • 我最终使用了这种方法。我对必须将存储在临时数据中的实例的值复制到从 POST 填充的实例中并不感到兴奋,但是在考虑了隐藏表单字段的安全问题之后,这似乎是最好的方法。如果有一种方法可以让 MVC 在从 POST 填充值时更新现有实例,那就太好了。
      【解决方案3】:

      找到了我正在寻找的东西,我只是还没有使用 MVC 足够了解它。 Controller.UpdateModel 方法完全符合我的要求。

      示例(使用问题中的代码):

      [HttpPost]
      public ActionResult DoSomethingWithSelectedResults()
      {
          // Load initial model data here, in this case I had simply cached the results in
          // temp data in the previous action as suggested by Emeka Awagu.
          ResultsViewModel model = (ResultsViewModel)TempData["results"];
      
          // Call UpdateModel and let it do it's magic.
          UpdateModel(model);
      
          // ...
          return View(new DoSomethingWithSelectedResultsViewModel
          {
              SelectedResults = model.Results.Where(r => r.Selected).ToList(),
              SomeOtherProperty = "...",
              // ...
          });
      }
      

      使用这种方法,我能够消除所有隐藏的表单字段,并且不必编写任何自定义复制逻辑,因为UpdateModel 会自动处理它。

      注意:我确实必须实现一些自定义模型绑定器才能让字典和集合正常工作(请参阅hereherehere)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-18
        • 1970-01-01
        • 1970-01-01
        • 2022-01-07
        • 2011-12-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多