适当的操作路由取消和存储

时间:2016-01-01 22:21:49

标签: c# asp.net-mvc razor routing actionlink

我有一个列出所有自行车的页面(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 ,但我感到不确定。我不想用“胶带”设计一些东西。

所以我摇摇头不能决定......

1 个答案:

答案 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");
}

编辑: 回答O​​P在评论中为未来读者提出的一些问题。

  

(1)我测试跳过[HttpPost]并且它仍然有效。应该吗?

更新数据的任何内容都应该是HttpPost方法。否则,人们可以通过url(GET方法)访问您的操作方法并传递表单字段名称值,并可以尝试更新您的数据。(您的授权检查如果

,可以阻止这种情况
  

(2)你的Html.BeginForm()如何知道路由?我正在使用   Html.BeginForm(动作,控制器)。

如果您没有向BeginForm方法传递任何参数,它会将表单操作值设置为当前网址。例如:如果您在客户/创建GET操作视图,您的表单将发布到customer / create。您可以使用不同的重载来覆盖此行为,您可以在其中指定不同的操作方法/控制器名称。

  

(3)如果我想要一个字段向上/向下传递但不是   可编辑/可见,我应该使用CSS来隐藏它吗?有一个很好的   控制屏幕外存储。

如果您不希望该字段可编辑/可见,请不要将事件传递给您的视图。在视图模型中仅包含您在视图中真正需要的属性。阅读有关如何防止过度发布的下一个回复。

  

(4)通常最好有一个专门的模型   查看而不是使用EF中的那个?

是的。如果您使用ORM创建的实体类在操作方法和视图之间传输数据,那么您正在构建一个紧密耦合的解决方案。如果您明天因任何原因决定不使用EF作为您的数据访问层,该怎么办?你想去更新你的所有观点吗?您的视图模型特定于视图。因此,请仅保留视图所需的属性/字段。这也可以帮助您prevent overposting