37

我们可以为创建和编辑操作提供一个单一的剃刀视图吗?

如果是,我们如何实现这一目标?

4

7 回答 7

53

我不推荐它。

这应该是一个相当长的答案,因为在正常的 MVC GET/POST 工作流的过程、请求和工作流中涉及到很多事情。我将尝试用所需的最少信息来回答您的问题,以及为什么我不建议使用相同的视图。

首先,为什么?

  1. 您无法控制视图,这可能会过度发布;
  2. 没有灵活性;
  3. 不可重用的视图或部分;
  4. 很难维护视图(必须在两个操作上测试视图中的一个更改)。

我建议的方法是使用不同的操作/视图,但共享通用代码:

正常创建两个视图。

您将有重复的代码,但并非所有代码都相同,例如,您可能不想在创建操作上发送 ID,这与您的问题没有直接关系,但使用相同的视图意味着您也在发送相同的数据,不建议这样做,特别是对于过度发布或批量分配。有关此处批量分配的更多信息(我在这里使用的是一种架构方法)。

因此,让我们从您将在控制器中收到的内容开始。在这种情况下,我使用了继承,但这不是唯一的策略。

绑定模型

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;}
}

这将确保您发送到 Create and Edit 的数据是最少需要的,仅此而已。

然后让我们看看将被发送到视图的视图模型,对于这个例子,我将包含一个列表,它将用于选择一些值,但不应该(列表)发布到控制器,只有选定的值。

查看模型

public class CreateViewModel : CreateBindingModel {
    public IEnumerable<SelectListItem> CountryList {get;set;}
}

public class UpdateViewModel : UpdateBindingModel {
    public IEnumerable<SelectListItem> CountryList {get;set;}
}

如您所见,这为您提供了很大的灵活性,但仍然有一些重复的代码(两个视图的视图模型所需的额外信息),可以通过多种方式缓解(取决于需求/上下文):

  1. 有一个动作来检索公共数据并使用@Html.Action("GetCountryList");
  2. 使用相同的 View Model akaCreateUpdateViewModel并丢弃视图中的额外UpdateBindingModel属性,但仍然在 POST 上发布相应的模型。
  3. 将您的绑定模型作为属性并在特定视图中选择一个或另一个。(更好地使用@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");
}

以及您的观点:

意见

Update.cshtml
<form action="Update">
    @Html.HiddenFor(Model.Id);
    @Html.Partial("EditFieldsPartial")
    <button>delete</button> // no delete button on create.
    <button>create new</button> // you can have a create new instead of update.
</form>

Create.cshtml
<form action="Create">
    @Html.Partial("EditFieldsPartial")
</form>

注意:代码不完整,为了简洁明了,在大多数情况下没有使用帮助程序。不要复制粘贴:D

于 2014-08-19T00:57:56.287 回答
47

你当然可以。

在发布时,检查您的控制器是否主键的值为 0,然后插入,否则更新。

创建和编辑的视图应该相同。

只要记住包括:

@Html.HiddenFor(model=>model.ID)

在你看来

例如:

模型:

public class DescriptionModel
{
    [Key]
    public int ID { get; set; }

    public string Description { get; set; }
}

创建编辑.cshtml:

@model DescriptionModel

@using (Html.BeginForm("CreateEdit"))
{
    @Html.HiddenFor(model=> model.ID)
    @Html.EditorFor(model=> model.Description)
    <input type="submit" value='Submit' />
}

描述模型控制器:

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);
}
于 2013-06-14T11:25:47.367 回答
3

绝对可以使用相同的模型共享视图以进行创建和编辑操作。但是,我强烈建议您三思而后行。在许多情况下,您会希望对编辑操作有不同的视图(例如,隐藏一些不应编辑的输入)以及模型可能略有不同,尽管它可能共享一些(或大部分)值。这些差异会导致视图中出现一些条件,检查您是在创建还是在编辑 - 这可能会使代码混乱。 结论:在决定是否共享视图之前,请先考虑一下编辑屏幕与创建屏幕有多大不同,然后您才能决定。

于 2014-11-28T09:44:11.943 回答
2

我不推荐这种方法,但是您可以将主表单从部分加载到两个视图中

于 2013-06-14T11:25:16.490 回答
2

你当然可以,但通常这是我会尽量避免的事情。如果创建和编辑操作几乎相同,那么您最终会在控制器中复制大量代码。通常在这种情况下,我的“添加”控制器上只有几个字段,然后在添加项目后,我会将用户重定向到编辑页面,他们可以在其中填写其余信息。

于 2013-06-14T11:26:11.860 回答
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);
        }
于 2013-09-30T08:04:31.567 回答
-1

所以,让我们想一想。如果 MVC 规定代码/视图/等是重复的,那么这肯定是一个缺陷吗?作为一名程序员,我永远不想重复任何努力无论其他任何事情。

于 2020-01-05T10:22:54.857 回答