在我的MVC应用程序中,我通常ViewModel
执行Edit
等操作,主要用于填充要修改的属性的选择列表。例如,我的Model
看起来像这样:
class MyModel{
public int? NavPropID {get; set;}
public AnotherModel NavProp {get; set;}
...
}
现在我想知道,我应该如何设计我的ViewModel
来引用NavProp。
class MyViewModel{
public int? NavPropID {get; set;}
public AnotherModel NavProp {get; set;}
...
}
我应该同时使用NavPropID
和NavProp
,还是应该只使用ViewModel
中的一个(?)?
我一开始只想使用NavProp
,因为对我来说感觉更自然(我觉得它隐藏了数据库实现细节,而且我是如何在WPF和MVVM中做的)。但是在我的编辑视图中,我有类似的东西:
@Html.DropDownListFor(model => model.NavProp,
new SelectList(Model.AllAnotherModels.Select(
i => new {Item = i, Text = i.Name}), "Item","Text"))
在Edit操作的回发中,我可以看到绑定器未正确绑定NavProp
,因为attemptsValue的类型为string,值为NavProp的类名(我猜它意味着它使用ToString ()方法回发给控制器)。如何使其适用于回发行动?
然后我尝试在NavPropID
中只有ViewModel
。但是存在两个问题:1)这意味着我必须在使用NavProp
从AutoMapper
映射回ViewModel
之前在控制器中加载实际的Model
。我觉得这超出了控制器的责任2)即使我在控制器中加载了实际的属性,我在稍后通过调用DBSet.Attach()进行更新时也遇到了一些问题。
那么ViewModel
引用Model
中的导航属性的最佳做法是什么?
更新:
这是我Edit
动作的回发功能。它是通用的我认为所以我没有首先粘贴它。
[HttpPost]
public ActionResult Edit(MyViewModel vm)
{
if (ModelState.IsValid)
{
... // I use Automapper to map back to Model and then
// use UnitOfWork and Repository to update the Model
}
}
我的ModelState.IsValid
是假的,所以无法继续。正如我所提到的,然后我检查了ModelState(字典),发现NavProp
无效,attemptedValue
是类名,而我认为它应该是属性的实际值。
答案 0 :(得分:1)
关于在基本视图模型中使用NavPropID
,我们需要确定是否适合展平您的视图模型。
如果视图模型适用于显示单个导航属性的页面。信息,我很想得到以下信息:
// Domain model
public class MyModel
{
public int? NavPropID { get; set; }
public NavProp NavProp { get; set; }
...
}
// Nav prop domain model
public class NavProp
{
public int? NavPropID { get; set; }
// Another property of your navigation property
public string AnotherProperty { get; set; }
}
// Flat view model containing all your navigation properties' properties
public class MyViewModel
{
public int? NavPropID { get; set; }
public string AnotherProperty { get; set; }
}
如果你想要,你可以引入另一个视图模型来表示你的NavProp项目 - 但如果你乐意将它弄平,那就太过分了:
// Domain model
public class MyModel
{
public int? NavPropID {get; set;}
public NavProp NavProp {get; set;}
...
}
// Nav prop domain model
public class NavProp
{
public int? NavPropID {get; set;}
// Another property of your navigation property
public string AnotherPropery {get; set;}
}
// View model representing your navigation property
public class NavPropViewModel
{
public int? NavPropID { get; set; }
public string AnotherProperty { get; set; }
}
// Main view model
public class MyViewModel
{
// Use another view model that represents your NavProp
public NavPropViewModel NavProp { get; set; }
...
}
我想说控制器无需将从业务层收到的对象映射到视图模型,反之亦然。
为了使这个更清洁,我会介绍DTO来映射到哪个可以传递到您的业务层。 Check out general comments on this post.
<强>更新强>
以下是如何使用MyViewModel
字段创建表单以回发到NavPropViewModel
:
示例视图:
@model MyViewModel
@using (Html.BeginForm())
{
@Html.LabelFor(x => x.NavProp.AnotherProperty)
@Html.TextBoxFor(x => x.NavProp.AnotherProperty)
}
控制器示例:
[HttpPost]
public ActionResult Edit(MyViewModel vm)
{
// Get the posted value of AnotherProperty
var postedValue = vm.NavProp.AnotherProperty;
}