操作的适当路由取消和存储
本文关键字:取消 存储 路由 操作 | 更新日期: 2023-09-27 18:28:44
我有一个列出所有自行车的页面(Bike.cshtml)。当单击单个自行车时,我会转到编辑页面(BikeyEdit.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但我觉得不确定。我不想用"胶带"设计东西。
所以我摇摆不定。。。
当用户单击更新按钮时,您应该向HttpPost操作方法提交一个表单,在那里您将更新数据库,然后重定向到Home/Bikes页面。
假设你的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
方法传递任何参数,它将把表单操作值设置为当前url。例如:如果您在customer/create GET操作视图中,您的表单将被张贴到customer/create。可以通过使用不同的重载来覆盖此行为,在重载中可以指定不同的操作方法/控制器名称。
(3) 如果我希望一个字段被向上/向下传递,但不被可编辑/可见,我应该使用CSS来隐藏它吗?如果有一个控制屏幕外存储。
如果您不希望字段是可编辑/可见的,请不要将其事件传递到您的视图。在视图模型中只包含视图中真正需要的属性。阅读下一篇关于如何防止过度张贴的回复。
(4) 为视图,而不是使用EF中的视图?
是的。如果你使用ORM创建的实体类在操作方法和视图之间传输数据,那么你就是在制作一个紧密耦合的解决方案。如果您明天出于任何原因决定不使用EF作为您的数据访问层,该怎么办?你想去更新你的所有视图吗?视图模型是特定于某个视图的。因此,只保留视图所需的属性/字段。这也将有助于您防止过度加注。