ASP.NET MVC - 使用相同的表单来创建和编辑

时间:2008-12-30 10:09:15

标签: asp.net-mvc forms

创建用于创建新模型和编辑现有模型的表单的最佳实践方法是什么?

有没有人可以指导我的教程?

10 个答案:

答案 0 :(得分:37)

NerdDinner真正显示出来。

Create.aspx

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<NerdDinner.Models.Dinner>" MasterPageFile="~/Views/Shared/Site.Master"  %>
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
    Host a Nerd Dinner
</asp:Content>
<asp:Content ID="Create" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Host a Dinner</h2>
    <% Html.RenderPartial("DinnerForm"); %>
</asp:Content>

Edit.aspx

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<NerdDinner.Models.Dinner>"
    MasterPageFile="~/Views/Shared/Site.Master" %>
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
    Edit: <%:Model.Title %>
</asp:Content>
<asp:Content ID="Edit" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Edit Dinner</h2>
    <% Html.RenderPartial("DinnerForm"); %>
</asp:Content>

DinnerForm.ascx

<%@ Language="C#" Inherits="System.Web.Mvc.ViewUserControl<NerdDinner.Models.Dinner>" %>
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcValidation.js" type="text/javascript"></script>
<% Html.EnableClientValidation(); %>
<%: Html.ValidationSummary("Please correct the errors and try again.") %>
   <% using (Html.BeginForm())
      { %>
   <fieldset>
       <div id="dinnerDiv">
           <%:Html.EditorForModel() %>
           <p>
               <input type="submit" value="Save" />
           </p>
       </div>
       <div id="mapDiv">
           <%: Html.EditorFor(m => m.Location) %>
       </div>
   </fieldset>
   <% } %>

考虑到此表单正在使用Html.EditorForModel(),这是一种用于一次生成所有字段的创新方法,您必须在使用它之前研究它的缺点。但是,您可以轻松地将示例的其余部分与创建和编辑视图分开。

最后,如果您有兴趣,可以查看controller code here

答案 1 :(得分:11)

答案 2 :(得分:8)

不要使用相同的控制器操作。新= HTTP PUT; edit = HTTP POST,这是两个不同的东西。但是,这两个动作都可以并且应该在同一个控制器上。

我喜欢将用户控件用于常用功能(例如编辑器),并将其包含在特定于操作的视图中,以用于只应出现在新内容或编辑内容中的内容,而不是两者。

答案 3 :(得分:5)

<强>假设

  1. 这对于用户在浏览器中查看不同操作的不同URL很有用。例如'/ pages / create'和'/ pages / edit / 1'。

  2. 这对于开发人员来说只有一个动作+视图对来创建和编辑页面是有好处的,因为它们通常非常相似。 (另外,每个实体最好有一个控制器。)

  3. <强>解决方案

    默认路线注册为“{controller} / {action} / {id}” 我们可以在之前添加另外两个规则

    {controller} / create(应指向'CreateOrEdit'动作)

    {controller} / edit / {id}(也应指向'CreateOrEdit'动作)

    我们现在可以拥有这样的东西:

    public static void RegisterRoutes(RouteCollection routes)
    {
      routes.MapRoute(
        name: "Create",
        url: "{controller}/create",
        defaults: new { controller = "Default", action = "CreateOrEdit" }
      );
    
      routes.MapRoute(
        name: "Edit",
        url: "{controller}/edit/{id}",
        defaults: new { controller = "Default", action = "CreateOrEdit" }
      );
    
      routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Default", action = "Index", id = UrlParameter.Optional }
      );
    }
    

    所以现在创建和编辑请求都将由'CreateOrEdit'操作处理。其他人将采用默认方式。

    接下来我们应该做的是在我们的控制器中为HttpGet和HttpPost添加'CreateOrEdit'动作:

    [HttpGet]
    public ActionResult CreateOrEdit(int? id)
    {
      return this.View(new CreateOrEditViewModelBuilder(this).Build(id));
    }
    
    [HttpPost]
    public ActionResult CreateOrEdit(CreateOrEditViewModel сreateOrEditViewModel)
    {
      if (this.ModelState.IsValid)
      {
        Page page = new CreateOrEditViewModelMapper(this).Map(сreateOrEditViewModel);
    
        if (сreateOrEditViewModel.Id == null)
          this.UnitOfWork.GetRepository<IPageRepository>().Create(page);
    
        else this.UnitOfWork.GetRepository<IPageRepository>().Edit(page);
    
        this.UnitOfWork.Save();
        return this.RedirectToAction("Index");
      }
    
      return this.View(сreateOrEditViewModel);
    }
    

    最后我们要添加名为'CreateOrEdit'的视图。我们可以使用'this.Model.Id == null'来了解我们是否创建或编辑。

    <强>结果

    现在我们没有重复的代码,可以有这样的明显网址:

    / pages(查看所有页面)

    / pages / create(创建新页面)

    / pages / edit / 1(编辑现有页面)

    / pages / delete / 1(删除现有页面)

    我希望它会帮助别人!

