我们可以为创建和编辑操作创建一个剃刀视图吗?
如果是,我们如何实现这一目标?
答案 0 :(得分:47)
我不推荐它。
这应该是一个相当长的答案,因为正常的MVC GET / POST工作流程的过程,请求和工作流程涉及很多事情。我将尝试用所需的最少信息回答您的问题,以及为什么我不建议使用相同的视图。
首先,为什么?
我建议的方法是使用不同的操作/视图,但共享公共代码:
正常创建两个视图。
您将拥有重复的代码,但并非所有代码都相同,例如,您可能不希望在创建操作上发送ID,这与您的问题没有直接关系,但使用相同的视图意味着您也发送相同的数据,这是不推荐的,特别是对于过度发布或批量分配。有关质量分配here的更多信息(建筑方法就是我在这里使用的)。
那么让我们从您将在控制器中收到的内容开始。 在这种情况下,我使用了继承,但这不是唯一的策略。
绑定模型
public class UpdateBindingModel : CreateBindingModel {
// since we are not using the same binding model,
// we can have a "real" validation rules on our update binding and view.
[Required]
public int? Id {get;set;}
}
public class CreateBindingModel {
// no id here prevent overposting.
[Required]
public string Name {get;set;}
[Required]
public int? CountryId {get;set;}
}
这将确保您发送到“创建”和“编辑”的数据是最不需要的,而不是其他任何内容。
然后让我们看看将发送到View的View Models,对于这个例子,我将包含一个List,用于选择一些值,但不应该发布(列表)到控制器,只有选定的值
查看模型
public class CreateViewModel : CreateBindingModel {
public IEnumerable<SelectListItem> CountryList {get;set;}
}
public class UpdateViewModel : UpdateBindingModel {
public IEnumerable<SelectListItem> CountryList {get;set;}
}
正如您所看到的,这为您提供了很大的灵活性,但仍然有一些重复的代码(两个视图的视图模型所需的额外信息),可以通过多种方式(根据需求/上下文)进行缓解:
@Html.Action("GetCountryList");
CreateUpdateViewModel
属性,但仍然在POST上发布相应的模型。UpdateBindingModel
而不是部分,因此Model Binder无需对代码进行其他更改即可使用控制器操作如下所示:
<强>控制器强>
@Html.EditorFor
您的观点:
<强>视图强>
[HttpGet]
public ActionResult Create(){
ViewData.Model = new CreateViewModel();
return View();
}
[HttpPost]
public RedirectToRouteResult Create(CreateBindingModel binding) {
// check valid model state and create data
return RedirectToAction("Index");
}
[HttpGet]
public ActionResult Update(int id) {
var objectToEdit = service.GetObjectToEdit(id);
ViewData.Model = new UpdateViewModel(objectToEdit);
return View();
}
[HttpPost]
public RedirectToRouteResult Update(UpdateBindingModel binding) {
// check valid model state and update data
return RedirectToAction("Index");
}
注意:代码不完整,在大多数情况下都没有使用帮助程序,以简洁明了。不要复制粘贴:D
答案 1 :(得分:42)
当然可以。
在帖子上,检查您的控制器是否主键值为0然后插入,否则更新。
“创建和编辑”视图应该相同。
请记住包括:
@Html.HiddenFor(model=>model.ID)
在你看来
例如:
型号:
public class DescriptionModel
{
[Key]
public int ID { get; set; }
public string Description { get; set; }
}
CreateEdit.cshtml:
@model DescriptionModel
@using (Html.BeginForm("CreateEdit"))
{
@Html.HiddenFor(model=> model.ID)
@Html.EditorFor(model=> model.Description)
<input type="submit" value='Submit' />
}
DescriptionModel控制器:
public ActionResult Create()
{
return View("CreateEdit", new DescriptionModel());
}
public ActionResult Edit(int id)
{
return View("CreateEdit", db.DescriptionModels.Find(id));
}
// Submit and add or update database
[HttpPost]
public ActionResult CreateEdit(DescriptionModel model)
{
if (ModelState.IsValid)
{
// No id so we add it to database
if (model.ID <= 0)
{
db.DescriptionModels.Add(model);
}
// Has Id, therefore it's in database so we update
else
{
db.Entry(model).State = EntityState.Modified;
}
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
答案 2 :(得分:2)
我不推荐这种方法,但您可以将主窗体从部分
加载到两个视图中答案 3 :(得分:2)
使用相同的模型,绝对可以为创建和编辑操作共享视图。 然而,我强烈建议您考虑两次。在许多情况下,您将需要具有不同的编辑操作视图(例如,隐藏一些不应该可编辑的输入)以及模型可能略有不同,尽管它可能共享一些(或大多数)值。这些差异将导致视图中的某些条件,检查您是否正在创建或编辑 - 这可能会使代码混乱。 结论:在决定是否拥有共享视图之前,请尝试考虑编辑屏幕与创建屏幕的差异程度,然后您可以决定。
答案 4 :(得分:1)
你当然可以,但通常这是我会尽量避免的。如果创建和编辑操作几乎相同,那么最终会复制控制器中的大量代码。通常在这种情况下,我的“添加”控制器上只有几个字段,然后一旦添加了项目,我就会将用户重定向到编辑页面,在那里他们可以填写其余的信息。
答案 5 :(得分:0)
[HttpGet]
public ActionResult myFun(int id = 0)
{
MyClass cls = new MyClass();
if (id == 0)
{
//Insert mode ... no data will be shown to textboxes , when primary key ie. id=0
//Display whole data
}
else
{
//Update mode... if id is not 0 ,data will be shown to textboxes
}
return View(cls);
}
答案 6 :(得分:-1)
所以,让我们考虑一下。如果MVC规定代码/视图/等重复,那一定是一个缺陷吗?作为程序员,我永远都不想重复任何努力 。