J'ai utilisé l'approche de Darin-Dimitrov pour créer un formulaire de registre à plusieurs étapes qui est expliqué Here et fonctionne correctement. Maintenant, je veux gérer les événements de soumission pour les boutons Précédent, Suivant et Terminer en utilisant jquery ajax au lieu de Html.Beginform().Implémentation de Jquery Ajax dans des formulaires de registre multi-étapes basés sur des modèles de vue éclatés dans ASP.NET MVC5
Notes:
- J'utilise MVC 5 avec .NET 4.5.2
- J'ai fileUpload et les propriétés datetime dans mon deuxième viewmodel étape.
Voici mon viewmodel
[Serializable]
public class RegisterWizardViewModel
{
public int CurrentStepIndex { get; set; }
public IList<IStepViewModel> Steps { get; set; }
public void Initialize()
{
Steps = typeof(IStepViewModel)
.Assembly
.GetTypes()
.Where(t => !t.IsAbstract && typeof(IStepViewModel).IsAssignableFrom(t))
.Select(t => (IStepViewModel)Activator.CreateInstance(t))
.ToList();
}
public interface IStepViewModel
{
}
[Serializable]
public class RegisterStep1ViewModel : IStepViewModel
{
[Required]
[EmailAddress]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
public string Password { get; set; }
[DataType(DataType.Password)]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
[Serializable]
public class RegisterStep2ViewModel : IStepViewModel
{
[Display(Name = "FirstName", ResourceType = typeof(Resources.Resources))]
public string FirstName { get; set; }
[Display(Name = "LastName", ResourceType = typeof(Resources.Resources))]
public string LastName { get; set; }
[NonSerialized]
private HttpPostedFileBase _file;
public HttpPostedFileBase File
{
get
{
return _file;
}
set
{
_file = value;
}
}
[Display(Name = "BirthDay", ResourceType = typeof(Resources.Resources))]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy/MM/dd}", ApplyFormatInEditMode = true)]
public DateTime? BirthDay { get; set; }
[Display(Name = "NationalCode", ResourceType = typeof(Resources.Resources))]
public int NationalCode { get; set; }
[Display(Name = "Gender", ResourceType = typeof(Resources.Resources))]
public bool IsMale { get; set; }
[Display(Name = "Mobile", ResourceType = typeof(Resources.Resources))]
public string MobilePhone { get; set; }
[Display(Name = "Country", ResourceType = typeof(Resources.Resources))]
public string Country { get; set; }
[Display(Name = "Address", ResourceType = typeof(Resources.Resources))]
public string Address { get; set; }
[MustBeTrue]
public bool CaptchaValid { get; set; }
}
}
Voici mon contrôleur
[AllowAnonymous]
public ActionResult Index()
{
var wizard = new RegisterWizardViewModel();
wizard.Initialize();
return View(wizard);
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Index([Deserialize] RegisterWizardViewModel wizard, RegisterWizardViewModel.IStepViewModel step)
{
wizard.Steps[wizard.CurrentStepIndex] = step;
if (ModelState.IsValid)
{
if (!string.IsNullOrEmpty(Request["next"]))
{
wizard.CurrentStepIndex++;
}
else if (!string.IsNullOrEmpty(Request["prev"]))
{
wizard.CurrentStepIndex--;
}
else
{
var model1 = wizard.Steps[0] as RegisterWizardViewModel.RegisterStep1ViewModel;
var model2 = wizard.Steps[1] as RegisterWizardViewModel.RegisterStep2ViewModel;
var uploadedFile = (model2.File != null && model2.File.ContentLength > 0) ? new byte[model2.File.InputStream.Length] : null;
if (uploadedFile != null)
{
model2.File.InputStream.Read(uploadedFile, 0, uploadedFile.Length);
}
var user = new ApplicationUser { UserName = model1.Email, Email = model1.Email, FirstName = model2.FirstName, LastName = model2.LastName, Image = uploadedFile , BirthDay = model2.BirthDay, IsMale = model2.IsMale, NationalCode = model2.NationalCode, MobilePhone = model2.MobilePhone, Country = model2.Country, Address = model2.Address };
var result = UserManager.Create(user, model1.Password);
if (result.Succeeded)
{
SignInManager.SignIn(user, isPersistent: false, rememberBrowser: false);
return Json(new { response = "Redirect", url = Url.Action("Index", "Home") });
}
else
{
AddErrors(result);
}
}
}
else if (!string.IsNullOrEmpty(Request["prev"]))
{
wizard.CurrentStepIndex--;
}
return View(wizard);
}
Et je l'ai utilisé ce code jquery pour soumettre via un appel ajax dans mon index des registerwizard.
@section scripts{
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<script type="text/javascript">
$(function() {
$('form').on("submit", function (e) {
e.preventDefault;
if ($(this).valid()) {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
window.location = result.url;
}
});
}
return false;
});
});
</script>
}
Eh bien maintenant, le problème est le contrôleur ne marche pas reconnaître que le bouton a été pressé et Request["next"]
ou Request["prev"]
revenir toujours nul et en cas d'état de modèle étant valable pour la première étape (e-mail, passer, confirmpass), le contrôleur va directement à créer un utilisateur. il vaut la peine de mentionner que puisque je ne pouvais pas arriver à la deuxième étape via l'appel ajax je ne sais pas si le téléchargement de fichiers et la propriété datetime envoyé au contrôleur sans aucun problème ou non.
Mise à jour:
est ici Index Voir
@using (Html.BeginForm("Index", "RegisterWizard", FormMethod.Post, new { @class = "form-horizontal", role = "form", enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
@Html.Serialize("wizard", Model)
@Html.Hidden("StepType", Model.Steps[Model.CurrentStepIndex].GetType())
@Html.EditorFor(x => currentStep, null, "")
if (Model.CurrentStepIndex > 0)
{
<div class="col-xs-9 col-sm-6 col-md-5 col-lg-5" style="padding-right:0px;">
<input type="submit" class="btn btn-default" value="Previous" name="prev" />
</div>
}
if (Model.CurrentStepIndex < Model.Steps.Count - 1)
{
<div class="col-xs-10 col-sm-8 col-md-6" style="">
<input type="submit" class="btn btn-default" value="Next" name="next" style="float:left;"/>
</div>
}
else
{
<div class="col-xs-3 col-sm-6 col-md-7 col-lg-7" style="padding-right:0px;">
<input type="submit" class="btn btn-default " value="Finish" name="finish" />
</div>
}
}
Vous pouvez utiliser @ Ajax.BeginForm –
@BonMacalindong merci pour votre suggestion mais compte tenu du contrôle total sur l'appel Ajax je préfère utiliser jquery Ajax –