我有一个这样的视图模型:
public class EditVM
{
public Media.Domain.Entities.Movie Movie { get; set; }
public IEnumerable<Genre> Genres { get; set; }
}
电影是我想要编辑的真实实体。类型只是为了填充下拉列表。我打电话的时候我更喜欢这个:
@Html.TextBoxFor(m => m.Movie.Title)
在我的强类型视图中,输入控件的名称为"Title"
,而不是"Movie.Title"
我不希望使用ViewData
或类似内容将我的视图拆分为部分视图或丢失强类型视图。
有没有办法向View表达我不希望拥有Movie.
前缀?我注意到你可以设置:
ViewData.TemplateInfo.HtmlFieldPrefix = "x";
在控制器中,但不幸的是,似乎只允许添加附加前缀。将其设置为""
不会做任何事情。
这有什么工作吗?或者,如果我希望保留强类型视图和lambdas,我是否会遇到在这种情况下并非真正必要的不幸前缀?
感谢您的帮助。
更新
这是控制器的动作,可能会让事情更清晰。
public ActionResult Edit(int? id)
{
var vm = new EditVM
{
Movie = id.HasValue ? _movieSvc.Find(id.Value) : new Movie(),
Genres = AppData.ListGenres()
};
return View(vm);
}
[HttpPost]
public void Edit([Bind(Prefix = "Movie")]Movie m)
{
_movieSvc.AddOrUpdateMovie(m); //Exceptions handled elsewhere
}
答案 0 :(得分:5)
不,为了做你想做的事,你必须重写Html助手,然后你必须编写自己的模型绑定器。似乎很多工作都是为了获得最低收益。
唯一的选择是将Movie对象作为模型传递的Partial视图。但是,这需要您编写自己的模型绑定器才能识别它。
您必须执行m.Movie.Title的原因是ID具有正确的名称,因此模型绑定器可以将其识别为模型的成员。
根据您的更新:
您的选择是:
就个人而言,我只使用1或2,可能是2。
编辑:
根据您的上述更新。将代码更改为此(请注意,Genres不会回发到服务器,因此m.Genres在回发时将为null):
[HttpPost]
public void Edit(EditVM m)
{
_movieSvc.AddOrUpdateMovie(m.Movie); //Exceptions handled elsewhere
}
编辑:
我想到了另一种选择。你可以这样做:
@{ var Movie = Model.Movie; }
@Html.TextBoxFor(m => Movie.Title)
但是,如果出现验证错误,则必须重新创建EditVM。
答案 1 :(得分:1)
我有一个像这样的视图模型
我认为你可能对视图模型有什么误解。视图模型不应包含对您的域模型的任何引用,这些引用似乎是Movie
和Genre
类。我的意思是创建一个后缀为VM
的新类,并将所有域模型填充为属性并不是视图模型。视图模型是专门为满足视图要求而设计的类。
更正确的视图模型如下所示:
public class EditVM
{
public string MovieTitle { get; set; }
public IEnumerable<GenreViewModel> Genres { get; set; }
}
并且在您看来,您将拥有:
@Html.EditorFor(x => x.MovieTitle)
@Html.EditorFor(x => x.Genres)
答案 2 :(得分:1)
另一个选择是使用TextBox(string name, object value)
重载而不是TextBoxFor
:
@Html.TextBox("Title", Model.Movie.Title)
您也可以指定输入标记HTML而不是使用帮助程序。
另一种选择是将EditVM作为回发参数。这就是我要做的。我的post动作参数始终与.cshtml模型的类型相同。是的,会有像列表这样的属性为null,但你只是忽略它们。它还允许您优雅地处理发布错误,因为如果出现错误,您无论如何都需要返回该视图模型的实例,并且包含它们提交的值。我通常使用私有方法或DB层来处理检索进入ViewModel的各种列表,因为这些列表在回发时将为空,并且需要重新填充,而不会触及帖子中的属性。
使用现在的post方法,如果需要返回相同的视图,则必须创建一个新的EditVM,然后将任何已发布的值复制到其中,并仍然填充列表。使用我的方法,您可以消除其中一个映射步骤。如果您要发布多个内容,您的帖子操作中是否会有多个不同的参数?让它们自然地进入一个键入视图EditVM的参数。虽然在回发过程中可能在VM中具有那些空属性感觉很棘手,但是在View和回发IMO之间可以获得良好的可预测一致性。您不必花费大量时间考虑post方法中的哪些参数组合将从表单中获取所有数据。