如何使用视图模型
好吧,经过一些研究,我无法理解“视图模型的事情”。
我没有找到任何文章来解释与简单地将实体作为模型传递给视图相比,使用 ViewModel 的步骤是什么。 使用纯实体时,它非常简单:
如果创建新条目,只需显示视图。如果是发布,验证,执行 Add(x) ,瞧!编辑时,填充一个对象并将其发送到视图。发布时,验证、更改状态并保存。这里没有秘密。
但我无法创建和编辑 ViewModel。有人可以帮我解决这个问题吗?
简而言之,我有这个 POCO:
public class Vessel
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public int ShipownerId { get; set; }
public virtual Shipowner Shipowner { get; set; }
}
public class Shipowner
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Vessel> Vessels { get; set; }
}
和这个视图:
@model INTREPWEB.Models.VesselCreateViewModel
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Vessel</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Vessel.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Vessel.Name)
@Html.ValidationMessageFor(model => model.Vessel.Name)
</div>
<div class="editor-field">
@Html.DropDownListFor(model => model.Vessel.ShipownerId, Model.Shipowners, String.Empty)
@Html.ValidationMessageFor(model => model.Vessel.Name)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
我创建了这个 ViewModel:
public class VesselCreateViewModel
{
public Vessel Vessel { get; set; }
public SelectList Shipowners { get; set; }
public VesselCreateViewModel()
{
using (INTREPDB db = new INTREPDB())
{
var list = db.Shipowners.ToList()
.Select(x => new SelectListItem
{
Text = x.Name,
Value = x.Id.ToString()
});
Shipowners = new SelectList(list, "Value", "Text");
}
}
public VesselCreateViewModel(int id)
{
using (INTREPDB db = new INTREPDB())
{
Vessel = db.Vessels.Find(id);
var list = db.Shipowners.ToList()
.Select(x => new SelectListItem
{
Text = x.Name,
Value = x.Id.ToString()
});
Shipowners = new SelectList(list, "Value", "Text");
}
}
}
如您所见,它会自动填充视图的集合以显示下拉菜单。我能够通过与仅使用模型相同的方式创建新容器。但在编辑这个东西时无法弄清楚我做错了什么。
这是错误的POST编辑方法:
[HttpPost]
public ActionResult Edit(VesselCreateViewModel vm)
{
if (ModelState.IsValid)
{
db.Entry(vm.Vessel).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vm);
}
我该怎么做才能拯救这个小怪物?
Ok, after some research I was unable to understand the "viewmodel thing".
I didn't find any article that explains me what are the steps to work with ViewModels compared to simply passing the Entity as a Model to the View.
When using the pure Entity it is pretty straight-forward:
If creating a new entry, just show the view. If is post, validate, do Add(x) and voilá! When editting, populate an object and send it to the View. When posting, validate, change the state and save. No secret here.
But I am unable to create and edit ViewModels. Can someone help me on this?
To be short, I have this POCOs :
public class Vessel
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public int ShipownerId { get; set; }
public virtual Shipowner Shipowner { get; set; }
}
public class Shipowner
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Vessel> Vessels { get; set; }
}
And this View:
@model INTREPWEB.Models.VesselCreateViewModel
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Vessel</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Vessel.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Vessel.Name)
@Html.ValidationMessageFor(model => model.Vessel.Name)
</div>
<div class="editor-field">
@Html.DropDownListFor(model => model.Vessel.ShipownerId, Model.Shipowners, String.Empty)
@Html.ValidationMessageFor(model => model.Vessel.Name)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
I've created this ViewModel:
public class VesselCreateViewModel
{
public Vessel Vessel { get; set; }
public SelectList Shipowners { get; set; }
public VesselCreateViewModel()
{
using (INTREPDB db = new INTREPDB())
{
var list = db.Shipowners.ToList()
.Select(x => new SelectListItem
{
Text = x.Name,
Value = x.Id.ToString()
});
Shipowners = new SelectList(list, "Value", "Text");
}
}
public VesselCreateViewModel(int id)
{
using (INTREPDB db = new INTREPDB())
{
Vessel = db.Vessels.Find(id);
var list = db.Shipowners.ToList()
.Select(x => new SelectListItem
{
Text = x.Name,
Value = x.Id.ToString()
});
Shipowners = new SelectList(list, "Value", "Text");
}
}
}
As you can see, it auto populates a collection for the View to show a DropDown menu. I was able to create new Vessels by doing the same way I do with only Models. But can't figure out what I'm doing wrong when editting this thing.
This is the wrong POST Edit method:
[HttpPost]
public ActionResult Edit(VesselCreateViewModel vm)
{
if (ModelState.IsValid)
{
db.Entry(vm.Vessel).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vm);
}
What should I do to save this little monster?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如您所见,在此代码中您仅使用 ViewModel 的模型部分。恕我直言,这是典型的,因此您将 ViewModel 传递给视图,但仅在编辑回发中绑定模型。
然后,如果需要,您可以根据更改的模型轻松地重新创建视图模型。
顺便说一句:在这种情况下,IMO ViewModel 是一个坏名字。如果我听到 ViewModel,我会想到 MVVM,但在这种情况下,视图模型只是某种静态类型的 View-Helper,不应该有任何行为。
as you can see you are only using the Model-part of your ViewModel in this code. This is IMHO typical so you pass the ViewModel to the View but only bind the Model in your Edit-Postback.
Then you can easily recreate the viewmodel based on the changed model if you have to.
BTW: IMO ViewModel is a bad name in this case. If I hear ViewModel I think of MVVM but this case the viewmodel is only some kind of static-typed View-Helper and should have no behavior.
Viewmodel 小摘自 Steve senderson 的书
如果你想保存视图模型,你可以使用 automapper
Viewmodel little excerpt from Steve senderson book
If you want to save view model you may use automapper
我猜您应该像在 VesselCreateViewModel 构造函数中一样将数据库调用包装在 using 块中。
您最终可以使用 ViewModel 中的命令来保存、编辑或删除数据,并将此命令绑定到视图上的按钮或其他控件。
我会向你推荐两本关于 MVVM 的好书,你会找到很好的例子,也很容易理解。
I'm guessing you should wrap around the db calls in a Using block just like in the VesselCreateViewModel constructors.
You could eventually use commands in your ViewModel to save, edit or delete your data and bind this command to Buttons or other Controls on the view.
I would recommend you two great books about MVVM, you find good examples, easy to understand them too.