答案 4 :(得分:1)

它可能(应该是IMO)一个控制器但不同的控制器动作。还要确保您具有与适当操作相关联的正确HTTP谓词。按照E Rolnicki发布的教程,你就可以了!

快乐编码!!

答案 5 :(得分:1)

这并非总是最佳做法,因为它取决于具体情况,这是我如何做到的

1 / 我结合了用于创建和编辑的控制器操作

public PartialViewResult Creedit(string id = null)
{
    if (id == null)
    {
        // Create new record (this is the view in Create mode)
        return PartialView();
    }
    else
    {
        // Edit record (view in Edit mode)
        Client x = db.ClientSet.Find(id);
        if (x == null) { return PartialView("_error"); }
        // ...
        return PartialView(x);
    }
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Creedit(Client x)
{
    if (x.id == null)
    {
        // insert new record
    }
    else
    {
        // update record
    }
}

2 / 我将编辑和创建视图合并到一个视图中我称之为Creedit

// if you need to display something unique to a create view
// just check if the Model is null
@if(Model==null){
}

所以我有1个视图和2个动作(1个帖子和1个获取),而不是2个视图和4个动作。

答案 6 :(得分:0)

我将表单本身放在用户控件中 - 比如Views / Shared / WidgetForm.ascx。我将所有表单字段放在此用户控件中,但不是表单标记本身。

视图,例如Views / Widgets / New.aspx和Views / Widgets / Edit.aspx,其中包含表单标签和所有“环境” - 填写表单,页面标题等的说明。然后它们在表单标记中包含用户控件。

用户控件只需一个Widget对象,并根据结果显示一个表单。因此,在新的Widget选项中设置合理的默认值变得很重要,但无论如何你都是这样做的,对吧? ;)

答案 7 :(得分:0)

我认为我的系统效果非常好。在我的共享视图中,我有两个通用形式,Edit.aspx和New.aspx

然后在我的特定视图文件夹中,我有一个名为EditItems.ascx的控件

在我的编辑表单中,我有用于编辑的表单标签和特定按钮,在新表单中,我有新的表单标签和特定按钮。在每个我有Html.RenderPartial(“EditItems.ascx”)

这样您的用户控件可以强类型,但您重复使用编辑和新页面的外观。

现在在某些情况下,您的新网页可能与“编辑”页面的布局不同。在这种情况下,只需将“Edit.aspx”添加到您的特定视图文件夹。

我发现这给了我最好的重用组合,同时在我需要时仍允许完全自定义。至于控制器动作,是的,它们应该是单独的动作。

答案 8 :(得分:0)

如果实体有某种内部私钥(例如“id”成员始终> 0),您可以使用/ Edit / 0而不是/ Create

答案 9 :(得分:0)

我使用类似

的东西
[HttpGet]
public ActionResult EntityEdit(Guid id)
{
    return View();
}

[HttpGet]
public ActionResult EntityCreate()
{
   return View("EntityEdit");
}

这似乎工作正常。