Skip to content

Instantly share code, notes, and snippets.

@robdmoore
Created October 2, 2013 14:12
Show Gist options
  • Save robdmoore/6794397 to your computer and use it in GitHub Desktop.
Save robdmoore/6794397 to your computer and use it in GitHub Desktop.
Multi-step form controller code idea
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Web.Mvc;
using Newtonsoft.Json;
namespace Web.Controllers
{
public class RegistrationController : Controller
{
private const string SerialisedValuesKey = "SerialisedValues";
private const string ValidationHashKey = "ValidationHash";
private const string SecretSalt = "drthSRT$%^7#fgh;awGSEER";
private static readonly LinkedList<RegistrationFormSteps> FormSteps = new LinkedList<RegistrationFormSteps>(Enums.Enumerate<RegistrationFormSteps>());
// This isn't used below, but it contains some logic around what might be done for the hidden field tracking.
private TReturn SaveFormStateAndReturn<TReturn>(Action<RegistrationFormViewModel> modifier, Func<RegistrationFormViewModel, TReturn> returnAccessor)
{
var vm = new RegistrationFormViewModel();
var serialised = Request.Params[SerialisedValuesKey];
if (!string.IsNullOrEmpty(serialised))
{
var expectedHash = (serialised + SecretSalt).ToSha1Hash();
var hash = Request.Params[ValidationHashKey];
if (hash != expectedHash)
throw new InvalidDataException("User tampered with registration submission");
vm = JsonConvert.DeserializeObject<RegistrationFormViewModel>(serialised);
}
modifier(vm);
ViewData[SerialisedValuesKey] = JsonConvert.SerializeObject(vm);
ViewData[ValidationHashKey] = (ViewData[SerialisedValuesKey] + SecretSalt).ToSha1Hash();
return returnAccessor(vm);
}
public ActionResult Step1()
{
return View();
}
[HttpPost]
public ActionResult Step1(Step1ViewModel vm)
{
return FormStep(RegistrationFormSteps.Step1);
}
[HttpPost]
public ActionResult Step2(Step2ViewModel vm)
{
return FormStep(RegistrationFormSteps.Step2);
}
private ActionResult FormStep(RegistrationFormSteps currentStep)
{
if (!ModelState.IsValid)
return View(currentStep.ToString(), GetViewModel(currentStep));
SaveFormState(currentStep);
var stepToShow = default(RegistrationFormSteps?);
if (currentStep != FormSteps.First() && Request.Params["previous"] != null)
stepToShow = GetPreviousStep(currentStep);
if (currentStep != FormSteps.Last() && (Request.Params["next"] != null))
stepToShow = GetNextStep(currentStep);
if (!stepToShow.HasValue && currentStep == FormSteps.Last())
return ProcessRegistration();
return View(stepToShow.ToString(), GetViewModel(stepToShow));
}
}
public enum RegistrationFormSteps
{
Step1,
Step2
}
public class RegistrationFormViewModel
{
public Step1ViewModel Step1 { get; set; }
public Step2ViewModel Step2 { get; set; }
}
public class Step1ViewModel
{
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
}
public class Step2ViewModel
{
[Required]
public string EmailAddress { get; set; }
[Required]
public string Address { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment