After a long day, I finally got all the validation working as I intend it. The question I now have is how do I pass the model back and forth between each step? My basic setup is I have Business.cshtml that has my Wizard on it. For each step of the wizard I then retrieve the correct PartialView and render to the step. What I am unsure of how to do is how do you pass the model back and forth. I made the assumption using '@Url.Action("_BusinessFinancial", "Onboard",Model)' in the javascript would work but I am just not 100% how to save the model between each step and reuse it.
Here is my Business.cshtml
@using Kendo.Mvc.UI
@model Reverberate.BLL.Model.Form.Application.BusinessOnboarding.BusinessOnboardingModel
@{
ViewBag.Title = "Business Onboarding";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<style>
.wide {
width: 95%;
}
.field-validation-error {
color: red;
}
</style>
<!-- Wizard -->
@(Html.Kendo().Wizard()
.Name("wizard")
.Events(ev => ev.Select("onSelect"))
.Events(ev => ev.Done("onDone"))
.LoadOnDemand(true)
.HtmlAttributes(new { @novalidate = "" })
.ReloadOnSelect(false)
.Steps(s =>
{
s.Add<Reverberate.BLL.Model.Form.Application.BusinessOnboarding.BusinessOnboardingModel>()
.Title("Business Profile")
.ContentUrl(Url.Action("_BusinessProfile", "Onboard", Model))
.Buttons(b =>
{
b.Next().Text("Next");
});
s.Add<Reverberate.BLL.Model.Form.Application.BusinessOnboarding.BusinessOnboardingModel>()
.Title("Business Financial")
.ContentUrl(Url.Action("_BusinessFinancial", "Onboard", Model))
.Buttons(b =>
{
b.Previous().Text("Back");
b.Next().Text("Next");
});
s.Add<Reverberate.BLL.Model.Form.Application.BusinessOnboarding.BusinessOnboardingModel>()
.Title("Business Address")
.ContentUrl(Url.Action("_BusinessAddress", "Onboard", Model))
.Buttons(b =>
{
b.Previous().Text("Back");
b.Done().Text("Submit");
});
})
)
<script type="text/javascript">
var dataPartial1;
var dataPartial2;
var currentStep;
function onSelect(e) {
var form, contentUrl;
if (e.step.options.index < currentStep) {
}
else {
if (e.step.options.index == 1) {
form = $('#frmPartialBusinessProfile');
dataPartial1 = form.serialize();
contentUrl = '@Url.Action("_BusinessFinancial", "Onboard",Model)';
}
else if (e.step.options.index == 2) {
form = $('#frmPartial2');
dataLesions = form.serialize();
contentUrl = '@Url.Action("_BusinessAddress", "Onboard",Model)';
}
if (!form.valid()) {
e.preventDefault();
}
else {
e.step.options.contentUrl = contentUrl;
}
}
currentStep = e.step.options.index;
}
function onNextStep(e) {
if (e.step.options.index == 2) {
openDoc();
}
}
function onDone(e) {
var form = $('#frmMain');
if (form.valid()) {
form.submit();
}
}
var onAddMainSuccess = function (result) {
if (result.error) {
alert(result.error);
}
};
</script>
Here is my Onboard controller
using Kendo.Mvc.UI;
using Reverberate.Services;
using Kendo.Mvc.Extensions;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Reverberate.Model;
namespace CallCenterWebsiteHelper.Controllers
{
public class OnboardController : Controller
{
// GET: Campaign
private List<SelectListItem> StatesSelectList()
{
var slStates = new List<SelectListItem>();
var states = new Reverberate.BLL.General.StaticDataSet.Geographic().States();
for (int i = 0; i < states.Count; i++)
slStates.Add(new SelectListItem() { Text = states[i], Value = states[i] });
return slStates;
}
private List<SelectListItem> BusinessTypesSelectList()
{
var sl = new List<SelectListItem>();
var list = new Reverberate.BLL.General.StaticDataSet.BusinessInformation().BusinessTypeList();
for (int i = 0; i < list.Count; i++)
sl.Add(new SelectListItem() { Text = list[i], Value = list[i] });
return sl;
}
public ActionResult Business()
{
ViewBag.States = StatesSelectList();
ViewBag.BusinessTypeList = BusinessTypesSelectList();
var model = new Reverberate.BLL.Model.Form.Application.BusinessOnboarding.BusinessOnboardingModel();
model.BusinessProfileModel = new Reverberate.BLL.Model.Form.Application.BusinessOnboarding.BusinessProfileModel();
model.BusinessFinancialModel = new Reverberate.BLL.Model.Form.Application.BusinessOnboarding.BusinessFinancialModel();
return View("Business",model);
}
public ActionResult _BusinessProfile(Reverberate.BLL.Model.Form.Application.BusinessOnboarding.BusinessOnboardingModel viewModel)
{
ViewBag.States = StatesSelectList();
ViewBag.BusinessTypeList = BusinessTypesSelectList();
return PartialView("_BusinessProfile",viewModel);
}
public ActionResult _BusinessFinancial(Reverberate.BLL.Model.Form.Application.BusinessOnboarding.BusinessOnboardingModel viewModel)
{
ViewBag.States = StatesSelectList();
ViewBag.BusinessTypeList = BusinessTypesSelectList();
return PartialView("_BusinessFinancial", viewModel);
}
public ActionResult _BusinessAddress(Reverberate.BLL.Model.Form.Application.BusinessOnboarding.BusinessOnboardingModel viewModel)
{
ViewBag.States = StatesSelectList();
ViewBag.BusinessTypeList = BusinessTypesSelectList();
return PartialView("_BusinessAddress", viewModel);
}
/*
public ActionResult BusinessProfile()
{
return PartialView("_BusinessProfile");
}*/
}
}
here is my two partial views
_busiessprofile
@using Kendo.Mvc.UI
@model Reverberate.BLL.Model.Form.Application.BusinessOnboarding.BusinessOnboardingModel
@using (Html.BeginForm(null, null, FormMethod.Post, new { @id = "frmPartialBusinessProfile", @name = "frmPartialBusinessProfile" }))
{
<div style="width: 45%; float: left; border: 1px solid black" id="BusinessInfoEntry">
<h3>Business Profile</h3>
<fieldset>
<legend></legend>
<ol>
<li>
@Html.LabelFor(m => m.BusinessProfileModel.BusinessName)
<br />
@Html.TextBoxFor(m => m.BusinessProfileModel.BusinessName, new { maxlength = 200, @class = "wide" })
@Html.ValidationMessageFor(m => m.BusinessProfileModel.BusinessName)
</li>
<li>
@Html.LabelFor(m => m.BusinessProfileModel.FederalTaxId)
<br />
@Html.TextBoxFor(m => m.BusinessProfileModel.FederalTaxId, new { maxlength = 20 })
@Html.ValidationMessageFor(m => m.BusinessProfileModel.FederalTaxId)
</li>
<li>
@Html.LabelFor(m => m.BusinessProfileModel.BusinessStartDate)
<br />
@Html.TextBoxFor(m => m.BusinessProfileModel.BusinessStartDate, new { @type = "date", @class = "form-control datepicker", @Value = Model == null || Model.BusinessProfileModel.BusinessStartDate == null ? null : Model.BusinessProfileModel.BusinessStartDate.ToString("yyyy-MM-dd") })
@Html.ValidationMessageFor(m => m.BusinessProfileModel.BusinessStartDate)
</li>
<li>
@Html.LabelFor(m => m.BusinessProfileModel.Industry)
<br />
@Html.TextBoxFor(m => m.BusinessProfileModel.Industry, new { maxlength = 200, @class = "wide" })
@Html.ValidationMessageFor(m => m.BusinessProfileModel.Industry)
</li>
<li>
@Html.LabelFor(m => m.BusinessProfileModel.Sector)
<br />
@Html.TextBoxFor(m => m.BusinessProfileModel.Sector, new { maxlength = 200, @class = "wide" })
@Html.ValidationMessageFor(m => m.BusinessProfileModel.Sector)
</li>
<li>
@Html.LabelFor(m => m.BusinessProfileModel.StateOfFormation)
<br />
@Html.DropDownListFor(m => m.BusinessProfileModel.StateOfFormation, new SelectList(ViewBag.States, "Value", "Text"), "Select State", htmlAttributes: new { @class = "form-control", id = "StateOfFormationList" })
@Html.ValidationMessageFor(m => m.BusinessProfileModel.StateOfFormation)
</li>
<li>
@Html.LabelFor(m => m.BusinessProfileModel.EmployeeCount)
<br />
@Html.TextBoxFor(m => m.BusinessProfileModel.EmployeeCount, new { @type = "number", @class = "wide" })
@Html.ValidationMessageFor(m => m.BusinessProfileModel.EmployeeCount)
</li>
<li>
@Html.LabelFor(m => m.BusinessProfileModel.BusinessStructure)
<br />
@Html.DropDownListFor(m => m.BusinessProfileModel.BusinessStructure, new SelectList(ViewBag.BusinessTypeList, "Value", "Text"), "Select Business Structure", htmlAttributes: new { @class = "form-control", id = "BusinessStructureList" })
@Html.ValidationMessageFor(m => m.BusinessProfileModel.BusinessStructure)
</li>
</ol>
</fieldset>
</div>
}
_BusinessFinancial.cshtml
@using Kendo.Mvc.UI
@model Reverberate.BLL.Model.Form.Application.BusinessOnboarding.BusinessOnboardingModel
<h2>Business Financial</h2>
<div style="width: 90%; border: 1px solid silver" id="BusinessInfoEntry">
<fieldset>
<legend></legend>
<ol>
<li>
@Html.LabelFor(m => m.BusinessFinancialModel.CreditCardProcessor)
@Html.TextBoxFor(m => m.BusinessFinancialModel.CreditCardProcessor, new { maxlength = 200, @class = "wide" })
@Html.ValidationMessageFor(m => m.BusinessFinancialModel.CreditCardProcessor)
</li>
<li>
@Html.LabelFor(m => m.BusinessFinancialModel.CreditCardMonthlyVolume)
@Html.TextBoxFor(m => m.BusinessFinancialModel.CreditCardMonthlyVolume, new { maxlength = 20 })
@Html.ValidationMessageFor(m => m.BusinessFinancialModel.CreditCardMonthlyVolume)
</li>
<li>
@Html.LabelFor(m => m.BusinessFinancialModel.GrossMonthlySales)
@Html.TextBoxFor(m => m.BusinessFinancialModel.GrossMonthlySales, new { @type = "date", @class = "form-control datepicker", @Value = Model == null || Model.BusinessProfileModel.BusinessStartDate == null ? null : Model.BusinessProfileModel.BusinessStartDate.ToString("yyyy-MM-dd") })
@Html.ValidationMessageFor(m => m.BusinessFinancialModel.GrossMonthlySales)
</li>
<li>
@Html.LabelFor(m => m.BusinessFinancialModel.AnnualRevenue)
@Html.TextBoxFor(m => m.BusinessFinancialModel.AnnualRevenue, new { maxlength = 200, @class = "wide" })
@Html.ValidationMessageFor(m => m.BusinessFinancialModel.AnnualRevenue)
</li>
</ol>
</fieldset>
<br />
</div>
here are the three models
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Reverberate.BLL.Model.Form.Application.BusinessOnboarding { public class BusinessOnboardingModel { public BusinessProfileModel BusinessProfileModel { get; set; } public BusinessFinancialModel BusinessFinancialModel { get; set; } } }
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Reverberate.BLL.Model.Form.Application.BusinessOnboarding { public class BusinessProfileModel { public BusinessProfileModel() { } [Required(ErrorMessage = "The business name is required.")] [DisplayName("*Business Name")] [StringLength(250)] public string BusinessName { get; set; } [DisplayName("*Federal Tax Id / SSN")] [StringLength(15, ErrorMessage = "Please enter a valid federal tax id or SSN")] [Required(ErrorMessage = "Please enter the federal tax id or SSN")] public string FederalTaxId { get; set; } [DisplayName("*Business Start Date")] [Required(ErrorMessage = "Please enter the business start date")] public DateTime BusinessStartDate { get; set; } [Required(ErrorMessage = "The industry is required.")] [DisplayName("*Industry")] [StringLength(500)] public string Industry { get; set; } [Required(ErrorMessage = "The sector is required.")] [DisplayName("*Sector")] [StringLength(500)] public string Sector { get; set; } [DisplayName("*State of Formation")] [Validation.InputValidation.ValidState(ErrorMessage = "This does not appear to be a valid US State.")] [Required(ErrorMessage = "The State of Formation is required.")] public string StateOfFormation { get; set; } [DisplayName("*No of Employees")] [Validation.InputValidation.ValidState(ErrorMessage = "Number of Employees.")] [Required(ErrorMessage = "Please Supply the number of employees.")] public int EmployeeCount { get; set; } [Validation.InputValidation.ValidBusinessType(ErrorMessage = "Please enter a valid business structure")] [Required(ErrorMessage = "The business structure required.")] [DisplayName("*Business Structure")] public string BusinessStructure { get; set; } } }
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Reverberate.BLL.Model.Form.Application.BusinessOnboarding { public class BusinessProfileModel { public BusinessProfileModel() { } [Required(ErrorMessage = "The business name is required.")] [DisplayName("*Business Name")] [StringLength(250)] public string BusinessName { get; set; } [DisplayName("*Federal Tax Id / SSN")] [StringLength(15, ErrorMessage = "Please enter a valid federal tax id or SSN")] [Required(ErrorMessage = "Please enter the federal tax id or SSN")] public string FederalTaxId { get; set; } [DisplayName("*Business Start Date")] [Required(ErrorMessage = "Please enter the business start date")] public DateTime BusinessStartDate { get; set; } [Required(ErrorMessage = "The industry is required.")] [DisplayName("*Industry")] [StringLength(500)] public string Industry { get; set; } [Required(ErrorMessage = "The sector is required.")] [DisplayName("*Sector")] [StringLength(500)] public string Sector { get; set; } [DisplayName("*State of Formation")] [Validation.InputValidation.ValidState(ErrorMessage = "This does not appear to be a valid US State.")] [Required(ErrorMessage = "The State of Formation is required.")] public string StateOfFormation { get; set; } [DisplayName("*No of Employees")] [Validation.InputValidation.ValidState(ErrorMessage = "Number of Employees.")] [Required(ErrorMessage = "Please Supply the number of employees.")] public int EmployeeCount { get; set; } [Validation.InputValidation.ValidBusinessType(ErrorMessage = "Please enter a valid business structure")] [Required(ErrorMessage = "The business structure required.")] [DisplayName("*Business Structure")] public string BusinessStructure { get; set; } } }
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Reverberate.BLL.Model.Form.Application.BusinessOnboarding { public class BusinessFinancialModel { public BusinessFinancialModel() { } [DisplayName("Credit Card Processor")] [StringLength(250)] public string CreditCardProcessor { get; set; } [DisplayName("Credit Card Monthly Volume")] public decimal CreditCardMonthlyVolume { get; set; } [DisplayName("Gross Monthly Sales")] public decimal GrossMonthlySales { get; set; } [DisplayName("AnnualRevenue")] public decimal AnnualRevenue { get; set; } } }
As recommend in my other question here: I have created a sample project. In this project there is an Index.cshtml which has my original structure. With regards to the index.cshtml there are two things, one - I am not sure why validation doesn't occur on the original page load, I have to reload the page to force page validation and also on the done command there isn't any validation occuring.
I created ind.cshtml when I trying the recomemnded solution for the question here: https://www.telerik.com/forums/using-wizard---how-do-you-validate-a-form-when-step-includes-partial-view#5789804 and I am getting `
Severity Code Description Project File Line Suppression State
Error CS1660 Cannot convert lambda expression to type 'string' because it is not a delegate type 6_Views_Home_Index2.cshtml M:\Code\Development\WizardPartialExample\WizardPartialExample\WizardPartialExample\Views\Home\Index2.cshtml 19 Active`