我有一个列出所有自行车的页面(Bike.cshtml)。单击单个自行车时,我将转到编辑页面(BikeEdit.cshtml)。在编辑器的底部,我有两个链接。
@Html.ActionLink("Cancel", "Bikes", "Home")
@Html.ActionLink("Update", "Bikes", "Home")
两种情况都应该返回列出自行车的页面。显然,在第二个中我希望将模型对象的更改存储到DB。我很想通过像这样发送模型来解决它。
@Html.ActionLink("Cancel", "Bikes", "Home")
@Html.ActionLink("Update", "Bikes", "Home", @Model, null)
然而,我感觉有一种更好的方法来处理它。从自行车观众的控制器管理储蓄中有一些令人不安的事情。
我能想到的另一种方法是添加一个新动作 BikeSave ,并在其中执行保存。但是,返回的视图实例不会基于Bikes.cshtml而是基于BikeSave.cshtml。我可以想象我可以使用 RedirectToAction ,但我感到不确定。我不想用“胶带”设计一些东西。
所以我摇摇头不能决定......
答案 0 :(得分:1)
当用户点击更新按钮时,您应该将表单提交到您的HttpPost操作方法,您将更新数据库,然后重定向到主页/自行车页面。
假设您的GET操作是这样的
public ActionResult BikeEdit(int id)
{
var bikeEditVm=new BikeEditVm { Id=id};
var bikeEntity = db.Bikes.FirstOrDefault(s=>s.Id==id);
if(bikeEntity!=null)
{
bikeEditVm.ModelName=bikeEntity.ModelName;
bikeEditVm.Color=bikeEntity.Color;
return View(bikeEditVm);
}
return View("NotFound"); // return a bike not found view to user
}
其中BikeEditVm
是编辑视图的视图模型,如下所示
public class BikeEditVm
{
public int Id {set;get;}
public string ModelName {set;get;}
public string Color {set;get;}
}
在您对BikeEditVm强类型的视图中,您将所有可修改字段保留在form
标记
@model BikeEditVm
@using(Html.BeginForm())
{
<label>ModelName</label>
@Html.TextBoxFor(s=>s.ModelName)
<label>Color</label>
@Html.TextBoxFor(s=>s.Color)
@Html.HiddenFor(s=>s.Id)
<input type="submit" value="Update" />
}
@Html.ActionLink("Cancel","Bikes","Home")
您将有一个HttpAction方法来处理表单发布,您将从数据库中读取现有实体,更新要更新的相关字段并将其保存回来。
[HttpPost]
public ActionResult BikeEdit(BikeEditVm model)
{
var bikeEntity = db.Bikes.FirstOrDefault(s=>s.Id==model.id);
if(bikeEntity!=null)
{
bikeEntity .ModelName = model.ModelName;
bikeEntity .Color = model.Color;
db.Entry(bikeEntity).State=EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Bikes","Home");
}
return View("NotFound");
}
编辑: 回答OP在评论中为未来读者提出的一些问题。
(1)我测试跳过[HttpPost]并且它仍然有效。应该吗?
更新数据的任何内容都应该是HttpPost方法。否则,人们可以通过url(GET方法)访问您的操作方法并传递表单字段名称值,并可以尝试更新您的数据。(您的授权检查如果)
,可以阻止这种情况(2)你的Html.BeginForm()如何知道路由?我正在使用 Html.BeginForm(动作,控制器)。
如果您没有向BeginForm
方法传递任何参数,它会将表单操作值设置为当前网址。例如:如果您在客户/创建GET操作视图,您的表单将发布到customer / create。您可以使用不同的重载来覆盖此行为,您可以在其中指定不同的操作方法/控制器名称。
(3)如果我想要一个字段向上/向下传递但不是 可编辑/可见,我应该使用CSS来隐藏它吗?有一个很好的 控制屏幕外存储。
如果您不希望该字段可编辑/可见,请不要将事件传递给您的视图。在视图模型中仅包含您在视图中真正需要的属性。阅读有关如何防止过度发布的下一个回复。
(4)通常最好有一个专门的模型 查看而不是使用EF中的那个?
是的。如果您使用ORM创建的实体类在操作方法和视图之间传输数据,那么您正在构建一个紧密耦合的解决方案。如果您明天因任何原因决定不使用EF作为您的数据访问层,该怎么办?你想去更新你的所有观点吗?您的视图模型特定于视图。因此,请仅保留视图所需的属性/字段。这也可以帮助您prevent overposting。