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
Assumptions
This is good for the user to see different URLs for different actions in the browser. For example '/pages/create' and '/pages/edit/1'.
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!