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
I put the form itself in a user control - say, Views/Shared/WidgetForm.ascx. I put all form fields in this user control, but NOT the form tags themselves.
The views, say Views/Widgets/New.aspx and Views/Widgets/Edit.aspx, have the form tags in them and all the "surroundings" - instructions for filling in the form, page title, etc etc. Then they include the user control inside the form tags.
The user control simply takes a Widget object, and displays a form based on the results. Putting sensible defaults in new Widget options therefore becomes important, but you're doing that anyway, right? ;)
Do not use the same controller action. New = HTTP POST; edit = HTTP PUT, so that's two different things. Both actions can and should be on the same controller, though.
I like the idea of using a user control for common features (e.g., editors), and wrapping that in action-specific views for stuff which should only appear on new or edit, but not both.
this is not always the best practice because it depends on the case, here's how i did it
1/ i combined the controller actions for create and edit
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/ i combined the edit and create views into one view i call Creedit
// if you need to display something unique to a create view
// just check if the Model is null
@if(Model==null){
}
so i have 1 view and 2 actions (1 post and 1 get) instead of 2 views and 4 action.
NerdDinner will really show the way.
<%@ 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>
<%@ 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>
<%@ 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>
<% } %>
Take into account that this form is using Html.EditorForModel()
, which is an innovative method for generating all the fields at once, and you have to study its disadvantages before using it. But you can easily take the rest of the example to separate your common form from the create and edit views.
Finally you can view the controller code here if you are interested.