我有一个视图模型,用于在一个视图上显示表单,然后还用于表示操作的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>
}
答案 0 :(得分: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。希望这会有所帮助...
答案 1 :(得分:0)
您可以将模型放在控制器的TempData属性中,这样它就可以在下一个请求中自动使用。
更多here
答案 2 :(得分:0)
找到了我想要的东西,我还没有和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
会自动处理它。