MVC 5多重防伪代币AJAX

时间:2016-06-23 12:17:43

标签: jquery ajax asp.net-mvc post antiforgerytoken

我的问题是我有一个局部视图,其中包含一个充满下拉的形式。我正在使用AJAX动态更新下拉内容。一切正常,直到我实施Anti Forgery Tokens。在ajax帖子中序列化我的表单后,我正在使用_LoginPartial.cshtml表单中的防伪标记和我从_config.cshtml发布数据的表单中的防伪标记。这导致验证属性罐装帖子并阻止ajax工作。

我尝试了以下内容:

  1. 删除所有令牌,只需在_Layout.cshtml页面中放置一个令牌并引用ajax调用中的令牌即可。这适用于Ajax,但在提交表单后,我得到一个令牌未找到错误,因为令牌不在表单中。

  2. 然后我尝试使用AJAX发布表单并引用_Layout.cshtml视图中的单个标记。这将数据返回到ajax而不是我希望的整个视图。

  3. 我的问题是:

    1. 如何只将当前表单标记放入ajax post函数?
    2. 或者,有没有正确的方法来做我想做的事情?
    3. 我很确定有一种简单的方法可以解决这个问题,但我真的只是一个初学者,我正在努力找到自己的脚。任何帮助,将不胜感激。

      _LoginPartial.cshtml

      @using Microsoft.AspNet.Identity
      @using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
      {
      
          if (Request.IsAuthenticated)
          {
              <ul class="nav navbar-nav navbar-right">
                  <li>
                      @Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })
                  </li>
                  @if (User.IsInRole("admin"))
                  { 
                      <li>@Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li>
                  }
                  <li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>
              </ul>
          }
          else
          {
              <ul class="nav navbar-nav navbar-right">
                  @if (User.IsInRole("admin"))
                  {
                      <li>@Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li>
                  }
                  <li>@Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li>
              </ul>
          }
      

      _Layout.cshtml

       <!DOCTYPE html>
      <html>
      <head>
          <meta charset="utf-8" />
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>@ViewBag.Title - Doogies Website</title>
          @Styles.Render("~/Content/css")
          @Styles.Render("~/Content/themes/base/css")
          @Scripts.Render("~/bundles/modernizr")
          @Scripts.Render("~/bundles/jquery")
          @Scripts.Render("~/bundles/jqueryui")
          @Scripts.Render("~/bundles/jqueryval")
      </head>
      <body>
      
          @using (Html.BeginForm(null, null, FormMethod.Post, new { id = "_AFT"})) { @Html.AntiForgeryToken()}
      
          <div class="navbar navbar-inverse navbar-fixed-top">
              <div class="container">
                  <div class="navbar-header">
                      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                          <span class="icon-bar"></span>
                          <span class="icon-bar"></span>
                          <span class="icon-bar"></span>
                      </button>
                      @Html.ActionLink("Doogies Site", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
                  </div>
                  <div class="navbar-collapse collapse">
                      <ul class="nav navbar-nav">
                          <li>@Html.ActionLink("Home", "Index", "Home")</li>
                          <li>@Html.ActionLink("About", "About", "Home")</li>
                          <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                          <li>@Html.ActionLink("RTCG", "RTCG_Configurator", "Rtcg")</li>
                      </ul>
                      @Html.Partial("_LoginPartial")
                  </div>
              </div>
          </div>
      
          <div class="container body-content" >
              @RenderBody()
              <hr />
              <footer>
                  <p>&copy; @DateTime.Now.Year - Chris Duguid</p>
              </footer>
          </div>
      
      
          @Scripts.Render("~/bundles/bootstrap")
          @RenderSection("scripts", required: false)
      </body>
      </html>
      

      _config.cshtml (表单所在的部分视图)

      是的我知道表单没有提交信息。我正在尝试使用ajax进行提交。

      @model HomeWeb.Models.RtcgConfigurationModel
      
      @using (Html.BeginForm( new { enctype = "multipart/form-data" , id = "configform"}))
      {
          <div class="form-horizontal">
              <h3>Configure RTCG</h3>
              <hr />
              @Html.ValidationSummary(true)
      
      
              <div class="form-group">
                  @Html.LabelFor(model => model.RtcgCabinetType, "Cabinet Type", new { @class = "control-label col-md-5" })
                  <div class="col-md-7">
                      @Html.DropDownListFor(model => Model.RtcgCabinetType, Model.Cabinets, new { onchange = "changed();" })
                      @Html.ValidationMessageFor(model => model.RtcgCabinetType)
                  </div>
              </div>
              <div class="form-group">
                  @Html.LabelFor(model => model.RtcgAdaptorType, "Adaptor Type", new { @class = "control-label col-md-5" })
                  <div class="col-md-7">
                      @Html.DropDownListFor(model => Model.RtcgAdaptorType, Model.Adaptors, new { onchange = "changed();" })
                      @Html.ValidationMessageFor(model => model.RtcgAdaptorType)
                  </div>
              </div>
              <div class="form-group">
                  @Html.LabelFor(model => model.RtcgQtyAdaptors, "Adaptor Qty.", new { @class = "control-label col-md-5" })
                  <div class="col-md-7">
                      @Html.DropDownListFor(model => Model.RtcgQtyAdaptors, Model.AdaptorQtys, new { onchange = "changed();" })
                      @Html.ValidationMessageFor(model => model.RtcgQtyAdaptors)
                  </div>
              </div>
      
              <div class="form-group">
                  @Html.LabelFor(model => model.RtcgTerminationMethod, "Termination", new { @class = "control-label col-md-5" })
                  <div class="col-md-7">
                      @Html.DropDownListFor(model => Model.RtcgTerminationMethod, Model.TerminationMethods)
                      @Html.ValidationMessageFor(model => model.RtcgTerminationMethod)
                  </div>
              </div>
              <div class="form-group">
                  @Html.LabelFor(model => model.RtcgFaceplateStyle, "Faceplate Style", new { @class = "control-label col-md-5" })
                  <div class="col-md-7">
                      @Html.DropDownListFor(model => Model.RtcgFaceplateStyle, Model.FacePlateStyles)
                      @Html.ValidationMessageFor(model => model.RtcgFaceplateStyle)
                  </div>
              </div>
              <div class="form-group">
                  @Html.LabelFor(model => model.RtcgScreenPrinting, "Screenprinting", new { @class = "control-label col-md-5" })
                  <div class="col-md-7">
                      @Html.DropDownListFor(model => Model.RtcgScreenPrinting, Model.ScreenPrintOptions)
                      @Html.ValidationMessageFor(model => model.RtcgScreenPrinting)
                  </div>
              </div>
              <div class="form-group">
                  @Html.LabelFor(model => model.RtcgApplication, "Fibre Type", new { @class = "control-label col-md-5" })
                  <div class="col-md-7">
                      @Html.DropDownListFor(model => Model.RtcgApplication, Model.Applications)
                      @Html.ValidationMessageFor(model => model.RtcgApplication)
                  </div>
              </div>
              <div class="form-group">
                  @Html.LabelFor(model => model.RtcgVerminProof, "Vermin Proof", new { @class = "control-label col-md-5" })
                  <div class="col-md-7">
                      @Html.DropDownListFor(model => Model.RtcgVerminProof, Model.VerminProofing)
      
                      @Html.ValidationMessageFor(model => model.RtcgVerminProof)
                  </div>
              </div>
              <div class="form-group">
                  <div class="col-md-offset-5 col-md-10">
                      <input  value="Get Quotation" class="btn btn-primary" style="float: none" onclick="submitajax()" />
                  </div>
              </div>
          </div>
      }
      
      <script type="text/javascript">
          function changed() {
              var tokensource = $('#_AFT');
              var formData = $('form').serialize();
              var token = $('input[name="__RequestVerificationToken"]', tokensource).val();
              $.extend(formData, { '__RequestVerificationToken': token });
              $.ajax({
                 url: '/Rtcg/Ajax_DropdownChanged',
                  type: "POST",
                  data: formData,
                  success: function (result) {
                      $('#config-form').html(result);
                  },
              })
          }
      
          function submitajax() {
              var tokensource = $('#_AFT');
              var formData = $('form').serialize();
              var token = $('input[name="__RequestVerificationToken"]', tokensource).val();
              $.extend(formData, { '__RequestVerificationToken': token });
              $.ajax({
                  url: '/Rtcg/updateDB',
                  type: "POST",
                  data: formData,
                  success: function (result) {
      
                  },
              })
          }
      </script>
      

      RTCG_Configurator (&#39;索引&#39;视图在呈现正文时显示)

      @model HomeWeb.Models.RtcgConfigurationModel
      @{
          ViewBag.Title = "RTCG Configurator";
      }
      
      <section >
          <div class="col-md-6 pv" id="config-form">
              @Html.Partial("_config")
          </div>    
          <div class="col-md-6" >
          </div> 
      </section>
      <div style="clear:both">
          <br /><br />
          <p><a href="~/Home/Index" class="btn btn-primary btn-sm">&laquo; Back Home </a></p>
      </div>
      

      控制器 - Ajax_DropdownChanged()

      // POST: handle dropdown changes from Ajax
            [HttpPost]
            [ValidateAntiForgeryToken]
              public ActionResult Ajax_DropdownChanged(RtcgConfigurationModel formData)
              {  
                  //handle 'postback' displaying the fields. 
                  if (ModelState.IsValid)
                  { 
                      RtcgConfigurationModel model = new RtcgConfigurationModel();
                      using (var db = new ApplicationDbContext())
                      {
                          model.Cabinets = DisplayElement.Cabinets(formData);
                          model.Adaptors = DisplayElement.Adaptors(formData);
                          model.AdaptorQtys = DisplayElement.AdaptorQuantities(formData);
                          model.TerminationMethods = DisplayElement.Termination(formData);
                          model.FacePlateStyles = DisplayElement.Faceplates(formData);
                          model.ScreenPrintOptions = DisplayElement.ScreenPrinting(formData);
                          model.Applications = DisplayElement.Application(formData);
                          model.VerminProofing = DisplayElement.VerminProof(formData);   
                      }
                      return PartialView("_config", model);
                      //return View(model);
                  }
                  else
                  {
                      return PartialView();
                  }
              }
      

2 个答案:

答案 0 :(得分:1)

您对var formData = $('form').serialize();的使用将序列化视图中所有表单中所有表单控件的值,包括防伪令牌,这就是您提交多个令牌的原因。

确保每个表单都有id属性,然后仅使用id="configform"在表单中提交值(和令牌),使用

var formData = $('#configform').serialize();

另请注意,您不需要

var token = $('input[name="__RequestVerificationToken"]', tokensource).val();
$.extend(formData, { '__RequestVerificationToken': token });

因为.serialize()已经包含令牌的名称/值对(假设@Html.AntiForgeryToken()标签之间包含<form>

答案 1 :(得分:0)

问题是新手的错误。

正如斯蒂芬在回答中所说的那样。我没有特别谈到这个表格。添加$('#configform')。serialize()就可以了。

我将令牌添加到每个表单并将其从布局页面中删除。

现在是我的ajax代码。

<script type="text/javascript">
    function changed() {
        $.ajax({
           url: '/Rtcg/Ajax_DropdownChanged',
            type: "POST",
            data: $('#configform').serialize(),
            success: function (result) {
                $('#config-form').html(result);
            },
        })
    }
</script>
斯蒂芬应该戴着斗篷。