ASP.NET MVC - using the same form to both create and edit

前端 未结 10 812
温柔的废话
温柔的废话 2021-01-30 05:27

Whats the best practice approach to creating a form that is used to both create new models and edit existing models?

Are there any tutorials that people can point me in

10条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2021-01-30 05:39

    Assumptions

    1. This is good for the user to see different URLs for different actions in the browser. For example '/pages/create' and '/pages/edit/1'.

    2. This is good for developer to have only one action+view pair both to create and edit pages because they are usually very similar. (Also, this is good to have one controller per entity.)

    Solution

    Default routes registration is '{controller}/{action}/{id}' We can add two more rules before this one:

    {controller}/create (should point to 'CreateOrEdit' action)

    {controller}/edit/{id} (should point to 'CreateOrEdit' action too)

    We can have now something like this:

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

    So now both create and edit requests will be handled by 'CreateOrEdit' action. Others will go the default way.

    Next what we should do is to add 'CreateOrEdit' action for HttpGet and HttpPost in our controller:

    [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().Create(page);
    
        else this.UnitOfWork.GetRepository().Edit(page);
    
        this.UnitOfWork.Save();
        return this.RedirectToAction("Index");
      }
    
      return this.View(сreateOrEditViewModel);
    }
    

    And the last we have to add view named 'CreateOrEdit'. We can user 'this.Model.Id == null' there to know whether we create or edit.

    Result

    Now we don't have duplicate code and can have obvious urls like this:

    /pages (to see all pages)

    /pages/create (to create new page)

    /pages/edit/1 (to edit existing page)

    /pages/delete/1 (to delete existing page)

    I hope it will help someone!

提交回复
热议问题