在ASP.NET MVC5中基于拆分视图模型的多步骤注册表单中实现Jquery Ajax

在ASP.NET MVC5中基于拆分视图模型的多步骤注册表单中实现Jquery Ajax,jquery,ajax,asp.net-mvc,wizard,multi-step,Jquery,Ajax,Asp.net Mvc,Wizard,Multi Step,我使用了Darin Dimitrov的方法制作了一个多步骤的寄存器表单,经过解释,效果很好。 现在,我想使用jquery ajax而不是Html.Beginform()来处理“上一步”、“下一步”和“完成”按钮的提交事件 注: 我将MVC5与.NET4.5.2一起使用 在我的第二步viewmodel中有fileupload和datetime属性 这是我的视图模型 [Serializable] public class RegisterWizardViewModel { publi

我使用了Darin Dimitrov的方法制作了一个多步骤的寄存器表单,经过解释,效果很好。 现在,我想使用jquery ajax而不是Html.Beginform()来处理“上一步”、“下一步”和“完成”按钮的提交事件

注:

  • 我将MVC5与.NET4.5.2一起使用
  • 在我的第二步viewmodel中有fileupload和datetime属性
这是我的视图模型

[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; }
    }

}
我在registerwizard索引视图中使用了这个jquery代码通过ajax调用提交

@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>

}

好的,如果有人面临这个问题并且可能有类似的问题,我将解释我的解决方法。
识别已提交表单的按钮的主要问题:
我添加了一个名为button的隐藏输入,并通过每个按钮上的点击事件jquery动态更改其名称,最后修改了我的控制器以从请求中获取此值。
以下是保存整个表单和我的控制器的后期操作的局部视图。

@using Microsoft.Web.Mvc
@model Models.RegisterWizardViewModel

@{
    var currentStep = Model.Steps[Model.CurrentStepIndex];
}

@using (Html.BeginForm("Index", "RegisterWizard", FormMethod.Post, new { @class = "form-horizontal", role = "form", enctype = "multipart/form-data", @id = "mainRWF" }))
{
    @Html.AntiForgeryToken()
    @Html.Hidden("Button")
    @Html.Serialize("wizard", Model)
    @Html.Hidden("StepType", Model.Steps[Model.CurrentStepIndex].GetType())
    @Html.EditorFor(x => currentStep, null, "")

    if (Model.CurrentStepIndex > 0)
        {
           <div >
              <input type="submit"  value="Previous" name="prev" />
           </div>
        }

    if (Model.CurrentStepIndex < Model.Steps.Count - 1)
        {
          <div >
            <input type="submit"  value="Next" name="next" />
          </div>
        }
    else
        {
          <div >
            <input type="submit"  value="Submit" name="finish"/>
          </div>
        }
 }
@使用Microsoft.Web.Mvc
@model Models.RegisterWizardViewModel
@{
var currentStep=Model.Steps[Model.CurrentStepIndex];
}
@使用(Html.BeginForm(“Index”、“RegisterWizard”、FormMethod.Post、new{@class=“form horizontal”、role=“form”、enctype=“multipart/form data”、@id=“mainRWF”}))
{
@Html.AntiForgeryToken()
@Html.Hidden(“按钮”)
@序列化(“向导”,模型)
@Html.Hidden(“StepType”,Model.Steps[Model.CurrentStepIndex].GetType())
@EditorFor(x=>currentStep,null,“”)
如果(Model.CurrentStepIndex>0)
{
}
if(Model.CurrentStepIndex

[ValidateAntiForgeryToken]
公共异步任务索引([反序列化]RegisterWizardViewModel向导,RegisterWizardViewModel.IStepViewModel步骤)
{
wizard.Steps[wizard.CurrentStepIndex]=步骤;
if(ModelState.IsValid)
{
if(Request.Form.GetValues(“按钮”)包含(“下一步”))
{
向导.CurrentStepIndex++;
}
else if(Request.Form.GetValues(“按钮”)包含(“prev”))
{
wizard.CurrentStepIndex--;
}
其他的
{
//用收到的值做一些事情
返回Json(新的{response=“Success”});
}
}
else if(Request.Form.GetValues(“按钮”)包含(“prev”))
{
//即使验证失败,我们也允许用户
//导航到前面的步骤
wizard.CurrentStepIndex--;
}
如果(!ModelState.IsValid),则为else
{
//如果我们走到了这一步,有些东西失败了,那么将它插入ajax的success func的html()中,重新显示有错误的表单
返回PartialView(“\u IndexPartial”,向导);
}
//返回下一步
返回PartialView(“\u IndexPartial”,向导);
}

显然我在上传文件时遇到了问题!并选择html5 formData作为ajax完成调用按钮的数据选项来处理上传。
为了使解决方案更好,我将对该解决方案发表评论

您可以使用@Ajax。BeginForm@BonMacalindong谢谢你的建议,但考虑到对Ajax调用的完全控制,我更喜欢使用jQueryAjax
  @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>


        }
    }
@using Microsoft.Web.Mvc
@model Models.RegisterWizardViewModel

@{
    var currentStep = Model.Steps[Model.CurrentStepIndex];
}

@using (Html.BeginForm("Index", "RegisterWizard", FormMethod.Post, new { @class = "form-horizontal", role = "form", enctype = "multipart/form-data", @id = "mainRWF" }))
{
    @Html.AntiForgeryToken()
    @Html.Hidden("Button")
    @Html.Serialize("wizard", Model)
    @Html.Hidden("StepType", Model.Steps[Model.CurrentStepIndex].GetType())
    @Html.EditorFor(x => currentStep, null, "")

    if (Model.CurrentStepIndex > 0)
        {
           <div >
              <input type="submit"  value="Previous" name="prev" />
           </div>
        }

    if (Model.CurrentStepIndex < Model.Steps.Count - 1)
        {
          <div >
            <input type="submit"  value="Next" name="next" />
          </div>
        }
    else
        {
          <div >
            <input type="submit"  value="Submit" name="finish"/>
          </div>
        }
 }
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Index([Deserialize]RegisterWizardViewModel wizard, RegisterWizardViewModel.IStepViewModel step)
    {
       wizard.Steps[wizard.CurrentStepIndex] = step;

        if (ModelState.IsValid)
        {
            if (Request.Form.GetValues("Button").Contains("next"))
            {
                wizard.CurrentStepIndex++;

            }
            else if (Request.Form.GetValues("Button").Contains("prev"))
            {
                wizard.CurrentStepIndex--;
            }
            else
            {
                //Do stuff with received values
                return Json(new { response = "Success" });

            }

       }
       else if (Request.Form.GetValues("Button").Contains("prev"))
       {
           // Even if validation failed we allow the user to
           // navigate to previous steps
           wizard.CurrentStepIndex--;
       }
       else if (!ModelState.IsValid)
       {
           // If we got this far, something failed, redisplay form with errors by inserting this into html() of success func of ajax
           return PartialView("_IndexPartial", wizard);
       }

    // return next step 
    return PartialView("_IndexPartial", wizard);

}