在我的项目中,我创建了一项调查,我将此调查链接到公司并选择要参与的用户。我选择调查模板,添加额外的问题并设置有关调查的信息,如开始和结束日期。
总而言之,结果是一个复杂的视图,其中包含来自域的许多部分的数据。 我为这个视图创建了一个ViewModel,其中包括所有公司的列表(因为我需要在下拉列表中选择公司)。
现在令人烦恼的是,当我提交保存时,如果我有一个模型状态错误,那么我想重新显示视图,但因为我所提取的所有数据,如所有公司的列表都没有从客户端发送(即使是viewmodel支持它)我必须在再次显示表单之前再次填充所有列表/变量。
我想我可以创建一个创建下拉列表的视图,但是因为下拉需要将它的值插入到我在CompanyId下的调查中,这也不是很明显。
我认为自定义模型绑定器也可以做到这一点。我在这里要求感受那里最好的解决方案。如果我想重新考虑整个战略。
答案 0 :(得分:2)
模型绑定器可能有助于该过程,但我不认为它是一个完整的解决方案。首先,模型绑定器在实例化模型时可能无法“知道”您的意图。例如,如何知道您稍后在操作方法中认为模型无效?
我通常有一个单独的方法(甚至是一个单独的类),其唯一目的是管理构建适合于该情况的视图模型的数据。
然后,action方法告诉这个帮助器它想要什么,允许它作为进程的调控器服务于它的目的。例如,控制器可以决定:
我将这个视图模型称为“组合”。从本质上讲,您将向视图呈现完整视图模型所需的数据汇总在一起。这些数据可能来自各个地方。
我描述了composition process in more detail here。我已经编写了一个完整的框架来支持ASP.Net MVC的组合模式(闭源,仅仅是因为时间)。我发现它使得支持复杂的视图模型变得更加容易,并且极大地改进了我的代码重用。
此示例将进程保留在控制器内(而不是单独的类),并专注于指定一些简单的选项。
[Flags]
public enum CompositionOptions
{
PopulateFromDomainModel = 1,
Hydrate = 2
}
[HttpGet]
public ActionResult Edit( int id)
{
var model = new ViewModel();
// the controller states exactly what it wants
Compose( model, CompositionOptions.PopulateFromDomainModel | CompositionOptions.Hydrate, id );
}
[HttpPost]
public ActionResult Edit( ViewModel model )
{
if( !ModelState.IsValid )
{
// Rebuild values which weren't contained in the POST. Again, the
// controller states exactly what it needs.
Compose( model, CompositionOptions.Hydrate );
return View( model );
}
// Use POST-redirect-GET pattern, allowing the page to reload with the changes
return RedirectToAction( "Edit", new { id = model.Id } );
}
private void Compose( ViewModel model, CompositionOptions options, int? id = null )
{
// This logic can become quite complex, but you are generally checking for
// existing data source (domain models) and what you should populate and
// what fields you should preserve.
if( id != null && options.HasFlag( CompositionOptions.PopulateFromDomainModel ) )
{
// get your domain model from a repository and populate the
// properties of the view model
}
if( options.HasFlag( CompositionOptions.Hydrate ) )
{
// set values on the view model which won't be included in
// a POST, and thus must be rebuilt with every roundtrip
}
}
答案 1 :(得分:1)
一种可能性肯定是Tim建议的自动补液。
然而,我最终采用的方法是Tim G Thomas在此提出的建议:http://timgthomas.com/2013/09/simplify-client-side-validation-by-adding-a-server/
这意味着除非数据有效,否则数据永远不会离开客户端,这意味着需要再次进行补液。 它确实需要javascript,这对我来说是可以接受的,因为你再也不需要为视图补充水分了。