I'm upgrading from sitecore 7.2 to sitecore 8.1. I have 5 years of experience with Web Forms but only a few months of exposure to MVC. In addition to upgrading to 8.1 my boss wants to change from Web Forms to MVC. My company has somewhat complicated form logic in Sitecore with Asp.Net Web Forms where each form field is its own Sublayout(User Control). This allows the content editor to include, not include, and reorder form fields based on the requirements given by the business. Here's how I accomplish this in Web Forms (BTW we also use GlassMapper): Form Markup Code Snippet:
<div id="formInputSection" runat="server">
<div id="fields">
<p class="required italic <%=reqFieldTextColor %>">
<sc:Text ID="formReqFields" Field="Required Fields Text" runat="server" ClientIDMode="Static" DataSource="<%#lpOptions.Paths.FullPath %>" />
</p>
<asp:UpdatePanel ID="formUpdatePanel" runat="server">
<ContentTemplate>
<asp:Panel ID="formPanel" runat="server">
<asp:ValidationSummary ID="valSumFormSubmit" runat="server" DisplayMode="BulletList" ValidationGroup="formSubmit" CssClass="errorMsg" />
<div>
<sc:Placeholder ID="FormFieldsSect" Key="v2_ph_form_fields_col1" runat="server" />
</div>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
</div>
<div id="form_action_submit" runat="server" class="form-action submit">
<asp:LinkButton ID="btnSubmitForm1" CssClass="form-input submit white" OnClientClick="ValidateAndDisableButton();" OnClick="submit_Click" UseSubmitBehavior="false" runat="server" ClientIDMode="Static" Text="<%#Model.Form_Submit_Text %>" ValidationGroup="formSubmit" />
<sc:Link ID="pgEditorFormSubmit1" Field="Editor Confirmation Link" CssClass="form-input submit white" runat="server" DataSource="<%#lpOptions.Paths.FullPath %>" Visible="false">
<sc:Text Field="Form Submit Text" ID="pgEditorSubmitText1" runat="server" ClientIDMode="Static" DataSource="<%#lpOptions.Paths.FullPath %>" Visible="false" />
</sc:Link>
</div>
Above, is the important part of the FormSublayout, that includes the an UpdatePanel that contains the placeholder for the individual form field sublayouts. As you can see I also have dynamic validation based on what fields you add into the "v2_ph_form_fields_col1" placeholder.
Next is the Markup for one of the basic field sublayouts. I'll use FirstName...
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="FirstNameField.ascx.cs" Inherits="MyNamespace.FirstName" %>
<%@ Register TagPrefix="sc" Namespace="Sitecore.Web.UI.WebControls" Assembly="Sitecore.Kernel" %>
<div class="clearfix form-input field text <%=LabelStyle %>">
<asp:Label ID="Label1" AssociatedControlID="txtFirstName" Text="<%#Editable(x => x.First_Name) %>" runat="server" />
<asp:TextBox ID="txtFirstName" runat="server" ClientIDMode="Static" type="text"></asp:TextBox>
<asp:RequiredFieldValidator ID="validFirstName" runat="server" ControlToValidate="txtFirstName" ErrorMessage="<%#Model.First_Name_Required %>"
Enabled="true" ValidationGroup="formSubmit" Display="None"></asp:RequiredFieldValidator>
</div>
<br />
This field sublayout like all of our fields is stand alone. It can be added to any of our forms and function without error. The Code Behind writes its input to session and on submit we take all values in session and map it to our contact object which would be our Model in MVC...
public partial class FirstName : InheritsFromGlassUserControl<FormFields>
{
protected override void Page_Load(object sender, EventArgs e)
{
if (this.Visible == true)
{
SitecoreContext context = new SitecoreContext();
Model = context.GetItem<FormFields>(Sitecore.Context.Database.GetItem(((Sublayout)Parent).DataSource).ID.Guid);
//ls is an object that we grab from session to update and put back into session
//to handle cross user control communication and such
ls = GetSession();
LabelStyle = ls.MergeLabels ? "merge-label" : string.Empty;
if (!string.IsNullOrWhiteSpace(txtFirstName.Text))
{
ls.CurrentLead.FirstName = txtFirstName.Text;
}
else
{
if (!IsPostBack)
{
if (!string.IsNullOrWhiteSpace(ls.CurrentLead.FirstName) && !ls.IsReferralForm)
txtFirstName.Text = ls.CurrentLead.FirstName;
}
}
//Put updated values in "ls" back into session for the next field to update, with its input
SessionDetails = ls;
SetRenderingParameters();
}
this.DataBind();
}
}
The question I have is what would be the best way to implement such a solution, in MVC? I don't have much experience in MVC and rather than just code up a sloppy solution I would like to know if someone had a more best practices example of how they would(have) implement(ed) stand alone form fields given the BeginForm() in MVC posts to a model, yet the glassmapper "model" is responsible for the field label and field validation error message content that is populated from sitecore. I haven't been able to get both models coexisting on the same cshtml file. I know this is complicated but the concept of plug and play form fields is a very valuable solution for businesses. And I figured out one that works for me in Web Forms; just having trouble wrapping my head around doing it in MVC.